Paid
Chat with a subject genie
POST
/api/v1/genies/{shortName}/chat4p- Scope
ai:chat- Price
- 4p per call
One stateless turn with a subject genie: our tutor persona for a specific qualification and board, streamed as NDJSON or returned whole.
What to know
- IT IS STATELESS. We store no conversation, read no learner profile and write nothing about anybody. You send the history on every call and you own it.
- DO NOT SEND US PERSONAL DATA ABOUT YOUR USERS. Names, contact details and school details must not appear in message content. Your users are yours; we are not your processor for them (developer terms clause 8.4).
- SAFEGUARDING DETECTION IS ALWAYS ON AND CANNOT BE TURNED OFF. Where a message suggests a user may be at risk, you get a `refusal` event with a reason instead of an answer, and the call is not charged. Your product must handle it responsibly: show the user something appropriate, give them a route to real help, and never hide the event or retry to get past it (developer terms clause 8.7).
- System subject genies only. A genie somebody built themselves is refused, because its persona, its owner’s rules and its uploaded files are not ours to sell.
- A stream that ends mid-answer emits an `error` event. Content already delivered is charged; a stream that produces nothing at all is refunded.
- THE HISTORY IS TRUNCATED TO A TOKEN BUDGET. The price is the same whatever you send, so we cap what reaches the model at roughly 6,000 tokens of conversation, keeping the newest turns and always the final user message. Whole messages are dropped, never half of one, and `usage.truncatedHistory` tells you when it happened. If you are hitting it, send a summary of the early conversation as one turn rather than the whole transcript.
- Any surface in your product powered by this endpoint must show "Powered by Revision Genie" where the user can see it (developer terms clause 4.1).
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| shortName | string (path) | Yes | The genie to talk to, for example "biology". System subject genies only. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| messages | array | Yes | The whole conversation, oldest first. Each entry is { role: "user" | "assistant", content: string }. Between 1 and 40 entries, each up to 8,000 characters, and the last one must have role "user". |
| stream | boolean | No | Defaults to true, which returns NDJSON. Set false to get one JSON object once the turn is finished. |
| options.hintFirst | boolean | No | Defaults to true. The genie leads a student towards the answer before giving it, and always gives it by its second reply. Set false for straight answers, which is usually right when your user is a teacher. |
Example request
curl
curl -X POST "https://www.revisiongenie.com/api/v1/genies/biology/chat" \
-H "Authorization: Bearer rgk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Why do plants need magnesium?"}],"stream":false}'Example response
json
// stream: false
{
"message": "Magnesium sits at the centre of every chlorophyll molecule ...",
"usage": { "costPence": 4, "balancePence": 4816, "truncatedHistory": false }
}
// stream: true (application/x-ndjson, one JSON object per line)
{"type":"delta","text":"Magnesium sits at "}
{"type":"delta","text":"the centre of every "}
{"type":"done","usage":{"costPence":4,"balancePence":4816,"truncatedHistory":false}}
// a safeguarding refusal, uncharged, HTTP 200
{"type":"refusal","reason":"safeguarding","message":"This message raises a wellbeing concern. Your application is responsible for directing the user to appropriate support."}Errors
Every error carries the same shape: a stable error code to branch on and a message for a human. Codes specific to this endpoint come first.
| Code | Status | When |
|---|---|---|
| insufficient_balance | 402 | The balance does not cover the call. The body carries `balancePence` and a top-up link. |
| billing_not_enabled | 403 | The paid endpoints are not enabled on this developer account. |
| invalid_request | 400 | The body is not JSON, is not a JSON object, or a field failed validation. The message names the field. |
| request_too_large | 413 | The request body is larger than 32 KB. Trim the oldest turns. |
| genie_not_found | 404 | No system subject genie with that shortName. Unknown, unlinked and user-created genies all read the same from outside. |
| upstream_failed | 502 | The model was unavailable or returned nothing. The call is not charged. |
| invalid_key | 401 | The key is missing, malformed, revoked, expired, or is not a developer key. |
| forbidden | 403 | The key is valid but does not hold the scope this endpoint requires. |
| suspended | 403 | The developer account is suspended. Data reads stop as well as billable calls. |
| rate_limited | 429 | The key went past its ceiling: 120 calls a minute overall, 30 a minute on the paid endpoints. Also returned after repeated failed authentication from one address. |
| server_error | 500 | Something failed on our side. Retry; a paid call is refunded. |