Browse the documentation

Paid

Generate exam-style questions

POST/api/v1/questions/generate8p
Scope
ai:questions
Price
8p per call

A set of questions with their answers, as plain text: written questions with mark schemes, multiple-choice questions with options and the correct answer, or both. Anchor a set on one of our subtopics or on a topic in your own words.

What to know

  • THE PRICE IS PER SET, NOT PER QUESTION AND NOT PER TYPE. 8p whether you ask for 1 written question or 5 split across both shapes.
  • ANCHOR ON A SUBTOPIC OR ON A TOPIC, NEVER BOTH. A subtopic gets you questions written against our curriculum and pitched by that subject’s own genie. A topic gets you questions about your own wording, which is what to use when what you teach does not line up with a subtopic of ours.
  • `count` IS THE TOTAL FOR THE SET, shared out across the types you asked for, with the odd question going to written. Asking for both shapes with a count of 1 therefore returns one written question and no multiple choice: ask for at least 2 to get both.
  • READ THE `type` FIELD, NOT THE POSITION. Every question carries `type`, and written questions come first. A written question has `marks`, `markScheme` and `markSchemePoints`; a multiple-choice question has `options`, `correctAnswer` (always one of `options` verbatim) and usually an `explanation`.
  • `markScheme` and `markSchemePoints` ARE THE SAME CONTENT. The array is the string split on its line breaks. The string is the original field and is not going anywhere.
  • ONLY SUBTOPIC-ANCHORED WRITTEN QUESTIONS ENTER THE SHARED REVISION GENIE POOL, and they carry an `id`. You are paying for the generation, not for exclusivity: they are our content, written against our subtopics, and students on our platform may see them too. Topic-anchored questions and multiple-choice questions are not stored anywhere, so keep what you are sent.
  • THE SUBJECT FIELDS ARE A HINT, NOT A FILTER. With a `topic`, naming a subject pitches the questions at that qualification and board. A subject we cannot resolve is not an error: you get generally-pitched questions and `subject: null` in the response, so you can see the hint did not land.
  • `difficulty` is a HINT. The topic-anchored and multiple-choice generators act on it; the subtopic-anchored written generator records it against the generation without changing its prompt, so treat it as a request rather than a contract.
  • YOU MAY GET FEWER QUESTIONS THAN YOU ASKED FOR. A question the generator returns without a usable answer is dropped rather than sent. A call that produces one shape but not the other still delivers, and is charged; a call that produces nothing at all is refunded in full.
  • Nothing here is checked by a person before it reaches you. Review anything you show a user, particularly a child (developer terms clause 9.2).
  • Generation is one or two large model calls and can take a while. Allow a generous timeout.

Request body

FieldTypeRequiredDescription
subtopicIdstringNoA subtopic id from either tree. We work out which hierarchy it belongs to, so you do not have to. Send this OR "topic", never both.
topicstringNoA topic in your own words, 3 to 200 characters, for example "photosynthesis and limiting factors". Send this OR "subtopicId", never both.
typesstring[]NoWhich shapes to return: any of written, multipleChoice. Defaults to both for a "topic", and to written alone for a "subtopicId" so an existing integration is unchanged.
countintegerNoHow many questions in the set, 1 to 5. Defaults to 3. It is the TOTAL for the set, shared out across the types you asked for.
difficultystringNoOne of foundation, standard, higher. A hint, not a guaranteed banding.
subjectIdstringNoOptional with "topic": pitch the questions at one of our subjects. Ignored with "subtopicId", which already knows its subject.
subjectstringNoOptional with "topic": a subject name, for example "Biology", instead of an id. Narrow it with "qualification" and "examBoard".
qualificationstringNoNarrows a subject name, for example "GCSE".
examBoardstringNoNarrows a subject name, for example "AQA".

Example request

