API Reference

sessions

16 endpoints

  • /api/v1/sessions
GET/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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
requires_ticketboolean

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_uuidstring | null

The reward template whose valid tickets the gate accepts, or null for none named

required_entitlementstring | 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_attendeesinteger | 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_windowboolean

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_reentryboolean

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_cardsboolean

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_uuidstring | 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
descriptionstring | null
start_time*string (date-time)
end_time*string (date-time)
is_checkin_openboolean

default: true

cancelled_atstring (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_uuidstring | null
series_uuidstring | 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_atstring (date-time) | null
401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
PATCH/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_backendstring

default: "primary"

Request body*application/json

FieldTypeDescription
requires_ticketboolean | 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_uuidstring | string (uuid) | null

The reward template whose valid tickets the gate accepts, or null for none named

required_entitlementstring | 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_attendeesinteger | 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_windowboolean | 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_reentryboolean | 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_cardsboolean | 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_holdersboolean

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_uuidstring | 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

namestring | null

Name of the session

descriptionstring | null

Session description

start_timestring (date-time) | null

Session start time

end_timestring (date-time) | null

Session end time

is_checkin_openboolean | null

Manual toggle for check-in

required_prior_session_uuidstring | string (uuid) | null

Another session of the same activity that must have been attended before this one admits anyone. None = no such gate

Responses

200Successful Response
FieldTypeDescription
requires_ticketboolean

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_uuidstring | null

The reward template whose valid tickets the gate accepts, or null for none named

required_entitlementstring | 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_attendeesinteger | 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_windowboolean

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_reentryboolean

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_cardsboolean

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_uuidstring | 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
descriptionstring | null
start_time*string (date-time)
end_time*string (date-time)
is_checkin_openboolean

default: true

cancelled_atstring (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_uuidstring | null
series_uuidstring | 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_atstring (date-time) | null
400Invalid request
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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 */ }'
DELETE/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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
message*string

Success or status message

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
POST/api/v1/sessions/{session_slug}/admit

Admit 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_taken is checkin when this call recorded the attendance, reentry when it re-admitted someone already present at a session that allows re-entry, and null when it was a retry of an admit that already succeeded (same idempotency_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 /admit again; the second call finds the ticket and admits.
  • blocked: it cannot be admitted and registering would not help; blocked_reason says why, with the same values /eligibility returns. already_admitted means 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_backendstring

default: "primary"

Request body*application/json

FieldTypeDescription
identifier*IdentifierRef

object · IdentifierRef

FieldTypeDescription
type*enum

How to interpret `value`

value*string

Identifier value (card uid, wallet address, username, user uuid, or Davi link)

idempotency_keystring | null
proof_metadataobject | null
occurred_atstring (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

200Successful Response
FieldTypeDescription
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_takenstring | 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_actionsstring[]

For `needs_confirm`, the actions the door can take next — currently `register`. Empty otherwise.

blocked_reasonstring | 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_idstring | 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_statusstring | 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_reasonstring | 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

ticketHeldTicketRef | null

object · HeldTicketRef

FieldTypeDescription
transaction_id*string

Ledger transaction ID of the redeemed ticket reward

template_uuid*string

UUID of the reward template the ticket was issued from

wallet_address*string

Wallet address holding the valid ticket

userCheckinUser | null

object · CheckinUser

FieldTypeDescription
display_namestring | null
avatar_urlstring | null
400Invalid request
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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 */ }'
GET/api/v1/sessions/{session_slug}/attendee-status

Get 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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
uuid*string
activity_uuidstring | null

Denormalized from the session, so it is null for an attendee of a session that stands alone

session_uuidstring | null
wallet_address*string
user_uuidstring | null
status*enum
sourceenum

Who produced the record: `door` (admitted at a door), `self` (the person checked themselves in) or `operator` (a correction)

default: "door"

recorded_by_user_uuidstring | null

The operator who last changed the record, for `operator` rows

reasonstring | null

Why an operator recorded or voided it

disputed_reasonstring | 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_atstring (date-time) | null
last_admitted_atstring (date-time) | null

The latest admission: the check-in, then each re-entry where the session allows re-entry

additional_dataobject | null
created_at*string (date-time)
updated_atstring (date-time) | null
usernamestring | null
display_namestring | null
avatar_urlstring | null
proof_tx_idstring | null
proof_statusstring | null
proof_verifiedboolean | null
proof_tx_hashstring | null
proof_amountnumber | null
401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/api/v1/sessions/{session_slug}/attendees

List Session Attendees

List attendees for a specific session.

Path parameters

session_slug*string

Query parameters

include_proofboolean

Include proof transaction info in response

default: false

default_backendstring

default: "primary"

pageinteger

default: 1 · ≥ 1

page_sizeinteger

default: 20 · ≥ 1 · ≤ 100

sort_bystring | null
sort_orderstring

default: "asc"

Responses

200Successful Response
FieldTypeDescription
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

FieldTypeDescription
uuid*string
activity_uuidstring | null

Denormalized from the session, so it is null for an attendee of a session that stands alone

session_uuidstring | null
wallet_address*string
user_uuidstring | null
status*enum
sourceenum

Who produced the record: `door` (admitted at a door), `self` (the person checked themselves in) or `operator` (a correction)

default: "door"

recorded_by_user_uuidstring | null

The operator who last changed the record, for `operator` rows

reasonstring | null

Why an operator recorded or voided it

disputed_reasonstring | 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_atstring (date-time) | null
last_admitted_atstring (date-time) | null

The latest admission: the check-in, then each re-entry where the session allows re-entry

additional_dataobject | null
created_at*string (date-time)
updated_atstring (date-time) | null
usernamestring | null
display_namestring | null
avatar_urlstring | null
proof_tx_idstring | null
proof_statusstring | null
proof_verifiedboolean | null
proof_tx_hashstring | null
proof_amountnumber | null
401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
uuid*string
activity_uuidstring | null

Denormalized from the session, so it is null for an attendee of a session that stands alone

session_uuidstring | null
wallet_address*string
user_uuidstring | null
status*enum
sourceenum

Who produced the record: `door` (admitted at a door), `self` (the person checked themselves in) or `operator` (a correction)

default: "door"

recorded_by_user_uuidstring | null

The operator who last changed the record, for `operator` rows

reasonstring | null

Why an operator recorded or voided it

disputed_reasonstring | 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_atstring (date-time) | null
last_admitted_atstring (date-time) | null

The latest admission: the check-in, then each re-entry where the session allows re-entry

additional_dataobject | null
created_at*string (date-time)
updated_atstring (date-time) | null
usernamestring | null
display_namestring | null
avatar_urlstring | null
proof_tx_idstring | null
proof_statusstring | null
proof_verifiedboolean | null
proof_tx_hashstring | null
proof_amountnumber | null
401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
PATCH/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_backendstring

default: "primary"

Request body*application/json

FieldTypeDescription
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

200Successful Response
FieldTypeDescription
uuid*string
activity_uuidstring | null

Denormalized from the session, so it is null for an attendee of a session that stands alone

session_uuidstring | null
wallet_address*string
user_uuidstring | null
status*enum
sourceenum

Who produced the record: `door` (admitted at a door), `self` (the person checked themselves in) or `operator` (a correction)

default: "door"

recorded_by_user_uuidstring | null

The operator who last changed the record, for `operator` rows

reasonstring | null

Why an operator recorded or voided it

disputed_reasonstring | 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_atstring (date-time) | null
last_admitted_atstring (date-time) | null

The latest admission: the check-in, then each re-entry where the session allows re-entry

additional_dataobject | null
created_at*string (date-time)
updated_atstring (date-time) | null
usernamestring | null
display_namestring | null
avatar_urlstring | null
proof_tx_idstring | null
proof_statusstring | null
proof_verifiedboolean | null
proof_tx_hashstring | null
proof_amountnumber | null
400Invalid request
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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 */ }'
POST/api/v1/sessions/{session_slug}/cancellation

Cancel 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_backendstring

default: "primary"

Responses

200The session, cancelled
FieldTypeDescription
requires_ticketboolean

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_uuidstring | null

The reward template whose valid tickets the gate accepts, or null for none named

required_entitlementstring | 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_attendeesinteger | 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_windowboolean

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_reentryboolean

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_cardsboolean

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_uuidstring | 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
descriptionstring | null
start_time*string (date-time)
end_time*string (date-time)
is_checkin_openboolean

default: true

cancelled_atstring (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_uuidstring | null
series_uuidstring | 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_atstring (date-time) | null
400Invalid request
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
DELETE/api/v1/sessions/{session_slug}/cancellation

Reinstate 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_backendstring

default: "primary"

Responses

200The session, reinstated
FieldTypeDescription
requires_ticketboolean

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_uuidstring | null

The reward template whose valid tickets the gate accepts, or null for none named

required_entitlementstring | 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_attendeesinteger | 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_windowboolean

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_reentryboolean

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_cardsboolean

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_uuidstring | 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
descriptionstring | null
start_time*string (date-time)
end_time*string (date-time)
is_checkin_openboolean

default: true

cancelled_atstring (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_uuidstring | null
series_uuidstring | 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_atstring (date-time) | null
400Invalid request
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/api/v1/sessions/{session_slug}/checkin-manifest

Get 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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
payload*CheckinManifestResponse

object · CheckinManifestResponse

FieldTypeDescription
session*ManifestSessionConfig

object · ManifestSessionConfig

FieldTypeDescription
slug*string
checkin_open*boolean

Whether check-in is open: the session's own switch and its event's, combined. While false the door refuses anyone not yet admitted as `checkin_closed`. Flipping either switch changes the manifest, so a door polling it hears within one fetch.

requires_ticket*boolean

Whether the ticket gate is on. When it is, the roster is the ticket's holders and a holder is never refused for capacity: their seat was counted when the ticket was issued.

ticket_reward_uuidstring | null

The reward template the ticket gate checks, or null for none named. Named while the gate is off too, so it is not a sign the gate is on.

capacityinteger | null

How many seats there are, or null for uncapped. Offline, a door counts the seats taken as the union, by wallet, of `admitted`, `reserved` and the admissions it has made itself since. It cannot see another offline door's admissions, so two offline doors on one capped session can together pass the cap.

required_entitlementstring | null

Membership entitlement key gating the session, or null. Everyone on the roster already satisfies it, so it is here for display, not a gate the door re-runs.

allow_reentry*boolean

Whether a repeat tap by someone already admitted re-admits them (true, a recurring-access door) or is refused as 'already here' (false, an event). The door evaluates this against its own local admit state; online admit is idempotent regardless.

admits_frozen_cardsboolean

Whether the session admits a frozen card. When true the roster's card lists include frozen cards, and an admission by one is flagged when the door uploads it; when false they are left out, so a frozen card is not on the roster at all.

default: false

checkin_window*ManifestCheckinWindow
roster_kind*string

What produced the roster, and how a door treats it. Every gate the session sets is folded into the roster, so being on it means passing all of them. `ticket_holders`: the ticket's valid holders. `membership_entitled`: the organization's active members holding the session's `required_entitlement`, each with an `entitled_until`. `prior_attendees`: the people who attended the session this one requires. `walk_in`: no roster; the door admits any resolvable tap (`holders` empty). A tap not on a roster is not a refusal the door can explain offline: it asks the server when it can, and refuses when it cannot. Treat an unfamiliar value the same way.

manifest_version*string

Digest of the config and roster, independent of `generated_at`. It changes only when the holder set or config changes, so a door can tell 'same manifest' from 'refresh needed' without diffing.

generated_at*string (date-time)
valid_until*string (date-time)

When the door stops admitting offline from this manifest: an hour after the session ends, and never more than a day after `generated_at`. A manifest describes the roster when it was built, and one kept past this no longer describes anyone: refunds, lapsed members, a closed session, a door since revoked. Past it the door admits only online, and fetches a fresh manifest

clock_tolerance_seconds*integer

How far the door's clock may differ from `generated_at` when it receives this manifest. A door whose clock is further out refuses offline rather than judging the session's hours against the wrong time

holders*ManifestHolder[]

The roster the door admits against. Empty for a `walk_in` session.

array items · ManifestHolder

FieldTypeDescription
wallet_address*string

The wallet holding the valid ticket.

card_identifiers*string[]

`managed_cards.identifier` for every card owned by the holder's user across their wallets (or the ticket wallet for a bearer holder) — the keys a tap resolves against offline. Empty means unavailable to the card-only offline lane.

entitled_untilstring (date-time) | null

When this holder's entitlement lapses, for a membership roster — the membership's term end. A door drops the holder from its own clock once this passes, so a lapsed member is not admitted offline. Null for a ticket holder (the whole roster expires with the manifest) and for a one-time membership that never expires.

admitted*ManifestHolder[]

The people already present, as of `generated_at`, whatever the roster kind. A door treats a tap from one of them as a person it admitted itself: `already_admitted` where re-entry is off, a re-entry where it is on. As fresh as the door's last fetch: two doors both offline since cannot know about each other's admissions

array items · ManifestHolder

FieldTypeDescription
wallet_address*string

The wallet holding the valid ticket.

card_identifiers*string[]

`managed_cards.identifier` for every card owned by the holder's user across their wallets (or the ticket wallet for a bearer holder) — the keys a tap resolves against offline. Empty means unavailable to the card-only offline lane.

entitled_untilstring (date-time) | null

When this holder's entitlement lapses, for a membership roster — the membership's term end. A door drops the holder from its own clock once this passes, so a lapsed member is not admitted offline. Null for a ticket holder (the whole roster expires with the manifest) and for a one-time membership that never expires.

reserved*ManifestHolder[]

The people a ticket holds a seat for while the session's ticket gate is paused. Capacity never refuses them, and each counts as a seat taken whether or not they have come. Empty unless the session is capped and its gate is off

array items · ManifestHolder

FieldTypeDescription
wallet_address*string

The wallet holding the valid ticket.

card_identifiers*string[]

`managed_cards.identifier` for every card owned by the holder's user across their wallets (or the ticket wallet for a bearer holder) — the keys a tap resolves against offline. Empty means unavailable to the card-only offline lane.

entitled_untilstring (date-time) | null

When this holder's entitlement lapses, for a membership roster — the membership's term end. A door drops the holder from its own clock once this passes, so a lapsed member is not admitted offline. Null for a ticket holder (the whole roster expires with the manifest) and for a one-time membership that never expires.

key_id*string
signature*string
delta_cursorstring | 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.

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/api/v1/sessions/{session_slug}/checkin-manifest/delta

Get 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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
payload*CheckinRosterDelta

object · CheckinRosterDelta

FieldTypeDescription
session_slug*string
roster_kind*string

What produced the roster — the same value the manifest reports. A door that gets a delta for a different kind than it holds should resync.

base_cursor*string

The cursor this delta was computed from — the one the caller sent.

next_cursor*string

The cursor to send on the next incremental fetch. It advances past this delta's changes; the caller stores it in place of `base_cursor`.

generated_at*string (date-time)

When this delta was computed, as a manifest's is.

valid_until*string (date-time)

The door's new offline deadline, replacing the manifest's `valid_until`: a door that keeps applying deltas keeps admitting offline, on the same terms a fresh manifest would give it.

added*ManifestHolder[]

Holders new to the roster since the cursor. Upsert each.

array items · ManifestHolder

FieldTypeDescription
wallet_address*string

The wallet holding the valid ticket.

card_identifiers*string[]

`managed_cards.identifier` for every card owned by the holder's user across their wallets (or the ticket wallet for a bearer holder) — the keys a tap resolves against offline. Empty means unavailable to the card-only offline lane.

entitled_untilstring (date-time) | null

When this holder's entitlement lapses, for a membership roster — the membership's term end. A door drops the holder from its own clock once this passes, so a lapsed member is not admitted offline. Null for a ticket holder (the whole roster expires with the manifest) and for a one-time membership that never expires.

removed*string[]

Wallet addresses of holders removed since the cursor — tombstones. Drop each from the local store. A wallet the door does not hold is ignored.

changed*ManifestHolder[]

Holders already on the roster whose gating core changed since the cursor (expiry moved, cards added). Upsert each.

array items · ManifestHolder

FieldTypeDescription
wallet_address*string

The wallet holding the valid ticket.

card_identifiers*string[]

`managed_cards.identifier` for every card owned by the holder's user across their wallets (or the ticket wallet for a bearer holder) — the keys a tap resolves against offline. Empty means unavailable to the card-only offline lane.

entitled_untilstring (date-time) | null

When this holder's entitlement lapses, for a membership roster — the membership's term end. A door drops the holder from its own clock once this passes, so a lapsed member is not admitted offline. Null for a ticket holder (the whole roster expires with the manifest) and for a one-time membership that never expires.

admitted_addedManifestHolder[]

People recorded present since the cursor, for the manifest's `admitted`. Upsert each.

array items · ManifestHolder

FieldTypeDescription
wallet_address*string

The wallet holding the valid ticket.

card_identifiers*string[]

`managed_cards.identifier` for every card owned by the holder's user across their wallets (or the ticket wallet for a bearer holder) — the keys a tap resolves against offline. Empty means unavailable to the card-only offline lane.

entitled_untilstring (date-time) | null

When this holder's entitlement lapses, for a membership roster — the membership's term end. A door drops the holder from its own clock once this passes, so a lapsed member is not admitted offline. Null for a ticket holder (the whole roster expires with the manifest) and for a one-time membership that never expires.

admitted_removedstring[]

Wallet addresses of presences voided since the cursor. Drop each from `admitted`: the person may be admitted again.

key_id*string
signature*string
401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/api/v1/sessions/{session_slug}/checkin-manifest/display

Get 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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
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

FieldTypeDescription
wallet_address*string

The gating-core holder this display belongs to.

namestring | null
avatar_urlstring | null
401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/api/v1/sessions/{session_slug}/checkin-manifest/trust-keys

Get 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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
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

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/api/v1/sessions/{session_slug}/eligibility

Get 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-entry
  • checkin_closed: check-in is switched off for the session or its event
  • too_early / too_late: the session refuses check-in outside its start and end times, and it is outside them
  • 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. Someone whose seat is already held, by a ticket for the session or an earlier admission, is never refused for this
  • card_frozen: the card presented has been frozen by its holder or its issuer, and the session does not set admits_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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
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_reasonstring | 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.

userCheckinUser | null

object · CheckinUser

FieldTypeDescription
display_namestring | null
avatar_urlstring | null
401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"
GET/api/v1/sessions/{session_slug}/ticket-requirement

Get 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 ticket
  • available: a ticket is required and can be issued now; ticket_reward_uuid is the reward to redeem
  • unavailable: the session's ticket cannot be issued now: withdrawn, sold out, or scoped to a different event
  • at_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_backendstring

default: "primary"

Responses

200Successful Response
FieldTypeDescription
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_uuidstring | null

The reward template to redeem to register, set only when `status` is `available`; null otherwise.

401Authentication failed
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

403Insufficient permissions
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

404Resource not found
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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.

422Validation error
FieldTypeDescription
errors*object

Map of field names to error messages. Use '_root' for form-level errors.

message*string

Human-readable error summary

codestring | null

Machine-readable error code

detailsobject | 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>"