ACTION_ID: http_api_call NAME: HTTP API Call CATEGORY: Integrations CREDITS: 0.005 Make an API call. 1. INPUTS method (dropdown, required) Method. Choose the HTTP method. Values: GET, POST, PATCH, PUT, DELETE. endpoint (string, required) Endpoint. Enter the endpoint to send the requests to. query_params (raw_array, optional) Query Params. Enter the Query Parameters of your Call. Each item is `{name, value}` — `value` accepts `{{ref}}` tokens or literals. body (raw_array, required) Body. Enter the Data Body to include in the Call. Each item becomes a JSON key on the outgoing request body. Each item is `{name, value}` — `value` accepts `{{ref}}` tokens or literals. headers (raw_array, optional) Headers. Enter any header fields to set for the Call. Each item is `{name, value}` — `value` accepts `{{ref}}` tokens or literals (auth tokens, content-type, etc.). 2. OUTPUTS Dynamic — there are no fixed output fields. The output schema is discovered after the first run via Get Action Outputs (see KEY NOTES); each top-level key on the response JSON becomes a referenceable output. Until the first run, no outputs are surfaced. 3. HOW TO CONFIGURE Configure Action body (PATCH /api/v1/workflows/{workflow_id}/sheets/{sheet_id}/actions/{action_instance_id}): { "inputs": { "method": "POST", "endpoint": "https://api.example.com/v1/score", "headers": [ { "name": "Authorization", "value": "Bearer YOUR_API_KEY" }, { "name": "Content-Type", "value": "application/json" } ], "query_params": [ { "name": "expand", "value": "full" } ], "body": [ { "name": "domain", "value": "{{input.domain}}" }, { "name": "company_name", "value": "{{input.company_name}}" } ] } } Field-by-field: - method HTTP verb. GET, POST, PATCH, PUT, DELETE. - endpoint The URL. Variable references (`{{input.foo}}`, `{{.bar}}`) resolve per-row at run time, so you can build per-row URLs like `https://api.example.com/v1/companies/{{input.id}}`. - query_params List of {name, value}. Omit for none. - headers List of {name, value}. Auth and content-type go here; references inside `value` resolve per-row. - body List of {name, value}. Each item becomes a JSON key on the outgoing request body. Discovering the output schema: 1. Configure the action with the body above (Configure Action). 2. Add ONE example row whose inputs exercise the API call: POST /api/v1/workflows/{workflow_id}/sheets/{sheet_id}/rows Body: { "rows": [{ ...representative input values... }] } 3. Run that row: POST /api/v1/workflows/{workflow_id}/sheets/{sheet_id}/run Body: { "row_ids": [""] } The worker hits the upstream API and stores the response so it can be inspected for shape on the next call. 4. Call Get Action Outputs: GET /api/v1/workflows/{workflow_id}/sheets/{sheet_id}/actions/ {action_instance_id}/outputs The handler reads the captured response, infers a field per top-level JSON key, mints stable responses, persists the new schema onto the action, and returns the public `outputs[]` array — each entry with a ready-to-paste `reference` token. Drop those tokens verbatim into downstream actions' Configure Action bodies. 5. ⚠ Important: the example row from step 3 ran BEFORE the schema existed, so its List Rows cell will NOT carry the discovered outputs. To get a populated cell for that row, re-run it — Run Rows on the same row_id, or call Run Action (`POST /actions/{action_instance_id}/run`) to run rows just for this action. Alternatively delete the example row (Delete Rows) and run fresh rows. From this point on every new run sees the persisted schema and surfaces the outputs in `cells[].outputs`. 4. KEY NOTES - Output schema is discovered, not declared. Until at least one row has run the call, the outputs list is empty. Get Action Outputs is the canonical place to read it once data is available — and note the example row used for discovery won't itself surface the typed outputs in its cell (it ran before the schema existed); re-run it or use fresh rows. See section 3 for the full walkthrough. - If the upstream API returns an array of objects, the output schema is derived from the FIRST item's keys. Per-key types are inferred from that one sample (`string` / `number` / `boolean` / `array` / `json`, plus `email` / `url` heuristics on strings) and applied to every row downstream. - References inside `endpoint`, header values, query-param values, and body item values all resolve per-row, so the same configured action can hit a different URL with different headers and body for each row of your sheet. - Auth is yours to wire. Floqer doesn't manage credentials for HTTP API Call — put a bearer token / API key in a header, or wire it from an upstream input column if it varies per row. - Response parsing falls back to text when the body isn't valid JSON. Non-JSON responses can still be referenced as a single string output but the per-key output schema only materialises for JSON bodies. - The output schema is LOCKED to the first response, and does not re-expand. If the first run returned a sparse response (an error payload, a different endpoint, a row missing optional fields), the action stays stuck on those keys — later runs that return more fields will NOT surface them, and `Get Action Outputs` won't add them. Discover the schema from a FULL-coverage row. To recover a locked action, DELETE it and re-add it, then let it rediscover on the next run (re-point any downstream refs to the new action_instance_id). - An empty `body` item fails the CELL at run time. Each `body[]` item's value is JSON-parsed, so an item with `value: ""` — the placeholder the UI leaves behind, or the residue of converting a body-based call to a query-param one — errors with `Unexpected end of JSON input`. The action still PATCHes 200 and looks correct in Get Action. For an API whose parameters all live in the query string, set `body: []` (an empty ARRAY), not an empty raw_json item. - Query-string APIs go in `query_params`, not `body`. Some APIs define no request body at all (Apollo's `add_contact_ids`, for one) and read every parameter off the query string. `query_params` values resolve `{{refs}}` per-row exactly like body values do, and bracket-style array keys work — `{ "name": "contact_ids[]", "value": "{{ref}}" }`. Sending those parameters in the body instead is silently ignored by the upstream API: you get a 200 that did nothing. 5. WHERE IT FITS IN A WORKFLOW Pattern: row data -> http_api_call (custom API) -> downstream processing. Worked example — pushing leads into an Apollo sequence (no native Floqer action exists for it) is a three-action http_api_call tail, and covers the whole shape: a JSON-body write, plucking an id out of the response, then a query-param-only call that uses it. See https://floqer.com/docs/use-case-detail/apollo_sequence_push.txt 6. WHEN TO USE Use http_api_call for any API not covered by a built-in action. 7. WHEN NOT TO USE A built-in action exists for the API -> use that action — search https://floqer.com/docs/action-catalog.txt for the provider name before falling back to a raw HTTP call. Last updated: 2026-07-13. Last updated: 2026-08-10.