Batching

Send up to 32 texts, statements or questions in one call and read the results back in input order.

Every capability accepts a batch. You batch on two axes:

  • texts — the same question against many texts. Every capability supports it.
  • statements / questions — many questions against the same text. Only yes-no and answer support these.

The two axes combine. The envelope tells you which axis you used.

The batch keys

KeyCapabilitiesReplacesLimit
textsall seventext1–32 items, each 1–20,000 characters
statementsyes-nostatement1–32 items, each min 1 character
questionsanswerquestion1–32 items, each min 1 character

text and texts are mutually exclusive. So are statement and statements, and question and questions. Send one key of each pair. yes-no is the one exception. See Gotchas below.

Batch over texts

Replace text with texts. The response becomes {"results": [...]}, one entry per text, in input order.

curl -s -X POST https://api.milliseconds.ai/v1/decision-machine-1/classify \
-H 'content-type: application/json' \
-d '{
"texts": [
"I was charged twice for my subscription this month and support has not replied.",
"My package still has not arrived after three weeks.",
"I cannot log in to my account since yesterday."
],
"labels": {
"billing": "payments, invoices, charges and refunds",
"shipping": "delivery, tracking and packages",
"account": "login, passwords and profile settings"
}
}'

Response, one entry per text:

{
"results": [
{"label":"billing","probability":0.999,"confidence":0.99,"scores":{"billing":0.999,"shipping":0,"account":0.001}},
{"label":"shipping","probability":0.988,"confidence":0.938,"scores":{"billing":0.011,"shipping":0.988,"account":0.001}},
{"label":"account","probability":0.999,"confidence":0.994,"scores":{"billing":0.001,"shipping":0,"account":0.999}}
]
}

results[i] always matches texts[i]. Zip the two arrays by index. No id field exists.

Batch over statements or questions

yes-no takes statements, answer takes questions. Both return {"results": [...]} in input order. Each result echoes the statement or question it scored.

curl -s -X POST https://api.milliseconds.ai/v1/decision-machine-1/yes-no \
-H 'content-type: application/json' \
-d '{
"text": "This is urgent, I need a refund today.",
"statements": [
"The customer expresses urgency.",
"The customer is asking about shipping."
]
}'
{
"results": [
{"statement":"The customer expresses urgency.","answer":true,"probability":1},
{"statement":"The customer is asking about shipping.","answer":false,"probability":0}
]
}

This axis adds no inference call, only the length of the extra statements. All the statements go into one inference call. Two statements measured 1.12 s against 0.75–1.25 s for one statement. Three questions on answer measured 0.56 s, the same as one question.

Both axes at once

Combine texts with statements or questions. The envelope nests: an outer results per text, an inner results per statement or question.

curl -s -X POST https://api.milliseconds.ai/v1/decision-machine-1/answer \
-H 'content-type: application/json' \
-d '{
"texts": [
"Tim Cook announced the iPhone 17 in Cupertino. It starts at $999.",
"Sundar Pichai announced the Pixel 11 in Mountain View. It starts at $799."
],
"questions": ["Who announced the product?", "How much does it cost?"]
}'

Response:

{
"results": [
{"results":[
{"question":"Who announced the product?","answer":"Tim Cook","probability":0.999,"start":0,"end":8},
{"question":"How much does it cost?","answer":"$999","probability":0.994,"start":60,"end":64}
]},
{"results":[
{"question":"Who announced the product?","answer":"Sundar Pichai","probability":0.998,"start":0,"end":13},
{"question":"How much does it cost?","answer":"$799","probability":0.994,"start":68,"end":72}
]}
]
}

Read it as results[textIndex].results[questionIndex]. Offsets are relative to that text.

start and end index the text at the same position in texts. Never index them into a joined string.

The 32 limit

texts, statements and questions each cap at 32 items. A 33rd item fails validation before any inference runs.

{"error":{"code":"invalid_request","message":"texts: Too big: expected array to have <=32 items"}}

The status is 400. Split larger workloads into chunks of 32 in your own code. Each text still carries the 20,000 character limit.

How a batch spreads across inference slots

One scheduler leases each inference call to a free slot. Each slot runs one call at a time.

  • texts costs one inference call per text. The worker fans them out and waits for all of them. A batch of 8 texts occupies up to 8 slots at once.
  • statements and questions cost nothing extra. Every statement becomes a label inside the same call.
  • Your batch shares the pool with everyone else. More texts means more parallel work, not slower work per text.

Measured evidence: extract over 2 texts took 1.03 s against 0.72 s for one text. yes-no over 2 texts × 2 statements took 1.08 s, inside the 0.75–1.25 s band of a single statement. The batch runs wide, not long.

When no slot frees in time, the call returns 529 with code overloaded and the message Every inference slot stayed busy. Retry with backoff. A large texts batch asks for many slots at once, so it meets this limit first. Retry the whole call with exponential backoff.

Cost and headers

Cost scales with everything you send, text plus statements, questions, labels, or schema, whatever the batch shape. The price is $0.04 per million input tokens and $0 per output token. See Pricing. Every capability response carries two headers:

HeaderValue
x-input-charsThe number of input characters. For texts, the sum over all items.
x-input-tokensThe input tokens billed for this call.

The three-ticket classify batch above returned x-input-chars: 176 and x-input-tokens: 43.

No API key is required during the launch period.

Gotchas

Every capability except yes-no answers 400 with body: provide text or texts, not both. The message is wrong for that case. Read it as “send exactly one of the two”.

yes-no applies its own statement / statements rule instead. It accepts both text and texts at once, uses text, and ignores texts. It also accepts neither, and returns {"results":[]} with x-input-chars: 0.

There is no per-item error. A validation error rejects the whole body. A 502 runner_error or 529 overloaded ends the whole call. Keep batches small enough that a retry is cheap.

Next

  • Input — how to shape text and the 20,000 character limit.
  • RAG passage filtering — one yes-no batch over retrieved passages.
  • Errors — the 529 backpressure signal and retry guidance.