> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orriven.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API quickstart

> From a fresh key to a checked-in attendee: create an event, price a ticket, watch remaining seats, register someone and scan them in.

This walkthrough runs the whole flow with `curl`. You need a key ([generate one](/en/developers/api-keys)) and your API host:

```bash theme={null}
export BASE="https://openapi.orriven.com"   # local development: http://localhost:3002
export KEY="osk_…"                              # the secret you copied at creation
```

<Steps>
  <Step title="1 — Create an event">
    ```bash theme={null}
    curl -s -X POST "$BASE/v1/events" \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d '{"name":"Autumn Summit","timezone":"Asia/Shanghai","startsAt":"2026-09-01T09:00:00+08:00"}'
    ```

    The event is born **draft** — invisible to the public until you publish it. Keep the returned `id`.
  </Step>

  <Step title="2 — Create a ticket type">
    ```bash theme={null}
    curl -s -X POST "$BASE/v1/events/$EVENT/ticket-types" \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d '{"name":"General","capacity":100,"priceAmount":12000}'
    ```

    `priceAmount` is minor units of the event's currency — `12000` is ¥120.00 for a CNY event. `0` (or omitting it) makes the ticket free. Keep the returned `id`.
  </Step>

  <Step title="3 — Open the ticket for sale">
    Ticket types are born **draft** too. Opening is a status change:

    ```bash theme={null}
    curl -s -X PATCH "$BASE/v1/events/$EVENT/ticket-types/$TYPE" \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d '{"status":"open"}'
    ```
  </Step>

  <Step title="4 — Watch remaining seats">
    ```bash theme={null}
    curl -s -H "Authorization: Bearer $KEY" \
      "$BASE/v1/events/$EVENT/ticket-types/$TYPE/availability"
    ```

    ```json theme={null}
    { "capacity": 100, "confirmed": 0, "waitlisted": 0, "held": 0, "remaining": 100 }
    ```

    `held` counts seats inside live order holds from the public checkout. The numbers are advisory — the binding check still happens at registration time, so you can never oversell by reading a stale value.
  </Step>

  <Step title="5 — Register an attendee">
    ```bash theme={null}
    curl -s -X POST "$BASE/v1/events/$EVENT/registrations" \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d "{\"email\":\"ada@example.com\",\"name\":\"Ada\",\"registrationTypeId\":\"$TYPE\"}"
    ```

    `201` with `"created": true` — and note the registration's `checkinCode`, the badge credential. Registering the same email again answers `200` with `"created": false` and the existing registration: repeats are acknowledged, never duplicated.
  </Step>

  <Step title="6 — Approve, if the ticket requires it">
    On a ticket with **approval mode**, API registrations land `pending` — the API records the application, it does not make the admission decision. Decide it explicitly:

    ```bash theme={null}
    curl -s -X POST "$BASE/v1/events/$EVENT/registrations/$REG/approve" \
      -H "Authorization: Bearer $KEY"
    ```
  </Step>

  <Step title="7 — Check them in">
    ```bash theme={null}
    curl -s -X POST "$BASE/v1/events/$EVENT/checkins" \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d '{"checkinCode":"CHK-…","subjectType":"event"}'
    ```

    `201` records the arrival; scanning the same badge again answers `200` with `"alreadyCheckedIn": true` — acknowledged, not an error.
  </Step>
</Steps>

## What you just exercised

* **Draft-first lifecycles** — events and ticket types are invisible until you open them, same as the console.
* **The capacity gate** — when `confirmed` reaches `capacity`, the next registration answers `412` (or lands `waitlisted` if the ticket allows a waitlist).
* **Idempotent repeats** — duplicate registrations and duplicate scans acknowledge instead of erroring, so retries in your integration are safe.
* **Automations** — if this Business Unit has an "attendee added" or check-in automation, your API calls just triggered it.

## Related

<CardGroup cols={2}>
  <Card title="Endpoint reference" icon="book" href="/en/developers/api-reference">
    Everything else: codes, add-ons, bundles, orders, errors, limits.
  </Card>

  <Card title="Ticket types" icon="tickets" href="/en/ticketing/ticket-types">
    Capacity, waitlists, approval mode and visibility, explained.
  </Card>
</CardGroup>
