Documentation

Activities & check-ins

Run events with sessions, ticketing, and tap-to-check-in.

An activity is an event with a capacity and a check-in window. Sessions are timeslots within it. Attendees check in by presenting an identifier (a card tap, QR scan, wallet, or username), which writes an immutable proof and can feed reward triggers.

All paths are under https://api.davi.social/api/v1; managing an org's activities uses an org-scoped token.

Create an activity and sessions

curl -X POST \
  "https://api.davi.social/api/v1/organizations/ORG_SLUG/activities" \
  -H "Authorization: Bearer ORG_SCOPED_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Launch Night",
    "description": "Doors at 7pm",
    "max_attendees": 200,
    "start_time": "2026-02-01T19:00:00Z",
    "end_time": "2026-02-01T23:00:00Z",
    "requires_ticket": false
  }'

Key fields: max_attendees (null = unlimited), start_time / end_time (the check-in window), and requires_ticket + ticket_template_uuid to gate entry. Add timeslots with POST /activities/{activity_slug}/sessions (each session can override capacity and ticketing, or inherit from the activity).

| Method | Path | Scope | |---|---|---| | POST | /organizations/{organization_slug}/activities | activity:create | | GET | /activities/{activity_slug} | activity:read | | POST | /activities/{activity_slug}/sessions | activity:create | | GET | /activities/{activity_slug}/attendees | activity:attendees:read |

Tickets and registration

There is no separate "register" call — registration means holding a valid ticket. When an activity or session sets requires_ticket, an attendee must already hold the ticket, which is a reward issued from the ticket_template_uuid. Open events (requires_ticket: false) let anyone check in.

Check in

Check a person into a session with POST /sessions/{session_slug}/attend (scope activity:attend):

curl -X POST \
  "https://api.davi.social/api/v1/sessions/SESSION_SLUG/attend" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "identifier": { "type": "card", "value": "CARD_IDENTIFIER" },
    "idempotency_key": "unique-per-checkin",
    "proof_metadata": { "method": "nfc_tap" }
  }'
  • identifier is an IdentifierReftype is card, wallet, username, user_id, or link.
  • proof_metadata is optional context (e.g. method nfc_tap / qr_scan, location, device).
  • Checking in yourself (the resolved identity matches your token) is self-service; checking in others (a kiosk or door app) needs activity:attendees:manage and an org-scoped token.

The response includes status, action_taken, the on-chain attendance_proof_tx_id, and the resolved ticket / user. A kiosk can call GET /sessions/{session_slug}/eligibility first to decide the recommended action.

Check-ins are de-duplicated server-side per session and attendee, so a repeated tap won't double-record. If a request fails with no response, re-read the attendee's status rather than repeating the writeGET /sessions/{session_slug}/attendee-status tells you whether it landed.

What check-ins power

Each check-in writes an immutable proof and emits an activity.checked_in event — which drives reward triggers (e.g. activity.checked_in:count:5), the user's feed, and webhooks.

Next