Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HTTP connector

The http connector calls an external HTTP(S) endpoint from a service_task. This is the locked, as-built config contract — the same schema the control plane validates on PUT /connectors/{action} and the worker executes.

Config schema

{
  "url": "https://...",           // required; must start with http:// or https://
  "method": "POST",               // optional; GET|POST|PUT|PATCH|DELETE, default POST
  "headers": { "X-Foo": "bar" },  // optional, passed through verbatim

  "auth": {                       // optional; one of four kinds
    "kind": "none"
    // "kind": "bearer", "token": "..."
    // "kind": "apiKey", "header": "X-API-Key", "value": "..."   // header defaults to X-API-Key
    // "kind": "basic",  "username": "...", "password": "..."
    // "secretRef" is reserved for a future Secrets Manager integration —
    //   v1 does not resolve it. If present without the matching inline
    //   secret, the call fails closed with Http.ConfigError.
  },

  "bodyTemplate": "...",          // optional; empty = the input object verbatim.
                                   //   Tokens: {{input}}, {{input.a.b}}, {{$.a.b}}
                                   //   (a missing path resolves to null)
  "responseMap": { "field": "$.a.b" }, // optional; empty = { connector, status, body };
                                        //   otherwise an object with only the mapped fields

  "timeoutMs": 20000,             // optional, default 20000, per request
  "retry": { "max": 2, "backoffMs": 500 } // optional; retries only transport
                                           //   errors and 5xx — never 4xx
}

Secrets (auth.token, auth.value, auth.password) are stored inline in the config in v1 — never as plaintext at rest, though: the whole config is encrypted under the tenant’s envelope before being persisted (see Encryption at rest). A future secretRef pointing at a secrets manager is reserved but not implemented.

Auth kinds

kindFieldsBehavior
none (or omitted)no auth header added
bearertokenAuthorization: Bearer <token>
apiKeyheader (default X-API-Key), valuesets the named header to value
basicusername, passwordHTTP Basic auth header

Request construction

  • Body: bodyTemplate maps the input/state into the request body; an empty/absent template sends the input object verbatim. Available tokens: {{input}} (the whole input), {{input.a.b}} / {{$.a.b}} (a specific path — missing paths resolve to null, never an error).
  • Response mapping: responseMap picks specific fields out of the HTTP response via dot/JSONPath-style expressions into the task’s output object. With no responseMap, the task result is { connector, status, body } — the raw response wrapped with metadata.
  • Timeout & retry: timeoutMs (default 20000) bounds each individual request; retry.max/retry.backoffMs govern retries within this HTTP call only — transport errors and 5xx responses are retried up to max times with backoff; 4xx responses are never retried. This is independent of, and layered under, the workflow step’s own retry/catch.

Error contract

Every failure maps to a typed Step Functions error name, so a workflow’s retry/catch on the service_task can key off it precisely:

ConditionError nameRetries at the workflow level?
Missing url / invalid config JSON / malformed auth / secretRef with no matching secretHttp.ConfigErrorNo
Response 4xxHttp.ClientErrorNo
Response 5xxHttp.ServerErrorYes (up to retry.max)
Transport deadline / timeoutHttp.TimeoutYes
Other transport errorHttp.RequestErrorYes
Untyped error (other connector types, unknown type)ConnectorErrorWorker-dependent fallback

Config-shape errors (a missing url, a malformed auth block, an unknown auth.kind) are also rejected synchronously at bind time — PUT /connectors/{action} returns 400 before the binding is ever saved, so a broken config never reaches a running workflow in the first place. The table above covers failures that only surface at call time (a misconfigured but structurally valid secretRef, or the target endpoint itself failing).

Example

curl -sS -X PUT "$RULEFLOW_API/api/connectors/disburse-funds" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "type": "http",
    "config": {
      "url": "https://payouts.acme.internal/v1/disburse",
      "method": "POST",
      "auth": { "kind": "bearer", "token": "sk_live_..." },
      "bodyTemplate": "{ \"amount\": {{input.requested_amount}}, \"account\": {{input.account_id}} }",
      "responseMap": { "payoutId": "$.id", "status": "$.status" },
      "timeoutMs": 10000,
      "retry": { "max": 2, "backoffMs": 500 }
    }
  }'

A service_task with "action": "disburse-funds" and a catch on Http.ServerError/Http.Timeout will route to its error branch after exhausting retries; a Http.ClientError (e.g. a 400 from the payout service — a config problem) fails immediately without retrying, since retrying an unchanged bad request would never succeed.