Chat completions
POST /v1/chat/completions takes OpenAI's request and returns OpenAI's response, from Macs on the network. What the pilot accepts, what it refuses and the errors it gives.
https://api.mlx.app/v1/chat/completionsSend your key as Authorization: Bearer sk-mlx-…. The request waits until the job is settled (see How jobs run), at most 45 seconds.
Request
| Parameter | Type | Notes |
|---|---|---|
model | string | Required. qwen2.5-0.5b-instruct (see GET /v1/models). |
messages | array | Required. system, developer, user and assistant messages with text content: a string or a list of {"type": "text"} parts. |
max_tokens | integer | 1 to 120. Default 120. max_completion_tokens is the same field. |
temperature | number | Leave it out or send 0: the pilot decodes greedily, so two Macs can check each other. |
stream | boolean | Leave it out or send false. |
n | integer | Leave it out or send 1. |
Other OpenAI fields (top_p, seed, user…) are accepted and ignored. Tools, images and audio are refused.
How the messages are run
MLX Node 0.9 runs one user turn with the model's chat template. So:
- One
usermessage, with optionalsystemordevelopermessages, becomes the instructions followed by the message, in one turn. - A conversation (an
assistantmessage, or more than oneusermessage) becomes a transcript in one turn:User: …,Assistant: …, ending withAssistant:.
The whole prompt is at most 4,000 characters, and at most 32 messages.
Response
OpenAI's chat.completion, plus mlx:
| Field | Notes |
|---|---|
choices[0].message.content | The answer. MLX Node returns at most 600 characters; a longer one comes back cut, with finish_reason: "length". |
choices[0].finish_reason | stop (the model ended), or length (it reached max_tokens or the text limit). |
usage | Tokens you pay for. Prompt tokens are those the Macs report (template included), never more than a bound from the prompt's length; completion tokens are the fewer of the agreeing Macs' counts. |
mlx.verified | true when two Macs of different wallets gave exactly this answer. false when the wait ran out with one answer only. |
mlx.macs | How many Macs gave the answer returned. |
mlx.gpu_group | The Macs' GPU group (m1, m2, m3 for M3–M4, m5 for M5 and newer). See GPU groups. |
mlx.cost_usd | What this request cost. |
mlx.ms | From your request to the answer. |
The header x-mlx-verified carries mlx.verified too.
Errors
Errors use OpenAI's shape: {"error": {"message", "type", "param", "code"}}.
| Status | code | When |
|---|---|---|
| 400 | invalid_request | A field the pilot doesn't take; param names it. |
| 401 | invalid_api_key | No key, an unknown key or a revoked one. |
| 402 | insufficient_credit | Your available credit doesn't cover the most this request could cost. Add credit in the console. |
| 403 | pilot_closed | The pilot is closed to your wallet (it can be closed again, and then opened to listed wallets only). |
| 413 | request_too_large | The body is over 64,000 characters. |
| 429 | rate_limit | Over 60 requests a minute on this key. |
| 429 | too_many_in_flight | Over 8 requests running at once for this wallet. |
| 503 | no_capacity | No Mac answered in time, or the Macs disagreed. Nothing was charged; try again. |
Other endpoints
https://mlx.app/api/v1/modelsGET /v1/models lists the models, with the price and limits under mlx. GET /v1/account (with your key) returns your wallet, credit, pending (used since the last bill), held (requests running), available, and pilot (whether your wallet is on the list).