Record outcome
Records one step of a multi-call workflow. agentKey names the OutcomeStep. runId is required and groups every signal of one run — a step may repeat freely.
This only records the step; it never bills. Close and bill the run with a separate call to POST /signal/outcome/complete.
If the model has both cache-read and cache-write rates, cacheTokens carries the cache-**read** tokens only (billed at the cache-read rate); send cache-write tokens separately as cacheWriteTokens.
Authorization
apiKey Organisation-scoped key from Settings → API Keys.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The step shape ONLY — POST /signal/outcome accepts nothing else. A body carrying complete is rejected outright; declaring the workflow finished is POST /signal/outcome/complete (see OutcomeCompletionInput), a wholly separate request.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/signal/outcome" \ -H "Content-Type: application/json" \ -d '{ "customerId": "cus_abc123", "agentKey": "resolved_ticket.triage", "runId": "ticket_9021", "usage": { "model": "openai/gpt-4o", "inputTokens": 900, "outputTokens": 120 } }'{ "statusCode": 200, "statusDetail": { "status": "SUCCESS", "message": "OK" }, "result": { "usageLog": { "id": "log_8m3n5p", "customerId": "cus_abc123", "modelName": "gpt-4o", "creditName": "Deep Research", "member": "dana@acme.com", "inputTokens": 1200, "outputTokens": 350, "cacheTokens": 200, "cacheWriteTokens": 0, "credit": 2, "providedCost": 0.0087, "customerCost": 0.012, "status": "SUCCESS", "appliedRules": [], "outcome": null, "balance": { "dimension": "credit", "remaining": 18, "name": "Deep Research" }, "createdAt": "2026-07-21T14:03:22.000Z" }, "rawId": "raw_4k8w2r" }}{ "statusCode": 202, "statusDetail": { "status": "SUCCESS", "message": "Signal accepted for processing." }, "result": { "queued": true, "messageId": "msg_2f4a1b8c", "rawId": "raw_4k8w2r" }}{ "statusCode": 400, "statusDetail": { "status": "ERROR", "message": "Request body must be valid JSON." }, "result": {}}{ "statusCode": 401, "statusDetail": { "status": "ERROR", "message": "Invalid API key." }, "result": {}}{ "statusCode": 404, "statusDetail": { "status": "ERROR", "message": "No customer with id \"cus_abc123\"." }, "result": {}}{ "statusCode": 409, "statusDetail": { "status": "ERROR", "message": "Customer \"cus_abc123\" is archived." }, "result": {}}{ "statusCode": 422, "statusDetail": { "status": "ERROR", "message": "No credit with agent key \"summarize\" exists in this workspace." }, "result": {}}{ "statusCode": 500, "statusDetail": { "status": "ERROR", "message": "Could not complete the request." }, "result": {}}Record credit POST
Records usage against a named Credit balance. `agentKey` must be sold on the customer's active plan, or covered by a composite that is. Priced automatically from the model's rates and token counts — you can't post a price yourself. If the model has both cache-read and cache-write rates, `cacheTokens` carries the cache-**read** tokens only (billed at the cache-read rate); send cache-write tokens separately as `cacheWriteTokens`.
Complete outcome POST
Closes and bills ONE outcome run. This is the only way to close a run; `POST /signal/outcome` never accepts `complete`. Closes the run only. If a step carried a `composite`, that occurrence still needs its own [`POST /signal/composite/complete`](/docs/api-reference/signals/completeCompositeSignal).