API Reference
sessions
16 endpoints
- /api/v1/sessions
/api/v1/sessions/{session_slug}Get Session
Get a session by slug (or uuid, until v1 is frozen).
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| requires_ticket | boolean | Whether the ticket gate is on: entry needs a valid ticket from `ticket_template_uuid`. A switch beside the ticket, so the gate can be turned off and on again without losing which ticket it checks. It cannot be on with no ticket named default: false |
| ticket_template_uuid | string | null | The reward template whose valid tickets the gate accepts, or null for none named |
| required_entitlement | string | null | The membership entitlement a person needs to enter at all: `member` for any active membership, a tier's own key for that capability, or null for anyone |
| max_attendees | integer | null | How many seats there are, or null for uncapped. A ticket issued for the session takes a seat, and a walk-in takes one when admitted ≥ 1 |
| enforces_checkin_window | boolean | Whether the start and end times refuse a tap outside them (a ticketed event: you cannot check into last night's concert) or only describe when it was meant to happen (attendance tracking, where refusing a late arrival records nothing and no record reads as not having come) default: true |
| allow_reentry | boolean | Whether a repeat tap by someone already admitted re-admits them (a recurring-access door) or is refused as already here (an event) default: false |
| admits_frozen_cards | boolean | Whether a card its holder or issuer has frozen is still admitted. False refuses it as `card_frozen`: freezing usually means the card is lost, and whoever found it would enter as its owner. True admits it and flags the presence with `disputed_reason: card_frozen` for the organizer to keep or void, for a door where a card frozen by mistake should not hold anyone up. Either way the owner can check in with another identifier default: false |
| uuid* | string | |
| slug* | string | |
| activity_uuid | string | null | The activity this session is filed under, or null for one that stands alone. An activity groups sessions; the organization owns them, so a session without one is complete rather than orphaned |
| name* | string | |
| description | string | null | |
| start_time* | string (date-time) | |
| end_time* | string (date-time) | |
| is_checkin_open | boolean | default: true |
| cancelled_at | string (date-time) | null | When it was cancelled, or null. A cancelled session admits nobody and takes no new seats, and is kept rather than deleted because its attendance and tickets are a record |
| required_prior_session_uuid | string | null | |
| series_uuid | string | null | The schedule this session was created as part of, or null for one created on its own |
| sequence_number* | integer | |
| created_at* | string (date-time) | |
| updated_at | string (date-time) | null |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}Update Session
Update a session. Only the fields sent change.
A finished session's times and settings are the terms its attendance was
recorded under, so changing them answers 400; its end can still move
later, to extend a session running over. Changing the ticket of a session
people already hold it for answers 409 stranding_holders unless
confirm_stranding_holders is set, since it leaves them with no seat and
no way in. Moving the session to another activity is refused while its
ticket belongs to the current one. A required prior session must start
before this one.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Request body*application/json
| Field | Type | Description |
|---|---|---|
| requires_ticket | boolean | null | Whether the ticket gate is on: entry needs a valid ticket from `ticket_template_uuid`. A switch beside the ticket, so the gate can be turned off and on again without losing which ticket it checks. It cannot be on with no ticket named |
| ticket_template_uuid | string | string (uuid) | null | The reward template whose valid tickets the gate accepts, or null for none named |
| required_entitlement | string | null | The membership entitlement a person needs to enter at all: `member` for any active membership, a tier's own key for that capability, or null for anyone |
| max_attendees | integer | null | How many seats there are, or null for uncapped. A ticket issued for the session takes a seat, and a walk-in takes one when admitted ≥ 1 |
| enforces_checkin_window | boolean | null | Whether the start and end times refuse a tap outside them (a ticketed event: you cannot check into last night's concert) or only describe when it was meant to happen (attendance tracking, where refusing a late arrival records nothing and no record reads as not having come) |
| allow_reentry | boolean | null | Whether a repeat tap by someone already admitted re-admits them (a recurring-access door) or is refused as already here (an event) |
| admits_frozen_cards | boolean | null | Whether a card its holder or issuer has frozen is still admitted. False refuses it as `card_frozen`: freezing usually means the card is lost, and whoever found it would enter as its owner. True admits it and flags the presence with `disputed_reason: card_frozen` for the organizer to keep or void, for a door where a card frozen by mistake should not hold anyone up. Either way the owner can check in with another identifier |
| confirm_stranding_holders | boolean | Go ahead with changing the ticket of a session people already hold it for. Without it such a change answers `409 stranding_holders`: the holders are left with no seat and no way in default: false |
| activity_uuid | string | string (uuid) | null | File the session under an activity, or send null to take it out of one and leave it standing alone. The activity must belong to the same organization. Omit to leave it where it is — this is the one field where null and absent differ |
| name | string | null | Name of the session |
| description | string | null | Session description |
| start_time | string (date-time) | null | Session start time |
| end_time | string (date-time) | null | Session end time |
| is_checkin_open | boolean | null | Manual toggle for check-in |
| required_prior_session_uuid | string | string (uuid) | null | Another session of the same activity that must have been attended before this one admits anyone. None = no such gate |
Responses
| Field | Type | Description |
|---|---|---|
| requires_ticket | boolean | Whether the ticket gate is on: entry needs a valid ticket from `ticket_template_uuid`. A switch beside the ticket, so the gate can be turned off and on again without losing which ticket it checks. It cannot be on with no ticket named default: false |
| ticket_template_uuid | string | null | The reward template whose valid tickets the gate accepts, or null for none named |
| required_entitlement | string | null | The membership entitlement a person needs to enter at all: `member` for any active membership, a tier's own key for that capability, or null for anyone |
| max_attendees | integer | null | How many seats there are, or null for uncapped. A ticket issued for the session takes a seat, and a walk-in takes one when admitted ≥ 1 |
| enforces_checkin_window | boolean | Whether the start and end times refuse a tap outside them (a ticketed event: you cannot check into last night's concert) or only describe when it was meant to happen (attendance tracking, where refusing a late arrival records nothing and no record reads as not having come) default: true |
| allow_reentry | boolean | Whether a repeat tap by someone already admitted re-admits them (a recurring-access door) or is refused as already here (an event) default: false |
| admits_frozen_cards | boolean | Whether a card its holder or issuer has frozen is still admitted. False refuses it as `card_frozen`: freezing usually means the card is lost, and whoever found it would enter as its owner. True admits it and flags the presence with `disputed_reason: card_frozen` for the organizer to keep or void, for a door where a card frozen by mistake should not hold anyone up. Either way the owner can check in with another identifier default: false |
| uuid* | string | |
| slug* | string | |
| activity_uuid | string | null | The activity this session is filed under, or null for one that stands alone. An activity groups sessions; the organization owns them, so a session without one is complete rather than orphaned |
| name* | string | |
| description | string | null | |
| start_time* | string (date-time) | |
| end_time* | string (date-time) | |
| is_checkin_open | boolean | default: true |
| cancelled_at | string (date-time) | null | When it was cancelled, or null. A cancelled session admits nobody and takes no new seats, and is kept rather than deleted because its attendance and tickets are a record |
| required_prior_session_uuid | string | null | |
| series_uuid | string | null | The schedule this session was created as part of, or null for one created on its own |
| sequence_number* | integer | |
| created_at* | string (date-time) | |
| updated_at | string (date-time) | null |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X PATCH "https://api.davi.social/api/v1/sessions/{session_slug}" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ /* request body */ }'/api/v1/sessions/{session_slug}Delete Session
Delete a session by slug (or uuid, until v1 is frozen).
Addressed on the session itself, so it deletes either kind — one filed under an activity or one standing alone. The organization owns a session in both cases, which is what the ownership check resolves against.
A session anyone has attended is a record, and deleting it answers
409 has_attendance; one its ticket has been issued for answers
409 has_tickets, whether or not the session has ended. Cancel it instead.
One another session requires attending first answers 409 has_dependents,
naming them in details.sessions: deleting it would leave them admitting
anyone. A session that is absent and one belonging to another organization
both answer 404.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| message* | string | Success or status message |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X DELETE "https://api.davi.social/api/v1/sessions/{session_slug}" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/admitAdmit Session
Admit a resolved identity to a session in one call — resolve, decide, and check in.
Present a tagged-union identifier (card, wallet, username, …); this resolves
it, reaches the same verdict /eligibility reports, and acts on it. Every
verdict answers 200:
admitted: the identity is in.action_takenischeckinwhen this call recorded the attendance,reentrywhen it re-admitted someone already present at a session that allows re-entry, andnullwhen it was a retry of an admit that already succeeded (sameidempotency_key).needs_confirm: the identity holds no ticket but one can be issued. Register it (redeem the session's ticket via/rewards/{reward_slug}/redeem) and call/admitagain; the second call finds the ticket and admits.blocked: it cannot be admitted and registering would not help;blocked_reasonsays why, with the same values/eligibilityreturns.already_admittedmeans the identity is already present and the session does not allow re-entry: a door shows it as "already here".
The reasons are checked in a fixed order, so the one returned is the most
useful thing to tell the person: "already here" where re-entry is off, then
whether the door is open, then re-entry, then the session's hours (which
govern first entry only), then membership and prior attendance (which no
ticket can fix), then the ticket, then capacity. Someone whose seat is
already held, by a ticket for the session or an earlier admission, is never
refused for capacity. Two admits racing for the last seat cannot both get
it: the loser is answered at_capacity.
A card that has been frozen, by its holder or its issuer, is refused as
card_frozen before anything else is decided, unless the session sets
admits_frozen_cards. Then it is judged like any other, and a check-in by
it is recorded with disputed_reason: card_frozen for the organizer to keep
or void.
Self-service: the resolved identity must match the token subject.
On-behalf-of (a door admitting a holder): requires session:attendees:manage
with an org-scoped token for the session's organization.
Attendance is recorded on the identity's canonical wallet for the session's organization — the one wallet every card it holds resolves to — so the door and the offline manifest admit the same set.
idempotency_key is persisted per session for offline replay. A retry with
the same key returns admitted; reuse for a different resolved identity is
a 409 idempotency_conflict, the only 409 this operation returns.
A door uploading an admission it made offline sends occurred_at, the time
of the tap, and must hold a session-bound token. The admission is judged at
that time and recorded at it, and recorded even where the server would
have refused: the response is admitted with disputed_reason saying
what it would have refused for, and the presence is flagged for an
operator to keep or void. A frozen card is recorded the same way, and so is
an admission whose ticket could not be checked because the ledger failed
(ledger_unavailable). Neither the check-in switches nor capacity are held
against an upload, since what they were at the tap is not recorded: the
person is already inside. A cancellation is, and one made before the tap
is disputed as checkin_closed. An upload resent
with the idempotency_key of a presence an operator has since voided is
acknowledged (admitted, attendee_status: voided) and the void stands.
occurred_at in
the future beyond a few minutes of clock tolerance, or more than seven days
old, answers 400.
The attendance is what the door waits on; its ledger proof is written just
after, off this path. So on a fresh check-in the response carries
proof_status: "pending" and no attendance_proof_tx_id yet — a ledger blip
delays the proof, it never blocks admit.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Request body*application/json
| Field | Type | Description | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| identifier* | IdentifierRef | ||||||||||
object · IdentifierRef
| |||||||||||
| idempotency_key | string | null | ||||||||||
| proof_metadata | object | null | ||||||||||
| occurred_at | string (date-time) | null | When a door admitted this identity offline, for an admission it is uploading now. Only a session-bound door token may send it. The admission is judged at this time and recorded at it, and recorded even where the server would have refused: see `disputed_reason` on the response. It may not be in the future, beyond a few minutes of clock tolerance, nor older than seven days | |||||||||
Responses
| Field | Type | Description | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| decision* | string | What happened. `admitted`: the identity is now checked in (or already was — a repeat admit is idempotent, not a `409`). `needs_confirm`: it holds no ticket but one can be issued, so the door should register it (redeem the ticket) and admit again — `available_actions` lists what it can do. `blocked`: it cannot be admitted and registering would not help — `blocked_reason` says why. Treat an unfamiliar value as a refusal. | ||||||||||||
| action_taken | string | null | What the call did: `checkin` when it recorded attendance, `null` when nothing changed (already admitted, needs-confirm, or blocked). | ||||||||||||
| attendee_status* | string | The identity's attendance record at the session after the call: `attended`, `voided`, or `none` when there is no record. | ||||||||||||
| available_actions | string[] | For `needs_confirm`, the actions the door can take next — currently `register`. Empty otherwise. | ||||||||||||
| blocked_reason | string | null | For `blocked`, why, null otherwise. The same reasons `/eligibility` returns. `already_admitted`: the identity is already present and the session does not allow re-entry. `checkin_closed`: check-in is switched off for the session or its event, or either is cancelled. `too_early` / `too_late`: the session refuses a first entry outside its start and end times. `membership_required`: the session is gated on a membership or tier the identity does not hold. `prior_session_required`: the session admits only those who attended an earlier one, and this identity has not. `registration_closed`: a ticket is required, the identity has none, and one cannot be issued: the ticket behind it is withdrawn, sold out, or scoped to a different event. `at_capacity`: every seat is taken. `card_frozen`: the card presented has been frozen. Treat an unfamiliar value as a plain refusal: the set grows. | ||||||||||||
| attendance_proof_tx_id | string | null | The ledger transaction id of the attendance proof, once written. Null on a fresh `admitted` check-in: the proof is written just after the attendance, off the response path — read `proof_status`. | ||||||||||||
| proof_status | string | null | The state of the attendance proof for a fresh check-in: `pending` (being written), `written` (`attendance_proof_tx_id` is set), or `failed` (a repair will complete it). Null when the call recorded no new check-in. | ||||||||||||
| disputed_reason | string | null | For an uploaded offline admission (`occurred_at`) the server would have refused, why: one of the `blocked_reason` values, or `ticket_required` for someone who held no ticket, or `ledger_unavailable` when the ticket could not be checked. The admission is still recorded, and flagged for an operator to keep or void. Also `card_frozen` for a check-in by a frozen card at a session that sets `admits_frozen_cards`. Null otherwise | ||||||||||||
| ticket | HeldTicketRef | null | |||||||||||||
object · HeldTicketRef
| ||||||||||||||
| user | CheckinUser | null | |||||||||||||
object · CheckinUser
| ||||||||||||||
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X POST "https://api.davi.social/api/v1/sessions/{session_slug}/admit" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ /* request body */ }'/api/v1/sessions/{session_slug}/attendee-statusGet Attendee Status
Check attendee status for a wallet in a session.
Returns the attendee record if registered, or null if not registered. Useful for checking status before attempting registration or check-in.
Path parameters
| session_slug* | string |
Query parameters
| wallet_address* | string | Wallet address to check |
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| uuid* | string | |
| activity_uuid | string | null | Denormalized from the session, so it is null for an attendee of a session that stands alone |
| session_uuid | string | null | |
| wallet_address* | string | |
| user_uuid | string | null | |
| status* | enum | |
| source | enum | Who produced the record: `door` (admitted at a door), `self` (the person checked themselves in) or `operator` (a correction) default: "door" |
| recorded_by_user_uuid | string | null | The operator who last changed the record, for `operator` rows |
| reason | string | null | Why an operator recorded or voided it |
| disputed_reason | string | null | For a presence a door recorded offline that the server would have refused, why: one of the `/admit` `blocked_reason` values, or `ticket_required`, or `ledger_unavailable` when its ticket could not be checked. The presence stands until an operator keeps it (recording it `attended` clears this) or voids it |
| registered_at* | string (date-time) | |
| attended_at | string (date-time) | null | |
| last_admitted_at | string (date-time) | null | The latest admission: the check-in, then each re-entry where the session allows re-entry |
| additional_data | object | null | |
| created_at* | string (date-time) | |
| updated_at | string (date-time) | null | |
| username | string | null | |
| display_name | string | null | |
| avatar_url | string | null | |
| proof_tx_id | string | null | |
| proof_status | string | null | |
| proof_verified | boolean | null | |
| proof_tx_hash | string | null | |
| proof_amount | number | null |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/attendee-status" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/attendeesList Session Attendees
List attendees for a specific session.
Path parameters
| session_slug* | string |
Query parameters
| include_proof | boolean | Include proof transaction info in response default: false |
| default_backend | string | default: "primary" |
| page | integer | default: 1 · ≥ 1 |
| page_size | integer | default: 20 · ≥ 1 · ≤ 100 |
| sort_by | string | null | |
| sort_order | string | default: "asc" |
Responses
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| total_items* | integer | Total number of items available | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| total_pages* | integer | Total number of pages available | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| current_page* | integer | Current page number | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| items* | ActivityAttendeeResponse[] | List of items on the current page | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
array items · ActivityAttendeeResponse
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/attendees" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/attendees/{wallet_address}Get Session Attendee
Read one attendee of a session.
The collection had a read and the item had a write, so a client that updated an attendee could not read back what it wrote.
Path parameters
| session_slug* | string | |
| wallet_address* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| uuid* | string | |
| activity_uuid | string | null | Denormalized from the session, so it is null for an attendee of a session that stands alone |
| session_uuid | string | null | |
| wallet_address* | string | |
| user_uuid | string | null | |
| status* | enum | |
| source | enum | Who produced the record: `door` (admitted at a door), `self` (the person checked themselves in) or `operator` (a correction) default: "door" |
| recorded_by_user_uuid | string | null | The operator who last changed the record, for `operator` rows |
| reason | string | null | Why an operator recorded or voided it |
| disputed_reason | string | null | For a presence a door recorded offline that the server would have refused, why: one of the `/admit` `blocked_reason` values, or `ticket_required`, or `ledger_unavailable` when its ticket could not be checked. The presence stands until an operator keeps it (recording it `attended` clears this) or voids it |
| registered_at* | string (date-time) | |
| attended_at | string (date-time) | null | |
| last_admitted_at | string (date-time) | null | The latest admission: the check-in, then each re-entry where the session allows re-entry |
| additional_data | object | null | |
| created_at* | string (date-time) | |
| updated_at | string (date-time) | null | |
| username | string | null | |
| display_name | string | null | |
| avatar_url | string | null | |
| proof_tx_id | string | null | |
| proof_status | string | null | |
| proof_verified | boolean | null | |
| proof_tx_hash | string | null | |
| proof_amount | number | null |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/attendees/{wallet_address}" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/attendees/{wallet_address}Update Session Attendee
Correct a session's attendance record for one person.
This corrects the record; it is not a door. None of the rules a door admits
by apply: not the check-in switches, the start and end times, capacity, the
ticket, the membership gate or the prior-session gate. An operator can
record that someone came to last week's session, or to one whose check-in
has closed. That is why reason is required: the record keeps it, beside
who made the change, as source: operator.
attended records the person as present and writes an attendance proof,
exactly as a check-in at the door would, so an operator correcting a record
and a reader recording one produce the same evidence. It applies whether or
not the person has a record at the session yet, and over a voided one.
voided withdraws a presence recorded in error. The record stays, and the
attendance proof already written is answered with a cancellation proof
rather than removed: the ledger keeps both. Setting attended again
records a new presence with a new proof.
A presence recorded here takes a seat even past capacity, as the record is being corrected rather than a door deciding. Voiding one gives back the seat it took, and never one a ticket holds.
A presence a door recorded offline that the server would have refused
carries disputed_reason. attended keeps it: the dispute clears and the
presence, its time and its proof stand as the door recorded them. voided
withdraws it like any other.
Marking someone already attended answers 409 rather than recording a
second check-in: attendance at a session is a fact about whether they came,
not a count of taps. Voiding someone with no record answers 404.
Path parameters
| session_slug* | string | |
| wallet_address* | string |
Query parameters
| default_backend | string | default: "primary" |
Request body*application/json
| Field | Type | Description |
|---|---|---|
| status* | enum | `attended` records the person as present and writes an attendance proof; `voided` withdraws a presence recorded in error |
| reason* | string | Why the record is being changed. Kept on the record beside who changed it, since an operator is not bound by the door's rules min length 1 · max length 500 |
Responses
| Field | Type | Description |
|---|---|---|
| uuid* | string | |
| activity_uuid | string | null | Denormalized from the session, so it is null for an attendee of a session that stands alone |
| session_uuid | string | null | |
| wallet_address* | string | |
| user_uuid | string | null | |
| status* | enum | |
| source | enum | Who produced the record: `door` (admitted at a door), `self` (the person checked themselves in) or `operator` (a correction) default: "door" |
| recorded_by_user_uuid | string | null | The operator who last changed the record, for `operator` rows |
| reason | string | null | Why an operator recorded or voided it |
| disputed_reason | string | null | For a presence a door recorded offline that the server would have refused, why: one of the `/admit` `blocked_reason` values, or `ticket_required`, or `ledger_unavailable` when its ticket could not be checked. The presence stands until an operator keeps it (recording it `attended` clears this) or voids it |
| registered_at* | string (date-time) | |
| attended_at | string (date-time) | null | |
| last_admitted_at | string (date-time) | null | The latest admission: the check-in, then each re-entry where the session allows re-entry |
| additional_data | object | null | |
| created_at* | string (date-time) | |
| updated_at | string (date-time) | null | |
| username | string | null | |
| display_name | string | null | |
| avatar_url | string | null | |
| proof_tx_id | string | null | |
| proof_status | string | null | |
| proof_verified | boolean | null | |
| proof_tx_hash | string | null | |
| proof_amount | number | null |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X PATCH "https://api.davi.social/api/v1/sessions/{session_slug}/attendees/{wallet_address}" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ /* request body */ }'/api/v1/sessions/{session_slug}/cancellationCancel Session
Cancel a session, keeping its record.
A cancelled session admits nobody and takes no new seats, online or at an
offline door. Its attendance, the tickets people hold and its reports stay,
which is why a session with any of them is cancelled rather than deleted.
Cancelling one already cancelled keeps its original cancelled_at.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| requires_ticket | boolean | Whether the ticket gate is on: entry needs a valid ticket from `ticket_template_uuid`. A switch beside the ticket, so the gate can be turned off and on again without losing which ticket it checks. It cannot be on with no ticket named default: false |
| ticket_template_uuid | string | null | The reward template whose valid tickets the gate accepts, or null for none named |
| required_entitlement | string | null | The membership entitlement a person needs to enter at all: `member` for any active membership, a tier's own key for that capability, or null for anyone |
| max_attendees | integer | null | How many seats there are, or null for uncapped. A ticket issued for the session takes a seat, and a walk-in takes one when admitted ≥ 1 |
| enforces_checkin_window | boolean | Whether the start and end times refuse a tap outside them (a ticketed event: you cannot check into last night's concert) or only describe when it was meant to happen (attendance tracking, where refusing a late arrival records nothing and no record reads as not having come) default: true |
| allow_reentry | boolean | Whether a repeat tap by someone already admitted re-admits them (a recurring-access door) or is refused as already here (an event) default: false |
| admits_frozen_cards | boolean | Whether a card its holder or issuer has frozen is still admitted. False refuses it as `card_frozen`: freezing usually means the card is lost, and whoever found it would enter as its owner. True admits it and flags the presence with `disputed_reason: card_frozen` for the organizer to keep or void, for a door where a card frozen by mistake should not hold anyone up. Either way the owner can check in with another identifier default: false |
| uuid* | string | |
| slug* | string | |
| activity_uuid | string | null | The activity this session is filed under, or null for one that stands alone. An activity groups sessions; the organization owns them, so a session without one is complete rather than orphaned |
| name* | string | |
| description | string | null | |
| start_time* | string (date-time) | |
| end_time* | string (date-time) | |
| is_checkin_open | boolean | default: true |
| cancelled_at | string (date-time) | null | When it was cancelled, or null. A cancelled session admits nobody and takes no new seats, and is kept rather than deleted because its attendance and tickets are a record |
| required_prior_session_uuid | string | null | |
| series_uuid | string | null | The schedule this session was created as part of, or null for one created on its own |
| sequence_number* | integer | |
| created_at* | string (date-time) | |
| updated_at | string (date-time) | null |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X POST "https://api.davi.social/api/v1/sessions/{session_slug}/cancellation" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/cancellationReinstate Session
Reinstate a cancelled session.
Its door is then decided by its check-in switch again, as before it was cancelled.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| requires_ticket | boolean | Whether the ticket gate is on: entry needs a valid ticket from `ticket_template_uuid`. A switch beside the ticket, so the gate can be turned off and on again without losing which ticket it checks. It cannot be on with no ticket named default: false |
| ticket_template_uuid | string | null | The reward template whose valid tickets the gate accepts, or null for none named |
| required_entitlement | string | null | The membership entitlement a person needs to enter at all: `member` for any active membership, a tier's own key for that capability, or null for anyone |
| max_attendees | integer | null | How many seats there are, or null for uncapped. A ticket issued for the session takes a seat, and a walk-in takes one when admitted ≥ 1 |
| enforces_checkin_window | boolean | Whether the start and end times refuse a tap outside them (a ticketed event: you cannot check into last night's concert) or only describe when it was meant to happen (attendance tracking, where refusing a late arrival records nothing and no record reads as not having come) default: true |
| allow_reentry | boolean | Whether a repeat tap by someone already admitted re-admits them (a recurring-access door) or is refused as already here (an event) default: false |
| admits_frozen_cards | boolean | Whether a card its holder or issuer has frozen is still admitted. False refuses it as `card_frozen`: freezing usually means the card is lost, and whoever found it would enter as its owner. True admits it and flags the presence with `disputed_reason: card_frozen` for the organizer to keep or void, for a door where a card frozen by mistake should not hold anyone up. Either way the owner can check in with another identifier default: false |
| uuid* | string | |
| slug* | string | |
| activity_uuid | string | null | The activity this session is filed under, or null for one that stands alone. An activity groups sessions; the organization owns them, so a session without one is complete rather than orphaned |
| name* | string | |
| description | string | null | |
| start_time* | string (date-time) | |
| end_time* | string (date-time) | |
| is_checkin_open | boolean | default: true |
| cancelled_at | string (date-time) | null | When it was cancelled, or null. A cancelled session admits nobody and takes no new seats, and is kept rather than deleted because its attendance and tickets are a record |
| required_prior_session_uuid | string | null | |
| series_uuid | string | null | The schedule this session was created as part of, or null for one created on its own |
| sequence_number* | integer | |
| created_at* | string (date-time) | |
| updated_at | string (date-time) | null |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X DELETE "https://api.davi.social/api/v1/sessions/{session_slug}/cancellation" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/checkin-manifestGet Session Checkin Manifest
Produce a self-contained snapshot a door can admit against offline.
Returns the session's configuration and its roster, which together carry everything the admission rules read, so a door applies them against its own clock and its own record of whom it has admitted, and reaches the same verdict the server would.
The configuration holds what is the same for everyone: checkin_open (the
session's switch and its event's, combined), the check-in window, capacity
and re-entry. The roster holds the people the per-person gates admit, with
every gate the session sets folded in, so being on it means passing all of
them. roster_kind says which set it is: the ticket's valid holders, the
members holding the required entitlement, the people who attended the
required earlier session, or none at all for a walk-in session. It is who
may enter, not who has: a person's attendance record exists only once they
are admitted.
Doors apply the rules in the order the verdict endpoints do: a person
already admitted is re-admitted or refused on allow_reentry; then a closed
switch or an enforced window refuses everyone; then a tap not on the roster
is not one the door can explain offline; then, for anyone admitted without
a ticket, a full session refuses. A ticket holder is never refused for
capacity.
Each holder is keyed by the canonical ticket wallet. Its
card_identifiers include every card owned by that wallet's user across
their wallets, because all resolve to the canonical wallet at check-in. A
bearer holder has no user, so it includes only cards bound to the ticket
wallet. A holder with no cards is unavailable to the card-only offline lane
(card_identifiers: []).
Beside the roster travel admitted, the people already present, so a
door does not admit again someone who came in through another door or
online; and reserved, the people a paused ticket gate's tickets still hold
seats for, so a door neither refuses them for capacity nor gives their
seats away. A frozen card appears in none of the three.
A walk-in session returns an empty roster. manifest_version changes only
when the config or one of the holder sets changes, so a door refreshes on
drift rather than on every fetch, and flipping either check-in switch is
such a change.
The door stops admitting offline at valid_until, and refuses offline
altogether while its clock is more than clock_tolerance_seconds from
generated_at as it receives the manifest. An admission it made offline is
uploaded to /admit with occurred_at.
The response envelope signs the exact RFC 8785 canonical JSON bytes of its
payload with a purpose-scoped Ed25519 key; /checkin-manifest/trust-keys
publishes the keys to verify it with. A ledger that cannot list a ticket's
holders answers 502 rather than a partial roster. Charged to the
expensive rate-limit bucket: it fans out across ticket holders and calls
the ledger. A session slug that names nothing answers 404.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| payload* | CheckinManifestResponse | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
object · CheckinManifestResponse
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| key_id* | string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| signature* | string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| delta_cursor | string | null | Opaque position for resuming incremental roster fetches against `/checkin-roster/delta`. A door fetches this full manifest once, then pulls only what changed from this cursor. It sits *outside* the signed `payload` deliberately: it is a timeline position, not part of the admit snapshot, so it never perturbs `manifest_version` or the signature. Null when the roster kind has no incremental path yet (`ticket_holders` and `prior_attendees`: the delta endpoint answers `resync_required` for them), so the door keeps re-fetching this manifest whole. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/checkin-manifest" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/checkin-manifest/deltaGet Session Checkin Manifest Delta
Fetch only what changed in a session's roster since a cursor — the incremental sync.
Companion to /checkin-manifest. A door fetches the full manifest once, then
pulls edits from here instead of re-fetching a whole (arena-sized) roster on
every drift. Apply the result by upserting every added and changed holder
and dropping every wallet in removed. Removals are tombstoned — a holder
absent from a delta is unchanged, not gone. Natural membership expiry sends
nothing: a door drops a holder locally the moment its entitled_until passes.
admitted_added and admitted_removed do the same for the manifest's
admitted: presences recorded and voided since the cursor, and anyone
present whose cards changed. A holder who released a card is in changed
without it. A change to the seats reserved for a paused gate's ticket
holders forces a resync.
The delta is signed as the manifest is, and a door applies it only once the
signature verifies. Its valid_until replaces the manifest's, so a door
that keeps following deltas keeps admitting offline. The response's
next_cursor is what to send on the following call.
Answers 410 resync_required when a correct delta cannot be produced, and
the door must then discard its cursor and re-fetch the full manifest: the
cursor is malformed or untrusted, older than the diff horizon, or its session
configuration has changed (config travels only in the signed manifest).
Only a walk-in session and a membership roster on the member entitlement
with no prior-session gate have an incremental path; every other roster has
no delta_cursor in its manifest and answers resync_required here.
Same access control as /checkin-manifest: a session-bound device token, or
session:attendees:read with ownership of the session. A session slug that
names nothing answers 404. Charged to the expensive rate-limit bucket: it
fans out across the roster's change timelines.
Path parameters
| session_slug* | string |
Query parameters
| cursor* | string | The opaque cursor to diff forward from — the `delta_cursor` from a prior manifest, or the `next_cursor` from a prior delta. |
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| payload* | CheckinRosterDelta | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
object · CheckinRosterDelta
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| key_id* | string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| signature* | string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/checkin-manifest/delta" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/checkin-manifest/displayGet Session Checkin Manifest Display
Fetch the roster's display names and avatars — the cosmetic half of the manifest.
Companion to /checkin-manifest. That endpoint carries the compact gating
core a door admits against; this carries the names and avatars its UI
shows, keyed by wallet_address back to the core. The two are split because
an avatar's storage URL re-signs on every fetch: folding it into the signed
manifest would churn a large payload with no roster change, so a door
refreshes the gating core on real roster drift and the display only when a
name or avatar actually changes — display_version tracks the latter.
Display never gates admission, so this response is unsigned — it is outside the offline security boundary. A door with no display shows the tap's wallet, resolves the name online at tap time, or shows nothing, and admits regardless. Entries appear only for holders with something to show: a bearer holder (no account) and a holder with neither name nor avatar have none.
Same roster and same access control as /checkin-manifest — a
session-bound device token, or session:attendees:read with ownership of
the session. A session slug that names nothing answers 404. Charged to the
expensive rate-limit bucket: it fans out across the roster.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| session_slug* | string | |||||||||||||
| roster_kind* | string | What produced the roster: the same value the manifest reports (`ticket_holders`, `membership_entitled`, `prior_attendees`, `walk_in`), so a door can tell the display matches the manifest it holds. | ||||||||||||
| display_version* | string | Digest over the stable display identity of the entries — wallet, name, and avatar *file*, not the re-signing avatar URL — and independent of `generated_at`. It changes only when a name or avatar actually changes, so a door refreshes display on real drift rather than on every fetch. Distinct from `manifest_version`: the two halves version independently. | ||||||||||||
| generated_at* | string (date-time) | |||||||||||||
| entries* | ManifestDisplayEntry[] | One entry per roster holder that has something to show, keyed by `wallet_address`. Empty for a `walk_in` session. | ||||||||||||
array items · ManifestDisplayEntry
| ||||||||||||||
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/checkin-manifest/display" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/checkin-manifest/trust-keysGet Session Checkin Manifest Trust Keys
List the keys a door accepts a signed check-in manifest under.
The current signing key, and after a rotation the one it replaced, so a door holding a manifest signed before the rotation still verifies it. A door refreshes these whenever it is online and replaces the trust keys its service file was provisioned with, which is what lets the signing key rotate without re-provisioning every door. Callable by the same tokens as the manifest.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| signing_key_id* | string | The key new manifests are signed with. |
| keys* | object | Base64url raw Ed25519 public keys by key id: the signing key, and the one it replaced while doors in the field catch up. A door replaces the trust keys from its service file with these, so a rotation needs no re-provisioning |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/checkin-manifest/trust-keys" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/eligibilityGet Session Eligibility
Tell a client what a tagged-union identifier can do for a session.
Read-only. This is the verdict /admit acts on, reached the same way, so a
door page does not reimplement the rules and cannot disagree with what
check-in will actually do.
recommended_action is the one action worth offering: checkin when an
admit would let the identity in, register when a ticket is the only thing
missing and one can still be issued, none when neither applies.
blocked_reason names why, when something stands in the way:
already_admitted: the identity is already present and the session does not allow re-entrycheckin_closed: check-in is switched off for the session or its eventtoo_early/too_late: the session refuses check-in outside its start and end times, and it is outside themmembership_required: the session is gated on a membership or tier the identity does not holdprior_session_required: the session admits only those who attended an earlier one, and this identity has notregistration_closed: a ticket is required, the identity has none, and one cannot be issued: the ticket behind it is withdrawn, sold out, or scoped to a different eventat_capacity: every seat is taken. Someone whose seat is already held, by a ticket for the session or an earlier admission, is never refused for thiscard_frozen: the card presented has been frozen by its holder or its issuer, and the session does not setadmits_frozen_cards
Unrecognized identifiers propagate as a 404, same as /admit.
Path parameters
| session_slug* | string |
Query parameters
| type* | string | Identifier type, e.g. 'wallet', 'card' |
| value* | string | Identifier value |
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| has_valid_ticket* | boolean | ||||||||||
| attendee_status* | string | The identity's attendance record at the session: `attended`, `voided`, or `none` when there is no record. | |||||||||
| can_checkin* | boolean | ||||||||||
| blocked_reason | string | null | What stands in the way, when something does. `already_admitted`: the identity is already present and the session does not allow re-entry. `checkin_closed`: check-in is switched off for the session or its event, or either is cancelled. `too_early` / `too_late`: the session refuses a first entry outside its start and end times. `membership_required`: the session is gated on a membership or tier the identity does not hold. `prior_session_required`: the session admits only those who attended an earlier one, and this identity has not. `registration_closed`: a ticket is required, the identity has none, and one cannot be issued: the ticket behind it is withdrawn, sold out, or scoped to a different event. `at_capacity`: every seat is taken. `card_frozen`: the card presented has been frozen. Treat an unfamiliar value as a plain refusal: the set grows. | |||||||||
| recommended_action* | string | The one action worth offering: `checkin` when it would succeed, `register` when a ticket is the only thing missing and one can still be issued, `none` when neither applies. | |||||||||
| user | CheckinUser | null | ||||||||||
object · CheckinUser
| |||||||||||
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/eligibility" \
-H "Authorization: Bearer <token>"/api/v1/sessions/{session_slug}/ticket-requirementGet Session Ticket Requirement
Report the ticket a session requires to register, and whether it can be issued.
Read-only and identity-free: this is the session's own configuration, not a
verdict about a particular attendee; ask /eligibility for that. A door
reads it to learn which reward to redeem when registering, so it does not
reimplement the check that the reward behind the session's ticket is still
issuable. status is the verdict:
not_required: the session admits without a ticketavailable: a ticket is required and can be issued now;ticket_reward_uuidis the reward to redeemunavailable: the session's ticket cannot be issued now: withdrawn, sold out, or scoped to a different eventat_capacity: every seat is taken, whatever the ticket's own supply says. Each ticket issued takes a seat, so a session's capacity is also how many tickets it can have
A session slug that names nothing answers 404.
Path parameters
| session_slug* | string |
Query parameters
| default_backend | string | default: "primary" |
Responses
| Field | Type | Description |
|---|---|---|
| status* | string | The ticket a session requires to register, as a verdict. `not_required`: the session admits without a ticket. `available`: a ticket is required and can be issued now — `ticket_reward_uuid` names the reward to redeem. `unavailable`: the session's ticket cannot be issued now: withdrawn, sold out, or scoped to a different event. `at_capacity`: the session's own seats are gone, whatever the ticket's supply says. Treat an unfamiliar value as a plain refusal — the set grows. |
| ticket_reward_uuid | string | null | The reward template to redeem to register, set only when `status` is `available`; null otherwise. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
| Field | Type | Description |
|---|---|---|
| errors* | object | Map of field names to error messages. Use '_root' for form-level errors. |
| message* | string | Human-readable error summary |
| code | string | null | Machine-readable error code |
| details | object | null | What the refusal is about, where it is something you can act on — the amount and currency owed on a `402`, the entitlement a tier did not grant on a `403`. Values are typed as the error carries them, so read a figure from here rather than from `errors`, whose values are always the copy a form shows against a field. |
Example request
curl -X GET "https://api.davi.social/api/v1/sessions/{session_slug}/ticket-requirement" \
-H "Authorization: Bearer <token>"