Skip to content

Partner API

Stub — expand with the endpoint reference.

Partners integrate over a server-to-server REST API, authenticated with a per-partner key (AIR_PARTNER_KEY) against AIR_PARTNER_BASE_URL. Inbound events are delivered as signed webhooks; the SDKs verify the signature and give you typed events.

Send the key as a bearer token on every request:

Authorization: Bearer <AIR_PARTNER_KEY>

A missing key is refused 401 (missing_key); a key AIR doesn't recognise is refused 403 (invalid_key).

Quizzes

Your team's published question sets can be launched for one of your contacts. The quiz runs as a conversation in the thread that contact already has with their colleague, so you start it here and find out how it went later, from the quiz.assignment.completed webhook.

For the colleague to run it, someone on the team must have taught a colleague Run a quiz. See quizzes and assessments.

List the quizzes you can offer

GET /v1/partner/quizzes

Returns the published sets your team can offer: the organisation's, and your team's own. Never another team's, and never a draft.

{
  "quizzes": [
    {
      "set_id": "5b0e…",
      "name": "Fire safety refresher",
      "stakes": "practice",
      "questions": 10,
      "tags": []
    }
  ]
}
Field Type Notes
set_id uuid Pass this to the launch call
name string The set's name, as shown in AIR
stakes enum compliance | practice | play
questions int How many questions are currently in the set
tags string[] May be empty

No question or answer is ever returned.

Launch a quiz for a contact

POST /v1/partner/contacts/{contact_id}/quizzes/{set_id}

No body. Answers 202 Accepted: the quiz has been started, and the first question arrives in the contact's thread the way anything the colleague says does.

{
  "set": "Fire safety refresher",
  "contact_id": "a2a0…",
  "outcome": "started",
  "assignment_id": "91c4…",
  "conversation_id": "cdf9…"
}
Field Type Notes
set string The set's name
contact_id uuid Echoes the path
outcome enum started — a new quiz was started. already — this contact already has this set open; launching again is a nudge, not a second quiz
assignment_id uuid Matches assignment_id on the completion webhook
conversation_id uuid The thread the quiz runs in

The score is not in this response. A quiz finishes minutes or days after it is launched; subscribe your door to quiz.assignment.completed to be told.

Refusals

Errors from these endpoints carry a stable code you can branch on:

{
  "detail": {
    "error": {
      "code": "no_thread",
      "message": "that person has no conversation with this colleague yet — …",
      "context": { "contact_id": "a2a0…" }
    }
  }
}
Status code What it means What to do
404 contact_not_found No contact with that id. Check the id.
403 contact_not_owned The contact isn't in any of your partner groups. Only your own contacts can be launched for.
403 group_not_owned The contact's group belongs to another partner. As above.
404 set_not_available That set isn't one your team can offer — it doesn't exist, isn't published, or belongs to another team. Use a set_id from GET /v1/partner/quizzes.
409 no_runner No colleague on your team has been taught to run a quiz. Ask the team's manager to teach one Run a quiz.
409 no_thread The contact hasn't talked to their colleague yet. A quiz is never the thing that opens someone's first conversation. Launch it after they have.
409 set_not_launchable The set can't be given right now — for example, it stopped being published between listing and launching. List again and retry with a set that is offered.