SocialToAIStart freeConsole

Batch jobs

[Bulk link data](/tools/batch-stats/) reads up to 2,000 links to posts or account pages as one batch job. You send the links once; the job reads them 50 at a time in the background, and you read the rows with its handle. Each row is charged as one call on its platform; dead links and rows that never ran cost nothing. Batches are for accounts that have bought credits.

POSThttps://api.socialtoai.com/v1/tools/batch_stats

The inputs and the credits of each platform are on Bulk link data in the documentation. This page is about the job.

Submit a batch

  • Send confirm: false first to get the quote: the most the job is charged, free. A batch runs in the background, so a request without confirm: true is answered with the quote too.
  • Send it again with confirm: true. The answer is HTTP 202 with a handle; nothing is charged yet. The same batch sent again under the same Idempotency-Key returns the same handle.
  • For an account that has bought credits, with a key that has the permission to start batches; otherwise HTTP 403. A link whose platform cannot be told refuses the whole request with invalid_params, and nothing runs.
cURL
curl https://api.socialtoai.com/v1/tools/batch_stats \  -H "Authorization: Bearer $SOCIALTOAI_KEY" \  -H "Idempotency-Key: $(uuidgen)" \  -H "Content-Type: application/json" \  -d '{    "urls": ["https://x.com/NASA"],    "confirm": true  }'
202 Accepted2020 credits
{  "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 (≈ $0.33)."  }}

Read the rows

Read the job at GET /v1/results/{handle} with its handle, as often as you like, for free. While it runs the answer is HTTP 202 with the rows that are in so far and retry_after_seconds; once it has ended, HTTP 200. Add ?format=csv for a table. The result is kept for 24 hours after the job ended.

cURL
curl https://api.socialtoai.com/v1/results/res_00000000000040008000000000000003 \  -H "Authorization: Bearer $SOCIALTOAI_KEY"
FieldTypeWhat it is
request_idstringThe id of the request that started the job.
schema_version"v1"The version of the response format.
tool"batch_stats"The tool the job runs.
status"running" | "done" | "stopped" | "cancelled" | "expired" | "refused"running, then one of the end statuses below.
stop_reasonstring | nullWhy it ended early: too_many_failed_rows, deadline, or the error code a wave was refused with.
handlestringThe handle the job is read with.
retry_after_secondsintegerWhile it runs: when to read again. (may be absent)
progress.rowsintegerThe links sent.
progress.rows_doneintegerThe rows run so far.
progress.wavesintegerThe waves the job is cut into.
progress.waves_doneintegerThe waves run so far.
charge.quote_creditsintegerThe quote: the most the job is charged.
charge.charged_creditsintegerWhat the rows that ran were charged so far.
main_number.idstringThe job's main number: engagement_total.
main_number.valuenumberThe engagement of the links that work, added up.
result.okintegerRows that came back.
result.deadintegerLinks that lead nowhere: deleted, private or gone.
result.failedintegerRows that did not come back.
result.unrecognizedintegerLinks whose post or account could not be read from the link.
result.not_runintegerRows the job never reached.
result.dead_linksstring[]The dead links themselves.
rowsarrayOne row per link, in the order sent: see below.
expires_atstring | nullUntil when the result can be read; null while it runs.

Each row:

FieldTypeWhat it is
rowintegerIts place in urls, from 0.
urlstringThe link as sent.
platformstringThe platform the link is on.
kind"post" | "account" | nullpost or account; null when the link does not say.
status"ok" | "dead" | "failed" | "unrecognized" | "not_run"How the row ended. Only ok is charged.
creditsintegerWhat the row was charged.
itemobject | any | nullThe post or the account as it is now, in the response format.
extraarrayItems of a second call some platforms need for a post's numbers.

How a job ends

The job is cut into waves of 50 rows, run one after another. Whatever the end, the rows that ran stay charged and the rest cost nothing.

statusWhat it means
runningWaves are still being run. Reading answers HTTP 202 with the rows that are in so far.
doneEvery row was run.
stoppedMore than 30% of the rows run so far failed, so no new wave was opened: stop_reason is too_many_failed_rows.
cancelledYou cancelled it in the console.
expiredIts 6 hours ran out: stop_reason is deadline.
refusedA wave could not be started, for example because the balance ran out: stop_reason is the error code.

What is charged

  • Each row is one call on its platform, at that platform's price for a post link or an account link. A row that came back is charged, numbers of zero and all.
  • A dead link, a link that could not be read and a row that never ran cost nothing. charge.charged_credits is never above the quote.
  • A batch cannot be paused. It can be cancelled on the console's Tasks page, also when a key started it: no new wave opens, the wave in flight runs to its end and is charged, and the rows not run cost nothing. Cancelling cannot be taken back.
  • When the job ends, a batch.finished event goes to your webhooks.

Over MCP

Your AI runs it with the research tool, tool set to batch_stats, and reads the result by calling the same tool again with the handle. The tool list has the description it is given.

Last updated: