# Comps & guest lists

Complimentary (comp) tickets are **free tickets issued to a named recipient** —
press, artists' guests, sponsors. Comps are real tickets: they claim tier
supply atomically (just like paid issuance), carry the standard `qr` delivery
data, emit `ticket.issued`, and count toward per-person purchase caps. Each
comp records who issued it and an optional note, and the event's comps
together form its **guest list**.

---

## POST /v1/events/{id}/comps

Issue up to 20 comp tickets to one recipient. Returns `201` with the issued
tickets as a list. The recipient is provisioned as a customer automatically,
keyed on their email.

**Scope:** `tickets:issue`

### Path params

| Param | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Event id. |

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `tier` | string | Yes | Tier to issue from — supply is claimed like a paid sale. |
| `recipient` | object | Yes | `{ "email": "...", "name": "..." }` — `email` required, `name` optional (up to 120 chars). |
| `note` | string | No | Free-form note, up to 500 chars — "press", "artist +1", … |
| `quantity` | integer | No | `1`–`20` tickets for this recipient (default `1`). The whole batch is claimed atomically — all or nothing. |

Accepts an `Idempotency-Key` header.

### Example request

```bash
curl https://api.ticketconnect.example/v1/events/evt_a1b2c3d4e5f6a7b8c9d0e1f2/comps \
  -H "Authorization: Bearer sk_test_your_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: comp-press-001" \
  -d '{
    "tier": "VIP",
    "recipient": { "email": "reviewer@musicweekly.example", "name": "Alex Reyes" },
    "note": "press",
    "quantity": 2
  }'
```

### Example response

```json
{
  "object": "list",
  "data": [
    {
      "id": "tkt_7a8b9c0d1e2f3a4b5c6d7e8f",
      "event_id": "evt_a1b2c3d4e5f6a7b8c9d0e1f2",
      "event_name": "Summer Festival 2026",
      "status": "valid",
      "tier": "VIP",
      "price": 0,
      "currency": "USD",
      "qr": { "data": "d4e5f6...opaque", "format": "QR" },
      "revoked": false,
      "created_at": "2026-07-11T09:00:00.000Z"
    }
  ],
  "has_more": false
}
```

> Errors: `400 parameter_missing` / `parameter_invalid` (bad `tier`,
> `recipient.email`, `note`, or `quantity`), `404 event_not_found`,
> `409 tier_not_found`, `409 sold_out` (the message names how many tickets
> remain when the batch doesn't fit). Emits one `ticket.issued` webhook per
> ticket.

> **Comps and money.** A comp has `price: 0` and no payment attached — a
> refund has nothing to reverse. To pull a comp back (a clawback), use
> [`POST /v1/tickets/{id}/revoke`](#api-tickets).

---

## GET /v1/events/{id}/comps

The event's guest list — its comp tickets, newest first, cursor-paginated.

**Scope:** `tickets:read`

### Path params

| Param | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Event id. |

### Query params

| Param | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | integer | No | Page size, `1`–`100` (default `20`). |
| `starting_after` | string | No | Cursor — a ticket id to page after. |

### Example request

```bash
curl "https://api.ticketconnect.example/v1/events/evt_a1b2c3d4e5f6a7b8c9d0e1f2/comps?limit=2" \
  -H "Authorization: Bearer sk_test_your_key_here"
```

### Example response

```json
{
  "object": "list",
  "data": [
    {
      "id": "tkt_7a8b9c0d1e2f3a4b5c6d7e8f",
      "tier": "VIP",
      "recipient": { "name": "Alex Reyes" },
      "note": "press",
      "issued_by": "Backend (staging)",
      "checked_in": false,
      "checked_in_at": null,
      "revoked": false,
      "revoked_at": null,
      "created_at": "2026-07-11T09:00:00.000Z"
    }
  ],
  "has_more": true
}
```

`issued_by` is the label of the API key that issued the comp (or the key's id
when no label is set) — your audit trail for who put whom on the list. The
`checked_in` / `revoked` fields track each guest's live state at the door.

> Errors: `404 event_not_found` if the event does not exist or is not yours.
