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

# Create Attendee

> Create one or more tickets for a contact on an event

# Create Attendee

Creates one or more tickets ("attendees") on an event your API key's organization owns. Mirrors the dashboard's manual-add flow:

* Upserts the contact (creates or updates by email).
* If an `invited` ticket exists for this email/contact on the event, it's upgraded and counted toward the requested quantity.
* All tickets in a single request share one `payment_id` so the QR ticket page groups them.
* Capacity is enforced against `quantity_total` on the ticket class and the event's `capacity`.

By default no confirmation email is sent — pass `send_email: true` to opt in.

Requires the `attendees:write` scope.

## Idempotency

Pass an `Idempotency-Key` header (max 255 chars) to make POST retries safe. The first request executes the create; subsequent requests with the same key within 24 hours replay the original response verbatim — including the original status code — and add an `Idempotent-Replay: true` response header. Keys are scoped per API key.

Two concurrent requests with the same key return `409 idempotent_request_in_progress` to the second caller.

## Path Parameters

<ParamField path="eventId" type="string" required>
  The unique identifier of the event.
</ParamField>

## Request Body

<ParamField body="ticket_class_id" type="string" required>
  The ID of the ticket class to issue.
</ParamField>

<ParamField body="contact" type="object" required>
  <Expandable>
    <ParamField body="email" type="string" required>Attendee email address.</ParamField>
    <ParamField body="first_name" type="string" required>Attendee first name (1..120 chars).</ParamField>
    <ParamField body="last_name" type="string" required>Attendee last name (1..120 chars).</ParamField>
    <ParamField body="phone_number" type="string">Optional phone number (max 40 chars).</ParamField>
  </Expandable>
</ParamField>

<ParamField body="quantity" type="integer">
  How many tickets to create for this contact (1..100). Defaults to `1`.
</ParamField>

<ParamField body="status" type="string">
  Override the initial status. Allowed: `valid`, `pending_approval`, `checked_in`, `invited`. Defaults to `pending_approval` when the ticket class requires approval, otherwise `valid`.
</ParamField>

<ParamField body="payment_method" type="string">
  Recorded on each ticket. `cash` (default), `free`, or `external`. Paid tickets continue to flow through Stripe — this field is informational for manually-recorded sales.
</ParamField>

<ParamField body="send_email" type="boolean">
  When `true`, the event's confirmation email is sent to the attendee. Default `false`.
</ParamField>

## Response

Returns `201 Created` with:

<ResponseField name="data" type="array">
  Array of attendee (ticket) objects — see [Get Attendee](/api-reference/attendees/get-attendee).
</ResponseField>

<ResponseField name="payment_id" type="string">
  Shared payment ID across all tickets in the batch.
</ResponseField>

<ResponseField name="quantity" type="integer">
  Number of tickets actually created (may differ from request when an existing invited ticket was upgraded).
</ResponseField>

## Errors

* `400 Validation failed` — invalid body shape.
* `404 Event not found` / `Ticket class not found` — resource missing or not owned by your org.
* `409` — capacity exceeded; the message lists how many seats remain.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST -H "X-API-KEY: your_api_key" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: attendee-$(uuidgen)" \
    -d '{
      "ticket_class_id": "prod_AbCdEf",
      "contact": {
        "email": "jane@example.com",
        "first_name": "Jane",
        "last_name": "Doe"
      },
      "quantity": 2,
      "send_email": false
    }' \
    https://www.gomry.com/api/v1/events/AbCdEfGhIjKlMnOpQrSt/attendees
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://www.gomry.com/api/v1/events/AbCdEfGhIjKlMnOpQrSt/attendees",
    {
      method: "POST",
      headers: {
        "X-API-KEY": "your_api_key",
        "Content-Type": "application/json",
        "Idempotency-Key": crypto.randomUUID(),
      },
      body: JSON.stringify({
        ticket_class_id: "prod_AbCdEf",
        contact: {
          email: "jane@example.com",
          first_name: "Jane",
          last_name: "Doe",
        },
        quantity: 2,
      }),
    }
  );
  const { data, payment_id, quantity } = await response.json();
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Created theme={null}
  {
    "data": [
      {
        "id": "tkt_AAA",
        "status": "valid",
        "ticket_class_id": "prod_AbCdEf",
        "ticket_class_name": "Early Bird",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com",
        "created_at": "2026-05-26T12:00:00.000Z",
        "updated_at": "2026-05-26T12:00:00.000Z"
      },
      {
        "id": "tkt_BBB",
        "status": "valid",
        "ticket_class_id": "prod_AbCdEf",
        "ticket_class_name": "Early Bird",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com",
        "created_at": "2026-05-26T12:00:00.000Z",
        "updated_at": "2026-05-26T12:00:00.000Z"
      }
    ],
    "payment_id": "pay_XYZ",
    "quantity": 2
  }
  ```
</ResponseExample>
