Text generation
POST /api/ai/generate sends a prompt through the engine chain in job mode; you poll for the answer and learn which engine served it.
When to use this endpoint
Use /api/ai/generate for anything that is not real-time: reports, grading, drafts, classification, document reading, batches. It supports engine preference order, exact models per engine, JSON mode, attachments and a strict subscription_only switch.
Use Chat completions instead when a person is typing in a chat client or an OpenAI-compatible tool (editor plugins, aichat, Open WebUI), or when you want streaming keepalives on one connection.
Both surfaces share one admission controller (24 running requests globally with a free-memory floor, 12 per API-key owner) and the same account rotation and deny rules.
Submit a job
POST /api/ai/generate
curl -s https://maximind.dev/api/ai/generate \
-H "x-api-key: $MAXIMIND_API_KEY" -H "content-type: application/json" \
-d '{"prompt":"…","system":"…","json":false,
"engines":["agy","codex","claude"],
"models":{"agy":"gemini-4-argon-high","codex":"gpt-5.6-sol","claude":"opus"},
"subscription_only":true,"async":true,"attachments":[]}'
{"ok": true, "job_id": "…"}
| Name | Type | Required | Description |
|---|---|---|---|
prompt |
string | Yes | The user request. |
system |
string | No | System prompt. |
json |
boolean | No | JSON mode: ask the model for a JSON answer. Strip code fences before parsing. |
engines |
string[] | No | Preference order among agy, codex, claude. Omitted: the key's own default chain (see below). |
models |
object | No | Exact model per engine, any id from the catalogue, e.g. {"agy":"gemini-4-argon-high","codex":"gpt-5.6-sol","claude":"opus"}. Since 13/10/2026 the old ids gemini-3.1-pro-high and gemini-3.1-pro-low are still accepted and are answered by Gemini 4 Argon (gemini-4-argon-high / -low); the result's model names the model that ran. |
subscription_only |
boolean | No | true: never touch a pay-per-use API; if no engine can answer the job fails and your app decides. Always send true. |
async |
boolean | No | true: return {job_id} now and poll. Always send true; the public edge cuts single requests at about 100 s. |
attachments |
array | No | Images, PDFs and text files by URL. See Vision. |
The raw JSON body is bounded to 512 KiB before it is parsed, including chunked bodies. A denied model (Codex Astra, Claude Fable) is silently replaced by that engine's default.
Poll the job
GET /api/ai/generate/jobs/{job_id}
curl -s https://maximind.dev/api/ai/generate/jobs/<job_id> -H "x-api-key: $MAXIMIND_API_KEY"
{"status": "queued|running|done|failed", "text": "…", "engine": "agy", "account": "agy-primary", "model": "gemini-4-argon-high", "error": null}
| Field | Meaning |
|---|---|
status |
queued (not yet at the front of the single queue), running, done, failed. |
text |
The answer when done. |
engine, account, model |
What actually answered. The model may differ from what you asked for when the request was denied or an account rotated. |
error |
Failure message when failed. |
attachments |
Per-input read receipts when attachments were sent. See Vision. |
Poll every 1 to 3 seconds. A queued status is normal: the machine runs one heavy task at a time. Job IDs are visible only to the API-key owner that created them; another key gets 404. Responses are Cache-Control: private, no-store, and finished in-memory records expire after one hour.
Which engine answered
Read engine, account and model from the job result and log them. With subscription_only: true the possible outcomes are:
done: an engine answered; the receipt says which.failed: no engine could answer (quota, signed-out accounts, all engines in the chain unavailable). MaxiMind did not spend paid API money. Your app's original paid path, if any, stays in your own ledger.
Default engine chain per key
GET /api/ai/site-chain and POST /api/ai/site-chain
The key's own default engine order, used when a request sends no engines.
curl -s https://maximind.dev/api/ai/site-chain -H "x-api-key: $MAXIMIND_API_KEY"
JSON mode
Send "json": true and instruct the model in system or prompt what shape to return. Models sometimes wrap JSON in code fences; strip fences before json.loads. The OpenAI-compatible endpoint offers the same through response_format: {"type":"json_object"}. JSON schemas are not supported on either surface.
Reference recipe (from the owner's PHP sites)
The owner's sites wrap every non-real-time paid call like this: try MaxiMind first with a tier (pro or fast), an optional prefer engine order and optional exact models; when the result is null (no engine could answer) run the original paid-API code unchanged. A MaxiMind outage then degrades to cost, never to a broken feature. Queue jobs marked subscription_only are skipped rather than sent to a paid key.
Legacy task endpoint
POST /api/ai/agent runs fixed task shapes (translate, write, summarize, proofread, explain, answer; custom is admin-only) with input up to 100k characters, optional options, engine and model, and returns {ok, job_id} to poll at GET /api/ai/agent/status/{job_id} ({status, text, engine, elapsed, isolation_receipt?}). Body limit 256 KiB; 2 credits. GET /api/ai/agent/tasks lists the tasks and engines available to your key. Prefer /api/ai/generate for new work.
curl -s -X POST https://maximind.dev/api/ai/agent \
-H "x-api-key: $MAXIMIND_API_KEY" -H "Content-Type: application/json" \
-d '{"task":"translate","input":"Xin chào các bạn","options":{"to":"English"}}'
Errors
| Status | Meaning |
|---|---|
| 401 | Missing or invalid key. |
| 403 | Pending account; key lacks generate or a permitted engine. |
| 404 | Job id unknown, expired (1 h) or owned by another key. |
| 413 | Body over 512 KiB. |
| 429 | Admission saturated (24 global / 12 per owner, or the server is short of memory). Retry-After: 5. Sent before the prompt is retained or quota spent. |
Limits
- 512 KiB raw body; 100,000-character attachment prompt bound; attachment file limits in Vision.
- 12 active requests per API-key owner, 24 globally, shared with chat completions and agent tasks.
- Job records expire one hour after completion.