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

# Endpoint reference

> Every resource of the Developer API — methods, paths, status codes, the error envelope, and rate limits.

All paths live under `$BASE/v1` and require `Authorization: Bearer <secret>`. This page is the map; the territory lives in two places:

* The **Endpoints** group in this tab documents every operation individually — full request and response schemas, field by field, with a **Try it** playground you can call with your own key.
* The API also describes itself: `GET $BASE/openapi.json` is the OpenAPI 3.1 spec (generate a client from it), and `$BASE/docs` serves the same interactive reference straight from your deployment.

## Events

| Method & path                       | Does                                                                                |
| ----------------------------------- | ----------------------------------------------------------------------------------- |
| `GET /v1/events`                    | List the Business Unit's events, all statuses                                       |
| `POST /v1/events`                   | Create (born **draft**); `name`, `timezone`, optional `startsAt`/`endsAt`           |
| `GET /v1/events/{eventId}`          | One event                                                                           |
| `PATCH /v1/events/{eventId}`        | Update name, dates, timezone, `status` (`draft`/`published`/`archived`), `currency` |
| `POST /v1/events/{eventId}/archive` | Archive — events are never deleted                                                  |

Console rules apply unchanged: publishing needs a start time (`400`); the **currency locks** once the event has taken an order (`412`); moving the start **date** clears the agenda — the first attempt answers `412`, restate with `"confirmAgendaReset": true` to confirm.

## Ticket types

| Method & path                              | Does                                                                                                                                                 |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/ticket-types`    | List with `counts` (confirmed / waitlisted)                                                                                                          |
| `POST …/ticket-types`                      | Create (born **draft**): `name`, `capacity` (null = unlimited), `priceAmount`, `allowWaitlist`, `isPublic`, `requiresApproval`, `opensAt`/`closesAt` |
| `GET …/ticket-types/{typeId}`              | One type                                                                                                                                             |
| `PATCH …/ticket-types/{typeId}`            | Any of the above plus `status` — the lifecycle is `draft → open ⇄ closed → archived`                                                                 |
| `GET …/ticket-types/{typeId}/availability` | `{ capacity, confirmed, waitlisted, held, remaining }`                                                                                               |

Repricing never rewrites sold orders — amounts on an order are purchase-time snapshots. Perk bindings, registration forms and refund policies are configured in the console, not over the API.

## Registrations

| Method & path                            | Does                                                                                                 |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/registrations` | List, newest first; `?status=` filters                                                               |
| `POST …/registrations`                   | Register: `email`, optional `name`, `registrationTypeId` (required when the event uses ticket types) |
| `GET …/registrations/{id}`               | One registration                                                                                     |
| `POST …/registrations/{id}/approve`      | Decide a `pending` application                                                                       |
| `POST …/registrations/{id}/reject`       | Decide it the other way; optional `reason`                                                           |
| `POST …/registrations/{id}/cancel`       | Release the seat (and the code use, if a code admitted them)                                         |
| `GET …/registrations/{id}/perks`         | The person's effective perks: ticket ∪ code ∪ individual grants                                      |

Behaviour to design for:

* **Approval-mode tickets land `pending`** when created over the API — unlike a console operator, the API is not an admission decision. Approve explicitly.
* **Full ticket** → `412` (or the registration lands `waitlisted` if the ticket allows it).
* **Repeat email** → `200` with `"created": false` and the existing registration — never a duplicate, never an error.
* Approve/reject only move `pending` rows; anything else answers `412`.
* Every registration carries a `checkinCode` (`CHK-…`) — the badge credential for check-in.

## Redemption codes

| Method & path                               | Does                                                                                                                                                   |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GET /v1/events/{eventId}/redemption-codes` | List with live `uses` counts                                                                                                                           |
| `POST …/redemption-codes`                   | Mint: `registrationTypeId`, optional `count` (batch), `code` (custom, forces count 1), `label`, `maxUses` (default 1, null = unlimited), `expiresAt`   |
| `GET …/redemption-codes/lookup?code=`       | Validate a buyer's code: the ticket it unlocks (hidden ones included), the admission's perks, the discounted price. Every invalid form is the same 404 |
| `POST …/redemption-codes/{codeId}/disable`  | Disable — codes are never deleted                                                                                                                      |

A custom `code` that already exists in the event answers `409`.

## Add-ons and bundles

| Method & path                                                       | Does                                                                                                    |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `GET/POST /v1/events/{eventId}/addons`, `GET/PATCH …/addons/{id}`   | Add-on configuration; the sellable lifecycle (`draft → open ⇄ closed → archived`)                       |
| `GET/POST /v1/events/{eventId}/bundles`, `GET/PATCH …/bundles/{id}` | Bundle configuration                                                                                    |
| `PUT …/bundles/{id}/items`                                          | Replace the bundle's whole contents: `[{ itemType: "registration_type" \| "addon", itemId, quantity }]` |

Every bundle item must be a real ticket type or add-on of the same event (`400` otherwise).

## Orders and checkout

| Method & path                         | Does                                                                                                                                                                                                               |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GET /v1/events/{eventId}/orders`     | List with line items                                                                                                                                                                                               |
| `GET …/orders/{orderId}`              | One order                                                                                                                                                                                                          |
| `POST …/orders`                       | Place: `email`, optional `name`, `items` (`registration_type` / `addon` / `bundle`), optional `redemptionCode`, `responses`. Holds places 15 minutes; a buyer already registered answers `alreadyRegistered: true` |
| `POST …/orders/{orderNumber}/confirm` | Free order → settles and fulfils (`status: "paid"`). Paid order → `status: "awaiting_payment"` + `paymentUrl` (hosted Stripe); requires `successUrl`/`cancelUrl` (https; localhost http allowed)                   |
| `POST …/orders/{orderNumber}/cancel`  | Releases the hold now; idempotent                                                                                                                                                                                  |

Settlement of paid orders arrives by the platform's Stripe webhook — poll the order until `paid`. Refunds stay a console decision. The whole flow, end to end: [Headless checkout](/en/developers/checkout).

## Check-ins

| Method & path                       | Does                                                                                                                                                                             |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/checkins` | List; filters `?subjectType=`, `?subjectId=`, `?registrationId=`                                                                                                                 |
| `POST …/checkins`                   | Record: `registrationId` **or** `checkinCode`, plus `subjectType` (`event` / `session` / `venue`), `subjectId` for session or venue doors, optional `method` (`scan` / `manual`) |

Only a `confirmed` registration can check in (`412`). A second scan at the same door answers `200` with `"alreadyCheckedIn": true`.

## Program and venues

| Method & path                       | Does                                                                                                             |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/sessions` | The agenda in time order: title, times, `venueId`, and the session's own gate as `perkIds` (empty = open to all) |
| `GET /v1/events/{eventId}/speakers` | The line-up: name, title, bio, `registrationId`, `sessionIds`                                                    |
| `GET /v1/events/{eventId}/venues`   | The rooms, each with its own gate as `perkIds` — a session inherits its venue's gate on top of its own           |

## Attendees

| Method & path                        | Does                                                                            |
| ------------------------------------ | ------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/attendees` | Read-only: one entry per person with their registration ids and standing status |

## The error envelope

Every error, whatever the status, wears the same shape:

```json theme={null}
{
  "error": {
    "code": 404,
    "status": "NOT_FOUND",
    "message": "Event not found.",
    "details": []
  }
}
```

| HTTP | `status`              | When                                                                                                                                                 |
| ---- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `INVALID_ARGUMENT`    | Malformed body or parameters; `details` carries field-level issues                                                                                   |
| 401  | `UNAUTHENTICATED`     | Missing, unknown, revoked or expired key — deliberately indistinguishable                                                                            |
| 404  | `NOT_FOUND`           | The resource is not in your key's Business Unit. A foreign id and a nonexistent id answer identically — the API never confirms what exists elsewhere |
| 409  | `ALREADY_EXISTS`      | A custom redemption code that already exists                                                                                                         |
| 412  | `FAILED_PRECONDITION` | A business rule blocks it: sold out, currency locked, not pending, not confirmed, agenda reset unconfirmed                                           |
| 429  | `RESOURCE_EXHAUSTED`  | Rate limit — see below                                                                                                                               |

## Rate limits and retries

Each key may make **120 requests per minute**; beyond that, requests answer `429` until the window resets. Design your integration to back off on `429` — and lean on the API's idempotent behaviours (repeat registrations and repeat scans acknowledge rather than fail), which make retrying writes safe.

## Related

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/en/developers/quickstart">
    The reference, exercised end to end.
  </Card>

  <Card title="Orders" icon="receipt" href="/en/ticketing/orders">
    What the read-only orders you see actually are.
  </Card>
</CardGroup>
