Results and handles
A call that cannot answer within its request answers 202 with a results handle instead of waiting. GET /v1/results/{handle} then reads what the call came to. Reading is free and can be repeated; only the key that started the call can read it; a result is kept for 24 hours after its run ended. Over MCP the same handle goes into the tool's handle argument. Nothing is charged before a run ends, and a failed call is not charged.
https://api.socialtoai.com/v1/results/{handle}When a call answers with a handle
- A slow interface. A few interfaces always take long. They answer with a handle at once; their own page says so.
- The wait ran out. Any other call waits up to 40 seconds for the platform. When the result is not there by then, the request answers with a handle and the call goes on.
- A tool run that goes on in the background. Its quote says so in
quote.mode.
The answer is HTTP 202 with a Retry-After header and this body. status is running, and billing.cost_credits is 0: nothing is charged until the run has ended.
{ "request_id": "req_00000000-0000-4000-8000-000000000003", "schema_version": "v1", "status": "running", "handle": "res_00000000000040008000000000000003", "retry_after_seconds": 5, "billing": { "cost_credits": 0, "balance_credits": 100, "today_spend_credits": 0, "daily_limit_credits": null, "daily_remaining_credits": null, "display": "This call: 0 credits. Balance: 100 credits." }}| Field | Type | What it is |
|---|---|---|
request_id | string | Identifies this answer. Quote it when you report a problem. |
schema_version | "v1" | Always "v1". |
status | "running" | Always "running" in this answer. |
handle | string | What the result is read with. |
retry_after_seconds | integer | How soon the handle is worth reading. The same number is in the Retry-After header. |
cells | array | Of a request for several platforms or targets: the answers that have already ended, each as the final answer will hold it. (may be absent) |
steps | array | Of a tool run: its steps as far as they have gone. (may be absent) |
billing.cost_credits | integer | Always 0 here: nothing is charged before the run ends. |
billing.balance_credits | integer | Your balance now. |
billing.today_spend_credits | integer | Credits spent today, in UTC. What the run holds meanwhile is counted here. |
billing.daily_limit_credits | integer | null | Your daily limit; null when none is set. |
billing.daily_remaining_credits | integer | null | What is left of the daily limit; null when none is set. |
billing.display | string | One sentence an AI can repeat to you. |
waves.planned | integer | |
waves.done | integer | |
charge.quote_credits | integer | |
charge.charged_credits | integer |
Read the result
curl https://api.socialtoai.com/v1/results/res_00000000000040008000000000000003 \ -H "Authorization: Bearer $SOCIALTOAI_KEY"- Still running: HTTP 202 and the same body as above. Wait
retry_after_secondsand read again. - Finished: exactly what the call would have answered, under its own status: the envelope under 200, or the error structure under the status of its code.
billing.cost_creditsis what the run was charged; the balance is as of this read. - Reading is free. Read as often as you like; the run is charged once, when it ends, by the same rules as any call.
- The run broke on our side: HTTP 500
internal_error. Nothing was charged.
Who can read it
Only the key that started the call. To any other key, another key of the same account included, the handle does not exist: HTTP 404 not_found. The handle alone opens nothing: reading it always takes the key. Calls you start in the Playground are read in the console, under your sign-in.
How long it is kept
A result is kept for 24 hours after its run ended. After that the handle answers HTTP 410 handle_expired. To get the data again, send the call again: that is a new call, charged as one.
As a file
Add ?format=csv or ?format=ndjson to get a finished result's rows as a file: a table, or one JSON object a line. While the run is still going the answer is the 202 body above, whatever the format. Another value of format is refused with invalid_params.
- The columns of the CSV are every field any row has. A nested field is written
a.b; a list stays in one cell. - A cell that starts with
=,+,-or@gets an apostrophe in front, so that a spreadsheet does not run it as a formula.
curl "https://api.socialtoai.com/v1/results/res_00000000000040008000000000000003?format=csv" \ -H "Authorization: Bearer $SOCIALTOAI_KEY" -o result.csvOver MCP
The 13 tools that charge all take one more argument, handle. A call with handle only reads that result: nothing else runs, nothing is charged, and the other arguments are not looked at. So when a tool answers status: "running", your AI calls the same tool again with the handle.
Large answers: more.handle
An answer over MCP holds at most about 60 KB of JSON (roughly 20,000 tokens), so that it does not fill your model's context. A larger result comes as its first rows and a more object:
| Field | Type | What it is |
|---|---|---|
more.handle | string | The handle with the place to read on from, written handle.position. Call the same tool with it for the next rows. |
more.rows_left | integer | How many rows are still to come. |
more.note | string | One sentence on how to go on, for the AI. |
Reading on is free. Go on until an answer carries no more. Over HTTP the same handle, without the position, reads the whole result at once.
Sending the same request again
A handle does not change how Idempotency-Key works. The same key with the same parameters while the run is still going is refused with HTTP 409; once the run has ended it returns the first result again and costs 0.
Last updated: