w6w docs

Invocations

Applies to: HTTP · SDK (reading an invocation through client.request) · MCP (the invocationId comes back in the w6w_invoke result) · Studio (the History page). The frame described here is on the response of every call in Call any API.

An invocation is one call you made that ran to an answer right away: an app action, a Function or an Endpoint. Each one gets an id (inv_…), a verdict from w6w, timing, and a stored record. You can ask for the record afterwards by id — to see what you sent, what came back, and how long it took.

A Workflow run is different: it is queued, and its record is the run itself (runId, read with GET /runs/{id}). See the difference below.

The frame

Every successful call answers like this:

{
  "kind": "function",
  "output": { "accepted": true, "statusCode": 202, "messageId": "k2qI95g6T4iOkCgmTsfTwA" },
  "invocationId": "inv_2f9b7c14-…",
  "status": "succeeded",
  "startedAt": "2026-10-06T09:14:02.401Z",
  "finishedAt": "2026-10-06T09:14:02.826Z",
  "durationMs": 425
}
FieldMeaning
kindWhat actually ran: action, function or workflow. An Endpoint that points at a Workflow still reports workflow.
outputWhat the thing you ran produced.
valueThe same payload as output, sent on action calls for older clients. Deprecated — read output.
invocationIdThe id of this attempt. Use it to look the call up.
statusw6w’s verdict on the attempt: succeeded or failed (a Workflow answers queued).
startedAt, finishedAt, durationMsWhen it ran and for how long.
runIdWorkflow calls only: the run that was queued.

Two things to keep straight:

  • status is w6w’s verdict, not the vendor’s. In the example the vendor’s own statusCode is 202; that sits inside output and describes the vendor’s request. Whether w6w counted the call as a success is the top-level status.
  • A failure carries the frame too. A failed call’s error body includes invocationId, status: "failed" and the timing next to the error, so even a call that did not work has a receipt.

What ran: meta

The test-invoke route, POST /apps/<app-id>/actions/<key>/invoke, adds one more top-level field beside value and output: meta, which says what actually ran.

{
  "kind": "action",
  "output": { "text": "hi" },
  "meta": { "app": "echo-app", "version": "1.0.1", "action": "echo", "connectionId": "conn_8f2a" }
}
FieldMeaning
appThe app that ran.
versionThe app version that was actually loaded: an explicit version in the request, else your tenant’s pin, else the latest.
actionThe action key.
connectionIdThe stored connection the call used, or null when it used none (no connection, or an inline one).

meta is on both the success answer and a failure after the call was authorized (the app loaded and any connection you named resolved). It is absent for @w6w/* built-ins and for a call that fails before that point: a policy refusal, an unknown app, version or connection. It exists on this route only, not on /run, Functions or Endpoints. A connection id is only a name: knowing it grants nothing.

Read one back

import { W6WClient } from "@w6w/sdk";

const client = new W6WClient(); // reads W6W_BASE_URL and W6W_TOKEN

const { body } = await client.request({
  method: "GET",
  path: "/invocations/inv_2f9b7c14-…",
});

console.log(body.invocation);
curl -sS "$W6W_BASE_URL/invocations/inv_2f9b7c14-…" \
  -H "Authorization: Bearer $W6W_TOKEN"

The answer is { "invocation": { … } }: the record of that call — what you sent, the output or the error, the timing, and links to a parent invocation or a Workflow run when there is one.

List them

curl -sS "$W6W_BASE_URL/invocations?kind=function&limit=20" \
  -H "Authorization: Bearer $W6W_TOKEN"

The answer is { "invocations": [ … ] }. All filters are optional:

QueryFilters by
kindaction, function or endpoint.
functionOne Function.
endpointOne Endpoint.
runInvocations made inside one Workflow run (by its run id).
parentInvocations started by another invocation, by its id.
limitPage size. Values out of range are clamped; a value that is not a positive number is ignored.

Records are private to you: you can only read invocations you made, and a teammate in the same account cannot read yours, even with the id.

The History page

Studio’s History page reads a merged list — Function and Endpoint invocations together with Workflow runs — from two routes, which you can also call yourself:

curl -sS "$W6W_BASE_URL/history?kind=function&limit=50" \
  -H "Authorization: Bearer $W6W_TOKEN"
# → { "executions": [ … ], "hasMore": false }

curl -sS "$W6W_BASE_URL/history/stats?kind=function" \
  -H "Authorization: Bearer $W6W_TOKEN"
# → { "stats": { … } }

They take project or callable to scope the list, plus kind, status, from, to, q, limit and offset (/history only). An unknown callable answers 404 unknown_callable; a malformed filter answers 400.

One record per call you made

You get one record per call you made, not one per internal step:

You calledRecorded
POST /functions/{id}/invokeOne function invocation.
POST /endpoints/{id}/invoke pointing at an actionOne endpoint invocation.
POST /endpoints/{id}/invoke pointing at a FunctionAn endpoint invocation and a child function invocation, linked by parent.
POST /run with a connection and an action, or an app actionOne action invocation.
POST /run with an aliasOne endpoint invocation.
POST /run with a Workflow idNo invocation — the run is the record.
A Function step inside a Workflow runOne function invocation, tied to that run.

The app action underneath a Function does not get a record of its own; it is part of the Function.

Invocation id or run id?

They name different things.

  • invocationId names the call. It is on every action, Function and Endpoint answer, and on failures.
  • runId names a queued Workflow run that a call started. Read it with GET /runs/{id} or the w6w_run_status tool.

Calling a Workflow directly gives you a runId and no invocationId — the run already is the record. Reach the same Workflow through an Endpoint or an alias and you get both: the invocationId for the call, the runId for the run it started.

What to expect

  • A record is written when the call finishes, not when it starts. A call that is killed halfway leaves no record. Work that cannot afford that belongs in a Workflow, which is queued and can resume.
  • Recording never fails your call. If w6w cannot save the record, your call still returns its real answer. Very rarely that means an invocationId that looks up to a 404.
  • Large payloads are trimmed. Input, output and error are kept up to 128 KiB of JSON each. Over that, the stored value is replaced by {"_w6w_omitted":"too_large","sizeBytes":…,"capBytes":…}, so you can tell “too big to keep” from “nothing was produced”. A value JSON cannot represent is stored as {"_w6w_omitted":"unserializable"}.
  • Payloads are stored as sent. Don’t pass a token as a Function parameter if you would not want it in the call record; keep credentials in a connection or a secret.
  • Old records are pruned by the retention policy your deployment is configured with.
  • Not every call is recorded before it starts. A call refused before it runs — an unknown id, a disabled Function, a Function that was never published — writes no record.

Errors

Statuserror.codeMeaning
404unknown_invocationNo invocation with that id in your scope. It may belong to someone else, never have been recorded, or have been pruned.
400invalid_kindkind on GET /invocations was not action, function or endpoint.
404unknown_callablecallable on /history names nothing you can see.

A call that is refused before it runs, because the thing was never published, answers with the kind’s own code (this is the call’s error, not an invocation error):

You calledStatuserror.code
A Function422function_not_published
A Workflow409workflow_not_published
An Endpoint404endpoint_not_published

Publish it, pin a version, or pass "allowUnpublished": true in the request body to run a draft on purpose.

Next