Step HTTP (:http)
Quick Answer
Use this reference for the :http step schema, required fields, persistence behavior, and large-payload safety defaults.
Use for HTTP APIs. Prefer :connection with a :http-api slot.
Canonical Shape
Core fields:
| Field | Type | Required | Notes |
|---|---|---|---|
:connection | keyword/string | Yes* | Slot or connection id |
:url | string | Yes* | Full URL (ad hoc request) |
:path | string | No | Appended to connection base URL |
:method | keyword | No | :get, :post, :put, :patch, :delete |
:headers | map | No | Header map |
:query | map | No | Query params |
:json | map | No | JSON body |
:form | map | No | URL-encoded form body |
:multipart | vector | No | Multipart parts |
:body | any | No | Raw body |
:body-from-ref | map | No | Load body from a blob ref, resource URI, or canonical resource-ref |
:content-type | keyword/string | No | Body content type |
:accept | keyword/string | No | Accept header helper (:json, :xml, :text) or a normal MIME header string such as "application/vnd.api+json" |
:response-as | keyword | No | :auto, :json, :jsonl, :sse, :text, :bytes, :edn, :xml, :yaml |
:include-headers | vector<string/keyword> | No | Return only selected response headers, e.g. ["location"] |
:parser-fn | form | No | Custom parse function |
:template | keyword | No | :http-request template id |
:data | map | No | Template variables |
:auth | map | No | Step-level auth (if not from connection) |
:client-opts | map | No | Transport overrides |
:timeout | int | No | Timeout seconds (common option) |
:retry | map | No | Retry policy (common option) |
:persist | map | No | Persist response refs; choose retained default for durable artifacts or :tier :ephemeral for temporary streamed HTTP blobs |
:metering | map | No | Advisory fixed API/tool cost for run cost estimates |
:auto-search-index? | boolean | No | Control automatic page indexing for searchable HTTP GET results |
* Provide either :connection or :url.
Limits And Behavior
Request and parsing:
- Prefer one body mode:
:json,:form,:multipart,:body, or:body-from-ref. If both:jsonand:bodyare set,:jsonwins. :acceptaccepts shortcuts such as:jsonor"json"and full MIME header values such as"application/json;q=0.9,*/*;q=0.1".:response-as :autouses responseContent-Typeto choose:json,:jsonl,:sse,:text, or:bytes.:response-as :sseis for finitetext/event-streamresponses, not indefinite listeners.:queryvalues must be scalar. Join repeated values into the API's expected string form before passing them.
Persistence and size:
- Inline results are intended to stay under
512 KB; larger or binary payloads need:persist {:type :blob ...}. - If payload size is unknown (exports, pagination, generated files), add
:persistfrom the start. - Use
:tier :ephemeralfor temporary streamed HTTP downloads, exports, generated media, and response blobs. - Keep the retained default for user-facing or durable artifacts.
- For binary downloads, set
:response-as :bytesand blob:persist; Breyta can stream the response directly to storage. - Persisted blob results include
:uri/:resource-urifor resource APIs/UI and:blob-reffor downstream blob loading. - Downstream function steps can hydrate persisted HTTP responses with
:input {:resp http-step-result}and:load [:resp]. :client-opts {:max-response-bytes ...}caps both buffered responses and streamed blob persists. If omitted, streamed blob persists use the persist-tier cap.- Binary blobs are searchable by metadata/path context. Add
:persist {:search-index {...}}when you have trusted domain text for a binary file.
Storage paths:
:persist :pathand:filenamesupport{{...}}interpolation from step params and runtime fields.:persist :pathmust be relative; do not include a leading/or...- Use
:persist {:type :blob :path ... :filename ...}for runtime-managed paths. - Use
:persist {:type :blob :slot <slot> ...}when installers should control the storage binding/root. :persist :slotmust refer to a local:blob-storagerequirement such as:archive.
Redirects, templates, auth:
- Automatic redirect following is disabled for SSRF protection.
- A
3xxresult is marked with:redirect? trueand:redirect-locationwhenLocationis present. - For public document systems, request
["location"], check:redirect?, and make a second explicit:httpstep to the returned URL. - Templates cover request shape; step-level keys like
:persiststay on the step. - Auth must use secret references. Inline tokens or API keys are rejected.
- Prefer connection auth, or use step-level auth with
:auth {:type :bearer|:token|:api-key|:aws-sigv4 :secret-ref :my-secret}. - DRF-style APIs can use
:auth {:type :token ...}forAuthorization: Token <key>or:auth {:type :bearer :prefix "Token" ...}. - Header API-key auth can use
:auth {:type :api-key :location :header :param-name "x-api-key" ...}. - AWS APIs that require Signature Version 4 can use
:auth {:type :aws-sigv4 :secret-ref :aws-creds :region "us-east-1" :service "bedrock"}. The secret should holdaccess-key-id,secret-access-key, and optionalsession-token. - Custom headers may reference secrets directly:
:headers {"x-api-key" {:secret-ref :shotstack-key}}. - Use
:meteringwhen this HTTP call has a known fixed per-request cost.
Large uploads:
- Prefer
:body-from-refand multipart:from-reffor uploads from prior persisted artifacts or resource-picker-selected files. - Supported refs: persisted blob envelopes,
{:blob-ref ...}, rawres://URIs,{:ref uri},{:resource-uri uri}, and resource-picker maps. - Resource URIs used with
:body-from-ref/:from-refmust point at blob-backed resources in the same workspace.
Automatic Page Indexing
By default, safe page-like GET responses are copied into retained workspace storage and indexed for :search.
By default, auto-indexing runs only when all of these are true:
- The request succeeds with an HTTP status below
400 - The method is
GET - The step does not already set
:persist - The response body is text or bytes that can be read as text
- The response content type is
text/html,application/xhtml+xml,text/markdown,text/x-markdown, or article-liketext/plain - Workspace storage and the resource store are available
- The request is safe to index by default: no resolved auth, no sensitive auth headers, and no sensitive query params
Plain text counts as article-like when the URL path looks like content, such as /article, /blog, /post, /news, or /docs.
When the page is indexed, the step result includes:
{:persisted-blob {...}
:auto-search-indexed? true}
Breyta stores raw page bytes as a retained blob and adds bounded search text. Use explicit :persist {:search-index ...} for curated title, tags, source label, or search text.
Use :auto-search-index? false to opt out:
(flow/step :http :read-page
{:url "https://example.com/article"
:method :get
:response-as :text
:auto-search-index? false})
Use :auto-search-index? true only when an authenticated or sensitive-looking response should become searchable workspace data. Other guards still apply.
(flow/step :http :read-private-doc
{:connection :docs
:path "/internal/article"
:method :get
:response-as :text
:auto-search-index? true})
If you set explicit :persist, that config owns persistence and search-index metadata. Automatic page indexing will not add a second blob.
Breyta Public Docs Retrieval
Use :http when a flow needs to retrieve Breyta public docs at runtime. The :search step is workspace-scoped and does not include a docs target.
Declare the docs API as a connection slot:
{:requires [{:slot :breyta-docs
:type :http-api
:label "Breyta docs API"
:base-url "https://flows.breyta.ai"
:auth {:type :none}}]}
Search pages first, then fetch the selected page as markdown:
'(let [doc-search (flow/step :http :find-breyta-docs
{:connection :breyta-docs
:path "/api/docs/pages"
:method :get
:query {:query (:question (flow/input))
:limit 5
:with-snippets "true"}
:response-as :json})
first-page (first (get-in doc-search [:data :pages]))
slug (:slug first-page)
markdown (when slug
(flow/step :http :read-breyta-doc
{:connection :breyta-docs
:path (str "/api/docs/pages/" slug)
:method :get
:query {:format "md"}
:response-as :text}))]
{:pages (get-in doc-search [:data :pages])
:selected-slug slug
:markdown markdown})
For direct HTTP without a slot, set :url "https://flows.breyta.ai/api/docs/pages", but prefer the slot form when the base URL should be configurable or reused.
Auth Variant: Google Service Account (:google-service-account)
Use this when you need unattended OAuth access to Google APIs on a schedule (e.g., Drive folder sync). The flow mints access tokens from a service account JSON secret.
Example (Google Drive list):
(flow/step :http :list-drive-files
{:title "List Drive files"
:url "https://www.googleapis.com/drive/v3/files"
:method :get
:query {:q "'<folder-id>' in parents and trashed = false"
:fields "nextPageToken,files(id,name,mimeType,modifiedTime,size,driveId)"
:pageSize 1000
:supportsAllDrives "true"
:includeItemsFromAllDrives "true"}
:auth {:type :google-service-account
:secret-ref :google-drive-service-account
:scopes ["https://www.googleapis.com/auth/drive.readonly"
"https://www.googleapis.com/auth/drive.metadata.readonly"]}})
Auth Variant: AWS SigV4 (:aws-sigv4)
Use this for AWS APIs that require Signature Version 4, including Amazon
Bedrock Runtime and API Gateway IAM endpoints.
The auth config supplies non-secret request metadata:
:auth {:type :aws-sigv4
:secret-ref :aws-bedrock
:region "us-east-1"
:service "bedrock"}
The referenced secret stores the credentials:
{
"access-key-id": "AKIA...",
"secret-access-key": "...",
"session-token": "optional temporary credential token"
}
For Breyta-hosted Bedrock authoring, this SigV4 connection shape is the
supported path today. Amazon Bedrock API keys use bearer-token auth separately
and are not accepted by the :backend :bedrock LLM backend yet.
For raw Bedrock Runtime calls, use a Bedrock Runtime host and a model invoke
path:
(flow/step :http :bedrock-invoke
{:connection :bedrock
:path "/model/anthropic.claude-3-5-sonnet-20241022-v2%3A0/invoke"
:method :post
:json {:anthropic_version "bedrock-2023-05-31"
:max_tokens 1024
:messages [{:role "user"
:content [{:type "text"
:text "Summarize this file."}]}]}
:response-as :json})
SigV4 signing uses the request method, path, query string, payload hash, Host,
x-amz-date, and any stable headers that are sent with the request. Volatile
transport headers such as User-Agent are sent normally but are not included in
the canonical signed header list.
Prefer the :llm Bedrock backend when the goal is a normal Claude model call;
use raw :http only when you need a Bedrock Runtime operation that the LLM step
does not expose.
Google OAuth Upload Init
For Google APIs that use an /upload/... endpoint, keep upload controls in scalar :query params and put OAuth on the connection:
(flow/step :http :init-youtube-upload
{:connection :youtube
:path "/upload/youtube/v3/videos"
:method :post
:query {:uploadType "resumable"
:part "snippet,status"}
:headers {"X-Upload-Content-Type" "video/mp4"}
:json {:snippet {:title "Demo"}
:status {:privacyStatus "private"}}
:include-headers ["location"]
:response-as :text})
Canonical Example
;; In the flow definition:
;; :templates [{:id :download-report
;; :type :http-request
;; :request {:path "/reports/latest" :method :get}}]
;; :functions [{:id :http-headers
;; :language :clojure
;; :code "(fn [input] {\"X-Request-Id\" (:request-id input)})"}]
'(let [headers (flow/step :function :build-http-headers
{:ref :http-headers
:input (flow/input)})
users (flow/step :http :get-users
{:connection :api
:path "/users"
:method :get
:query {:limit 10}
:headers headers
:retry {:max-attempts 3
:backoff-ms 500}})
report (flow/step :http :download-report
{:connection :api
:template :download-report
:data {:customer-id "cust-77"
:report-id "rep-42"
:run-date "2026-03-23"}
:response-as :bytes
:persist {:type :blob
:slot :archive
:path "{{data.customer-id}}/{{data.run-date}}"
:filename "summary-{{data.report-id}}.pdf"
:tier :ephemeral}})]
{:users users
:report report})
Author the matching blob-storage slot like this:
{:requires [{:slot :archive
:type :blob-storage
:label "Archive storage"
:config {:prefix {:default "reports"
:label "Folder prefix"
:placeholder "reports/customer-a"}}}]}
With :persist {:slot :archive ...}, platform-backed writes land under:
workspaces/<ws>/storage/<root>/<path>/<filename>