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. |
Related¶
- Webhooks — receiving and verifying AIR events.
- Quizzes and assessments — how sets are written, published and run.