Skip to Content
APIReferenceAccreditation

Accreditation

An accreditation application is a request to be admitted in a category — Press, Contractor, VIP — reviewed by the organiser and, if approved, issued a credential. This endpoint reads the outcome for one registration.

It has its own key permission: registration.accreditation.read. registration.read does not confer it. A key you already hold for attendee lists gained nothing when this shipped, and never will — a new capability gets a new permission, so widening what a key can see is always an act by the workspace that owns it.

Read a decision

GET /api/public/v1/registrations/{id}/accreditation
{ "data": { "id": "acc_2f9…", "decision": "APPROVED", "status": "APPROVED", "category": { "code": "PRESS", "name": "Press", "nameAr": "صحافة" }, "submittedAt": "2026-09-01T10:00:00.000Z", "decidedAt": "2026-09-02T11:00:00.000Z", "credential": { "issued": true, "issuedAt": "2026-09-02T11:00:05.000Z", "revokedAt": null, "active": true }, "createdAt": "2026-09-01T09:00:00.000Z", "updatedAt": "2026-09-02T11:00:05.000Z" } }

Read decision, not status

decision is the outcome, and its meaning never changes. It is one of APPROVED, DECLINED, WITHDRAWN, REVOKED, or null while the application is still being decided.

status is the raw internal row state — DRAFT, SUBMITTED, UNDER_REVIEW, APPROVED, REJECTED, WITHDRAWN — and it carries one trap we would rather state than let you discover: a revocation overwrites it to WITHDRAWN. So on status alone, a credential the organiser revoked is indistinguishable from an application the applicant withdrew, and an approval that is later revoked stops looking like an approval. decision separates them:

what happeneddecisionstatuscredential.issuedcredential.active
Approved, credential liveAPPROVEDAPPROVEDtruetrue
Approved, then revokedREVOKEDWITHDRAWNtruefalse
Withdrawn by the applicantWITHDRAWNWITHDRAWNfalsefalse
Declined by the organiserDECLINEDREJECTEDfalsefalse
Still under reviewnullUNDER_REVIEWfalsefalse

status is published because it carries lifecycle stages decision cannot express (is it submitted? under review?). It is not the field to key a decision off.

A revoked credential

{ "data": { "id": "acc_2f9…", "decision": "REVOKED", "status": "WITHDRAWN", "category": { "code": "PRESS", "name": "Press", "nameAr": "صحافة" }, "submittedAt": "2026-09-01T10:00:00.000Z", "decidedAt": "2026-09-02T11:00:00.000Z", "credential": { "issued": true, "issuedAt": "2026-09-02T11:00:05.000Z", "revokedAt": "2026-09-03T08:00:00.000Z", "active": false }, "createdAt": "2026-09-01T09:00:00.000Z", "updatedAt": "2026-09-03T08:00:00.000Z" } }

credential.active is the field a door should read. It is issued && !revoked, computed here rather than left to you, so two integrations cannot disagree about whether a revoked credential still counts. issued stays true after a revocation, because “was issued and withdrawn” and “was never issued” are different facts and both matter.

The credential code is never returned

The credential itself — the value a scanner reads — is not in this response and is not in any read. It is a capability: whoever holds it can present as the accredited person, and there is no second factor behind it. It is shown once, to the organiser, at the moment of approval.

If you are building a door, you do not need it: ask this endpoint whether a credential is active for the registration in front of you.

The reviewer’s decision note is also withheld. It is internal text written about a named person during review, for the organiser’s own record.

Errors

This endpoint returns the standard error codes and adds nothing of its own. Two of them are worth reading in this context:

403 FORBIDDEN means the key is valid but lacks registration.accreditation.read. A key that reads registrations perfectly well still gets a 403 here — see the note at the top of this page.

404 NOT_FOUND deliberately covers three cases: no such registration, a registration with no accreditation application, and a registration belonging to another workspace. Distinguishing them would let an id be probed for existence, so they answer identically.

If a registration has more than one application

Nothing stops a registration carrying several applications — a re-application after a decline, for instance. This endpoint answers with the one that holds a credential, falling back to the most recently created when none does. That is deliberate: credential.active is the field a door reads, and answering with a newer application while an older one holds a live credential would refuse somebody who should be let in.

Not here yet

There is no list endpoint — this reads one registration’s decision. A directory of applications is a separate, wider surface and will arrive as its own change rather than by widening this one.

There are no writes. Applications are created in the app or at the door; an API that submitted one would invite bulk submission of other people’s identity documents.

Last updated on