Overview
The API caller node performs a single HTTP request configured on the node row. The Worker resolves the URL and credentials (preferring edge-linked values when present), merges query parameters into the URL, builds headers and body fromcontentType and related fields, executes the request with undiciβs Agent (optional TLS verification control), then stores the response body as text and returns it from the activity.
apiCallerActivity delegates to ApiCallerService.process.
When it runs
apiCallerActivity is invoked from the processSingleNode workflow when the node type is API caller (NodeType.API_CALLER, stored value apiCaller).
Activity signature
ApiCallerResponse:
flows_nodes.data.text on success (see Persisted node data).
Resolving URL and secrets (edge vs static)
Some fields can come either from static properties ondata or from the first row of an edge-driven array (when the UI passes dynamic inputs):
| Concept | Static field | Edge-driven (takes precedence when non-empty) |
|---|---|---|
| Request URL | url | urlData[0].text |
| Custom headers (JSON) | jsonAuth | jsonAuthData[0].text |
| Basic auth username | username | usernameData[0].text |
| Basic auth password | password | passwordData[0].text |
*Data array exists and has length > 0, use [0].text; otherwise use the static field. After resolution, url is required β if still missing, the service throws: No URL provided: urlData and url are both missing or empty.
The service copies resolved values back onto a merged ApiCallerNodeData object (resolvedNodeData) so downstream logic always reads url, jsonAuth, username, and password from the effective values.
Node data fields
Types reference: ApiCallerNodeData.
Request line
| Field | Role |
|---|---|
method | HTTP method: GET, POST, PUT, DELETE, or PATCH. |
url | Base URL string (used if urlData is absent or empty). |
urlData | Optional EdgeDataItem[]; first itemβs text overrides url when present. |
queryParams | Optional { key, value }[]. Each pair is appended to the URL search string (key required; value may be undefined and is skipped with the key). |
Headers and auth
| Field | Role |
|---|---|
jsonAuth | String containing JSON of header key/value pairs (e.g. {"Authorization":"Bearer β¦"}). Parsed with JSON.parse and merged into the request headers. If parsing fails, merge is skipped (no throw). |
jsonAuthData | Optional; first text overrides jsonAuth when non-empty. |
username | If set, triggers HTTP Basic auth: Authorization: Basic base64(username:password). Password defaults to empty string when omitted. |
password | Used with Basic auth when username is set. |
passwordData / usernameData | Optional edge overrides for password / username. |
jsonAuth (custom headers) and Basic auth apply, Basic sets Authorization after the JSON merge, so Basic wins for Authorization when both are present.
| Field | Role |
|---|---|
contentType | Optional. When set, becomes Content-Type on the request. Also drives how the body is built (see Request body). |
Request body
| Field | Role |
|---|---|
jsonRequestBody | String. Interpretation depends on contentType (and effective content type β see below). |
formDataParams | { key, value }[] for application/x-www-form-urlencoded bodies. |
nodeData.contentType ?? headers['Content-Type'] (headers already include jsonAuth and possibly Content-Type from contentType).
Behavior of buildRequestBody:
application/x-www-form-urlencoded- If
formDataParamshas entries: buildURLSearchParamsfrom key/value pairs (skip entries with missingkeyorundefinedvalue). - Else if
jsonRequestBodyis set: parse it as JSON into an object, then append each key withString(value)intoURLSearchParams.
- If
application/json- If
jsonRequestBodyis set: parse with a tolerant path β first strictJSON.parse; on failure, a regex tries to add quotes around unquoted object keys, then parse again. If both fail, throwsInvalid JSON in request body.
- If
undefined).
The fetch call passes body as a string: either the form-encoded string, or JSON.stringify of the parsed object for JSON.
TLS
| Field | Role |
|---|---|
validateCertificate | Boolean; default true if omitted. When false, the undici Agent uses connect.rejectUnauthorized: false (allows self-signed or mismatched certificates). Use with care. |
End-to-end flow
- Load
flows_nodesbynodeIdand castdatatoApiCallerNodeData. - Resolve URL and auth-related fields (edge vs static).
- Construct
URL, applyqueryParamsviasearchParams.set. - Build
RequestInit: method, headers, body, anddispatcherwith TLS options. fetch(url, options).- If
!response.ok, readresponse.text()for the error payload, lognodeId, status, and body, then throwHTTP <status>: <body>. - On success, read full response as text (
response.text()). UPDATE flows_nodes: mergeresolvedNodeDatawithtext(response body) andexecutionStatus: 'COMPLETED'.- Return
{ result: responseText }.
Persisted node data
On success, the stored JSON includes the merged caller configuration plus:
| Field | Role |
|---|---|
text | Response body as a string (not parsed as JSON by the Worker). |
executionStatus | 'COMPLETED'. |
Errors
- Missing node β
Node not found. - Missing URL after resolution β see above.
- HTTP status outside 2xx β thrown error with status and body text.
- Invalid JSON body (JSON content type path) β
Invalid JSON in request body.