Skip to content

Latest commit

 

History

History
155 lines (121 loc) · 3.74 KB

File metadata and controls

155 lines (121 loc) · 3.74 KB

API Specification

Base URL: /api/v1

All endpoints require:

  • X-Mock-User-Id: uuid (Phase 1 auth)
  • Idempotency-Key: uuid for all write operations

Endpoints

GET /events/{eventId}/seats

→ List available seats with price/position

POST /events/{eventId}/hold

Hold seats (creates PENDING reservation)

Request headers:

  • X-Mock-User-Id: uuid
  • Idempotency-Key: a0eebc999c0b4ef8bb6d6bb9bd380a11 (UUID v4 lowercase no hyphens)

Request body:

{
  "seats": [
    { "seatId": "uuid" },
    { "seatId": "uuid" }
  ]
}

Success (201 Created):

{
  "data": {
    "reservationId": "uuid",
    "expiresAt": "2025-11-22T10:15:00+00:00",
    "totalAmount": 15000,
    "seatCount": 2
  }
}

Idempotency-Key Rules

  • Must be UUID v4
  • Must be lowercase
  • Must NOT contain hyphens
  • Example valid: f47ac10b58cf4b1b9c2e6d7f8a91b2c3

Idempotency-Key Validation

The Idempotency-Key header is mandatory for all write operations.

Validation rules:

  • Must match the following regex (UUID v4, lowercase, no hyphens):
  ^[0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}$
  • Any missing or invalid Idempotency-Key MUST result in:

    • HTTP status: 422 Unprocessable Entity
    • Error code: VALIDATION_ERROR
    • Response body (RFC 7807-style):
    {
      "error": {
        "code": "VALIDATION_ERROR",
        "message": "Invalid request",
        "violations": [
          {
            "field": "Idempotency-Key",
            "message": "Idempotency-Key must be a lowercase UUID v4 without hyphens"
          }
        ]
      }
    }

The server MUST NOT start any reservation transaction when the Idempotency-Key header fails validation.

Error Response Format (all non-2xx)

{
  "error": {
    "code": "SEAT_ALREADY_RESERVED",
    "message": "One or more seats are no longer available"
  }
}

Standardized Error Codes

Code HTTP Meaning Client Action
SEAT_ALREADY_RESERVED 409 Seat taken by someone else Refresh & retry
LOCK_TIMEOUT 503 DB lock timeout Auto-retry with backoff
TOO_MANY_SEATS 400 >5 seats requested Reduce selection
IDEMPOTENCY_KEY_IN_USE 409 Request already processing Wait or new key
RESERVATION_EXPIRED 410 Hold expired Start over
VALIDATION_ERROR 422 RFC 7807 Problem Details Fix input

Validation errors use RFC 7807 format with violations[].

Idempotency-Key Conflict (In-flight)

If a request with the same Idempotency-Key is already being processed:

  • Status: 409 Conflict
  • Body:
{
  "error": {
    "code": "IDEMPOTENCY_KEY_IN_USE",
    "message": "Another request with this idempotency key is in progress"
  }
}

Maximum Seats per Reservation

Business rule: maximum 5 seats per reservation.

If exceeded:

  • Status: 400 Bad Request
  • Code: TOO_MANY_SEATS

Partial Seat Availability (Hold Endpoint)

The /hold endpoint uses all-or-nothing semantics.

If any requested seat is no longer available:

  • Entire request fails
  • Status: 409 Conflict
  • Code: SEAT_ALREADY_RESERVED
  • Response includes:
{
  "error": {
    "code": "SEAT_ALREADY_RESERVED",
    "message": "One or more seats are no longer available",
    "details": {
      "unavailable_seat_ids": ["uuid1", "uuid3"]
    }
  }
}

Reservation TTL

A PENDING reservation expires exactly 900 seconds (15 minutes) after creation.

Field: expiresAt = createdAt + 900 seconds