Public Events API

The public events API is consumed by embedded widgets and third-party integrations. All endpoints authenticate with a publishable widget key in the X-Widget-Key header (see Widget Keys).


GET/api/v1/public/events/:id

Get event details

Returns the full public event payload — fields safe for client-side rendering. Excludes precise coordinates and internal IDs.

An event whose registration has not opened, has closed, or is full still returns 200; read registration_open and is_sold_out to decide what to render. The 400 below is only for an event that takes no registrations at all.

Path parameters

  • Name
    id
    Type
    string
    Description

    The ULID of the event.

Response shape

Returns the event directly on data. There is no item wrapper on a single resource — only list endpoints use one. ULIDs are 26-character alphanumeric.

Identification

  • id, title, slug, summary, description (HTML), public_url

Pricing

  • pricing_model: 'free' | 'paid' | 'external'
  • currency: 3-letter ISO 4217 code, uppercase (e.g. 'USD')

Date and time

  • start_date, end_date (YYYY-MM-DD)
  • start_time, end_time (HH:mm:ss)
  • timezone (IANA identifier)
  • start_datetime_utc, end_datetime_utc (ISO 8601)

Location

  • is_online: boolean
  • virtual_platform: string when is_online is true, otherwise null
  • address: { venue_name, city, state, country, display_address } or null. Coordinates are intentionally omitted from the public API.

Registration

  • has_tickets, requires_registration, requires_approval, registration_open, is_sold_out

Relations

  • category: { name, slug } or null
  • organization: { name, slug, logo, is_verified } or null
  • cover_image: { url, alt_text } (always present; falls back to a placeholder)
  • ticket_types[]: only types a buyer could take right now. An inactive type, a sold-out one, or one whose sale window has not opened or has already closed is left out (see below)
  • features[]: { name, slug, category }

Ticket type fields

  • Name
    id
    Type
    string
    Description
    ULID.
  • Name
    name
    Type
    string
    Description
    Display name.
  • Name
    description
    Type
    string?
    Description
    Optional description.
  • Name
    price_cents
    Type
    integer
    Description
    Minor currency units. Zero for free types.
  • Name
    currency
    Type
    string
    Description
    3-letter ISO 4217 code, uppercase.
  • Name
    quantity_available
    Type
    integer | null
    Description

    Seats still available, net of tickets held in other shoppers' live carts. Null when the type is uncapped, which means "no limit" — not "none left". Do not print null as a count and do not read it as sold out; only max_per_order bounds an uncapped type.

  • Name
    max_per_order
    Type
    integer
    Description
    Per-order maximum (default 10 if unset).
  • Name
    min_per_order
    Type
    integer
    Description
    Per-order minimum (default 1 if unset).
  • Name
    is_free
    Type
    boolean
    Description
    true when price_cents is zero.

Request

GET
/api/v1/public/events/:id
curl https://api.qariyb.com/api/v1/public/events/01HWX9KPQR \
  -H "X-Widget-Key: pk_live_..." \
  -H "Accept: application/json"

Response

{
  "success": true,
  "code": 100,
  "locale": "en",
  "message": "OK",
  "data": {
    "id": "01HWX9KPQR5T7V8MNCBDJ3GFYZ",
    "title": "Community Iftar Dinner",
    "slug": "community-iftar-dinner",
    "summary": "Join us for a blessed evening...",
    "description": "<p>Full description...</p>",
    "pricing_model": "paid",
    "currency": "GBP",
    "start_date": "2026-06-16",
    "start_time": "18:30:00",
    "end_date": "2026-06-16",
    "end_time": "21:00:00",
    "timezone": "Europe/London",
    "start_datetime_utc": "2026-06-16T17:30:00+00:00",
    "end_datetime_utc": "2026-06-16T20:00:00+00:00",
    "is_online": false,
    "virtual_platform": null,
    "address": {
      "venue_name": "Al-Noor Islamic Centre",
      "city": "London",
      "state": null,
      "country": "GB",
      "display_address": "Al-Noor Islamic Centre, London, GB"
    },
    "has_tickets": true,
    "requires_registration": true,
    "requires_approval": false,
    "registration_open": true,
    "is_sold_out": false,
    "category": {
      "name": "Ramadan & Eid Events",
      "slug": "ramadan-eid-events"
    },
    "organization": {
      "name": "Al-Noor Islamic Centre",
      "slug": "al-noor-islamic-centre",
      "logo": null,
      "is_verified": false
    },
    "cover_image": {
      "url": "https://qariyb.com/storage/events/iftar.jpg",
      "alt_text": "Community Iftar Dinner"
    },
    "ticket_types": [
      {
        "id": "01HWX9TKT123",
        "name": "Individual Ticket",
        "description": "Single person ticket",
        "price_cents": 1500,
        "currency": "GBP",
        "quantity_available": 172,
        "max_per_order": 8,
        "min_per_order": 1,
        "is_free": false
      }
    ],
    "features": [
      {
        "name": "Halal Food",
        "slug": "halal_food",
        "category": "dietary"
      }
    ],
    "public_url": "https://qariyb.com/discover/events/community-iftar-dinner"
  }
}

