Docs
Reference

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:

FieldTypeRequiredNotes
:connectionkeyword/stringYes*Slot or connection id
:urlstringYes*Full URL (ad hoc request)
:pathstringNoAppended to connection base URL
:methodkeywordNo:get, :post, :put, :patch, :delete
:headersmapNoHeader map
:querymapNoQuery params
:jsonmapNoJSON body
:formmapNoURL-encoded form body
:multipartvectorNoMultipart parts
:bodyanyNoRaw body
:body-from-refmapNoLoad body from a blob ref, resource URI, or canonical resource-ref
:content-typekeyword/stringNoBody content type
:acceptkeyword/stringNoAccept header helper (:json, :xml, :text) or a normal MIME header string such as "application/vnd.api+json"
:response-askeywordNo:auto, :json, :jsonl, :sse, :text, :bytes, :edn, :xml, :yaml
:include-headersvector<string/keyword>NoReturn only selected response headers, e.g. ["location"]
:parser-fnformNoCustom parse function
:templatekeywordNo:http-request template id
:datamapNoTemplate variables
:authmapNoStep-level auth (if not from connection)
:client-optsmapNoTransport overrides
:timeoutintNoTimeout seconds (common option)
:retrymapNoRetry policy (common option)
:persistmapNoPersist response refs; choose retained default for durable artifacts or :tier :ephemeral for temporary streamed HTTP blobs
:meteringmapNoAdvisory fixed API/tool cost for run cost estimates
:auto-search-index?booleanNoControl 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 :json and :body are set, :json wins.
  • :accept accepts shortcuts such as :json or "json" and full MIME header values such as "application/json;q=0.9,*/*;q=0.1".
  • :response-as :auto uses response Content-Type to choose :json, :jsonl, :sse, :text, or :bytes.
  • :response-as :sse is for finite text/event-stream responses, not indefinite listeners.
  • :query values 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 :persist from the start.
  • Use :tier :ephemeral for 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 :bytes and blob :persist; Breyta can stream the response directly to storage.
  • Persisted blob results include :uri / :resource-uri for resource APIs/UI and :blob-ref for 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 :path and :filename support {{...}} interpolation from step params and runtime fields.
  • :persist :path must 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 :slot must refer to a local :blob-storage requirement such as :archive.

Redirects, templates, auth:

  • Automatic redirect following is disabled for SSRF protection.
  • A 3xx result is marked with :redirect? true and :redirect-location when Location is present.
  • For public document systems, request ["location"], check :redirect?, and make a second explicit :http step to the returned URL.
  • Templates cover request shape; step-level keys like :persist stay 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 ...} for Authorization: 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 hold access-key-id, secret-access-key, and optional session-token.
  • Custom headers may reference secrets directly: :headers {"x-api-key" {:secret-ref :shotstack-key}}.
  • Use :metering when this HTTP call has a known fixed per-request cost.

Large uploads:

  • Prefer :body-from-ref and multipart :from-ref for uploads from prior persisted artifacts or resource-picker-selected files.
  • Supported refs: persisted blob envelopes, {:blob-ref ...}, raw res:// URIs, {:ref uri}, {:resource-uri uri}, and resource-picker maps.
  • Resource URIs used with :body-from-ref / :from-ref must 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-like text/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>

Related

As of May 21, 2026