Structured extraction

Send response_format.json_schema to any OpenAI client and get a filled JSON object back as the assistant message.

POST /v1/chat/completions with response_format.type: "json_schema" runs the extract capability. The model reads the user text and fills your schema. It returns the filled object as the assistant content string, with finish_reason: "stop".

This is the fastest way to add typed extraction to code that already speaks OpenAI. You change the base URL and the model id. You change nothing else.

No API key is required during the launch period. OpenAI SDKs demand an api_key value, so pass any non-empty string.

What the facade does with your request

1

It joins the user turns

The facade keeps messages with role: "user". It joins several user turns with a blank line. It joins the text parts of array content with a newline.

2

It drops system prompts

system, developer, assistant and tool messages are discarded. A decision model takes no instructions, so a system prompt changes nothing.

3

It runs extract over your schema

The facade passes response_format.json_schema.schema straight to extract. json_schema.name and json_schema.strict are accepted and ignored.

4

It returns the object as a string

choices[0].message.content holds the JSON text. Parse it yourself, or let the SDK parse it for you.

Make the call

curl -s -X POST https://api.milliseconds.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "decision-machine-1",
"messages": [
{"role": "user", "content": "Order #A-2291 shipped on 4 September 2026 to Berlin. The customer paid 149.90 EUR and asked for express delivery."}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "order",
"schema": {
"type": "object",
"properties": {
"order_number": {"type": "string", "description": "The order reference"},
"city": {"type": "string", "description": "Destination city"},
"amount": {"type": "number", "description": "Amount paid"},
"express": {"type": "boolean", "description": "Customer asked for express delivery"}
}
}
}
}
}'

The response

The call above returned this. A chat json_schema call measures 0.63 s end to end.

{
"id": "chatcmpl-306e6ee7881f4c9284cdbe0e",
"object": "chat.completion",
"created": 1789607702,
"model": "decision-machine-1",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"order_number\":\"A-2291\",\"city\":\"Berlin\",\"amount\":149.9,\"express\":true}"
},
"finish_reason": "stop"
}
],
"usage": {"prompt_tokens": 28, "completion_tokens": 18, "total_tokens": 46}
}

Read content as a string, then parse it. A field the text does not carry comes back as null. Nothing is invented.

Give every property a description. The description is what the extractor looks for in the text. A bare property name works, but a described field wins the right span more often.

Schema support

The facade applies the same rules as the native endpoint. Strings, numbers, integers, booleans, enums, string arrays and nested objects all work. An array-of-objects property is accepted and returned empty for now. oneOf, anyOf, allOf and $ref do not.

Read the full support matrix on the Extract page before you design a schema.

A root schema that is not an object with properties returns 400 invalid_schema, message schema must be an object with properties.

Limits and errors

RuleValue
Model iddecision-machine-1. Anything else returns 404 model_not_found.
Input sizeThe native extract endpoint caps text at 20,000 characters
BatchingNone here. Use texts on the native extract endpoint for up to 32 inputs.
Ignored fieldstemperature, max_tokens, top_p and other chat parameters are accepted and ignored
No user text400 invalid_request, message At least one user message with text is required.

tools beats response_format. When a request carries both, the facade takes the function-calling path and your schema is never used. Send tool_choice: "none" to keep the extraction path.

A request with no response_format.json_schema and no tools returns 400 unsupported_request:

{"error":{"code":"unsupported_request","message":"decision-machine-1 decides, it does not chat. Send response_format.json_schema for structured extraction, tools for function calling, or use the capability endpoints under /v1/decision-machine-1/."}}

response_format: {"type":"json_object"} and {"type":"text"} return the same 400. tool_choice: "none" without a json_schema also returns it. Only json_schema does work.

Next