GET/api/v1/public/events/:id/tickets

List ticket types

Returns just the available ticket types for an event. Useful when the widget already has the rest of the event payload cached.

Returns 400 with EVENT_NOT_AVAILABLE (code: 500) when the event has has_tickets = false.

Response fields

  • Name
    event_id
    Type
    string
    Description
    Event ULID.
  • Name
    currency
    Type
    string
    Description
    Event-level currency, uppercase.
  • Name
    ticket_types
    Type
    TicketType[]
    Description
    Same shape as on the event details endpoint.
  • Name
    registration_open
    Type
    boolean
    Description
    Whether the event is currently accepting registrations.
  • Name
    is_sold_out
    Type
    boolean
    Description

    true when every ticket type is exhausted, or when the event's own attendee cap has been reached. Counted from tickets sold, so seats merely held in live carts do not count — a type can report quantity_available: 0 while this is still false.

Request

GET
/api/v1/public/events/:id/tickets
curl https://api.qariyb.com/api/v1/public/events/01HWX9KPQR/tickets \
  -H "X-Widget-Key: pk_live_..." \
  -H "Accept: application/json"

Response

{
  "success": true,
  "code": 100,
  "locale": "en",
  "message": "OK",
  "data": {
    "event_id": "01HWX9KPQR5T7V8MNCBDJ3GFYZ",
    "currency": "GBP",
    "ticket_types": [
      {
        "id": "01HWX9TKT123",
        "name": "Individual Ticket",
        "description": null,
        "price_cents": 1500,
        "currency": "GBP",
        "quantity_available": 172,
        "max_per_order": 8,
        "min_per_order": 1,
        "is_free": false
      }
    ],
    "registration_open": true,
    "is_sold_out": false
  }
}

GET/api/v1/public/events/:id/availability

Check availability

Lightweight endpoint for widgets to decide whether to render a checkout CTA. Always returns HTTP 200; the body indicates the outcome.

Only available and reason are guaranteed. The remaining fields are populated only on success paths and omitted when reason is 'event_not_found' or 'event_not_available'.

Response fields

  • Name
    available
    Type
    boolean
    Description

    true when the event is published, registration is open, and capacity remains.

  • Name
    reason
    Type
    string | null
    Description

    One of 'event_not_found', 'event_not_available', 'sold_out', 'registration_closed', or null when the event is available.

  • Name
    event_id
    Type
    string?
    Description
    Event ULID. Present only on success paths.
  • Name
    registration_open
    Type
    boolean?
    Description
    Present only on success paths.
  • Name
    has_tickets
    Type
    boolean?
    Description
    Present only on success paths.
  • Name
    is_sold_out
    Type
    boolean?
    Description
    Present only on success paths.
  • Name
    total_tickets_available
    Type
    integer?
    Description

    Sum of what the listed types can still sell, net of seats held in live carts. An uncapped type contributes an internal allowance rather than a real limit, so treat this as a hint rather than a guarantee. Present only on success paths.

Request

GET
/api/v1/public/events/:id/availability
curl https://api.qariyb.com/api/v1/public/events/01HWX9KPQR/availability \
  -H "X-Widget-Key: pk_live_..." \
  -H "Accept: application/json"

Response (available)

{
  "success": true,
  "code": 100,
  "data": {
    "available": true,
    "reason": null,
    "event_id": "01HWX9KPQR5T7V8MNCBDJ3GFYZ",
    "registration_open": true,
    "has_tickets": true,
    "is_sold_out": false,
    "total_tickets_available": 172
  }
}

Response (event not found)

{
  "success": true,
  "code": 100,
  "data": {
    "available": false,
    "reason": "event_not_found"
  }
}

Errors

HTTPApiCodeScenario
401600 WIDGET_KEY_MISSINGNo X-Widget-Key header.
401601 WIDGET_KEY_INVALIDUnknown, inactive, or malformed key.
403604 WIDGET_ORIGIN_DENIEDOrigin not in the key's allowed_domains.
404203 NOT_FOUNDEvent ULID not found, not published, or belonging to another organization (show and tickets only).
400500 EVENT_NOT_AVAILABLEOn show: the event neither sells tickets nor takes registrations (has_tickets and requires_registration both false). On tickets: has_tickets = false.
429605 WIDGET_RATE_LIMITEDPer-key read limit exceeded.

Was this page helpful?