curl
curl -X POST "https://www.revisiongenie.com/api/v1/questions/generate" \
  -H "Authorization: Bearer rgk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"topic":"Photosynthesis","types":["written","multipleChoice"],"count":2,"subject":"Biology","qualification":"GCSE","examBoard":"AQA"}'

Example response

json
// anchored on a topic, both shapes
{
  "source": "topic",
  "subtopic": null,
  "topic": "Photosynthesis",
  "subject": {
    "id": "6612f0a1c3b4d5e6f7a80912",
    "name": "Biology",
    "qualification": "GCSE",
    "examBoard": "AQA"
  },
  "questions": [
    {
      "type": "written",
      "question": "Explain why the rate of photosynthesis stops rising once light intensity is very high.",
      "marks": 3,
      "markScheme": "Light is no longer the limiting factor (1 mark)\nAnother factor limits the rate (1 mark)\nAccept: carbon dioxide concentration or temperature (1 mark)",
      "markSchemePoints": [
        "Light is no longer the limiting factor (1 mark)",
        "Another factor limits the rate (1 mark)",
        "Accept: carbon dioxide concentration or temperature (1 mark)"
      ]
    },
    {
      "type": "multipleChoice",
      "question": "Which gas is taken in by a leaf during photosynthesis?",
      "options": ["Oxygen", "Carbon dioxide", "Nitrogen", "Hydrogen"],
      "correctAnswer": "Carbon dioxide",
      "explanation": "Carbon dioxide diffuses in through the stomata and is combined with water to make glucose."
    }
  ],
  "usage": { "costPence": 8, "balancePence": 4808 }
}

// anchored on a subtopic, written only (what you get with no "types")
{
  "source": "subtopic",
  "subtopic": {
    "id": "6612f0e5c3b4d5e6f7a80d01",
    "name": "Eukaryotes and prokaryotes",
    "topic": "Paper 1: Cell biology and organisation",
    "subject": "Biology",
    "hierarchy": "exam"
  },
  "topic": null,
  "subject": {
    "id": "6612f0a1c3b4d5e6f7a80912",
    "name": "Biology",
    "qualification": "GCSE",
    "examBoard": "AQA"
  },
  "questions": [
    {
      "type": "written",
      "id": "6613a1b2c3d4e5f6a7b80101",
      "question": "(a) Name two structures found in a plant cell but not in an animal cell. [2]\n(b) Explain why a bacterial cell is described as prokaryotic. [3]",
      "marks": 5,
      "markScheme": "(a) Cell wall (1); chloroplast / permanent vacuole (1) ...",
      "markSchemePoints": ["(a) Cell wall (1); chloroplast / permanent vacuole (1) ..."],
      "parts": [
        {
          "partNumber": "a",
          "question": "Name two structures found in a plant cell but not in an animal cell.",
          "marks": 2,
          "answerFormat": "lined"
        }
      ]
    }
  ],
  "usage": { "costPence": 8, "balancePence": 4800 }
}

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.

CodeStatusWhen
insufficient_balance402The balance does not cover the call. The body carries `balancePence` and a top-up link.
billing_not_enabled403The paid endpoints are not enabled on this developer account.
invalid_request400The body is not JSON, is not a JSON object, or a field failed validation. The message names the field.
request_too_large413The request body is larger than 8 KB.
subtopic_not_found404No subtopic with that id in either hierarchy, or it could not be resolved to a subject we generate for. Never returned for a "topic": a topic we cannot place is still generated for.
generation_failed502The generator produced nothing usable at all. The call is not charged.
invalid_key401The key is missing, malformed, revoked, expired, or is not a developer key.
forbidden403The key is valid but does not hold the scope this endpoint requires.
suspended403The developer account is suspended. Data reads stop as well as billable calls.
rate_limited429The 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_error500Something failed on our side. Retry; a paid call is refunded.

Revision Genie is an independent product and is not affiliated with or endorsed by AQA, Pearson Edexcel, OCR, WJEC or Eduqas.

Use of this API is governed by the developer terms. Questions: support@revisiongenie.com.