{
  "$schema": "./_mapping.schema.json",
  "provider": "dice",
  "name": "DICE (Ticket Holders API for partners)",
  "vertical": "tickets",
  "verified_on": "2026-10-13",
  "docs": [
    {
      "title": "DICE Ticket Holders API (GraphQL reference)",
      "url": "https://partners-endpoint.dice.fm/graphql/docs/index.html",
      "note": "Public SpectaQL reference for the partner GraphQL API at https://partners-endpoint.dice.fm/graphql (which answers 401 without a token). It defines the queries (viewer, node) and every type quoted below. It has no mutations and no webhooks: the API is read-only, built for who-bought / who-holds / event-finance reporting. Many fields are marked 'available with restricted access'. Example values on the page are SpectaQL placeholders (\"abc123\", 987), not real data."
    },
    {
      "title": "DICE MIO (partner dashboard where API tokens are generated)",
      "url": "https://mio.dice.fm",
      "note": "Login required; linked from the reference's Authorization section."
    }
  ],
  "access": {
    "public_docs": true,
    "how_to_get_access": "Only for DICE partners (promoters, venues, festivals) with a MIO account: a MIO user generates an API token and gives it to SplitClub. Fields marked 'available with restricted access' (event name, startDatetime, ticket type name/price context, order purchasedAt/quantity/total, ticket holder) need DICE to enable that access for the token; how is not documented, so ask the venue's DICE account manager.",
    "auth": "Authorization: Bearer <token generated in MIO>; GraphQL POST with Content-Type: application/json.",
    "base_url": "https://partners-endpoint.dice.fm/graphql"
  },
  "splitclub": {
    "integration_provider": null,
    "recommended_path": "poll_and_post",
    "note": "SplitClub's inbound hook does not accept a 'dice' provider, and DICE sends no webhooks, so the only path is polling: a SplitClub-side worker with the venue's MIO token queries viewer { events(where: …) { edges { node { … ticketTypes { … } venues { timezoneName } } } } } and POSTs Events with tiers to SplitClub. The API is read-only (no mutations), so SplitClub cannot reserve or issue DICE tickets for a funded group checkout; DICE sells only through its own app. A group checkout for a DICE night therefore needs the venue to issue the tickets on DICE's side (or sell a SplitClub-only table/package that is not a DICE ticket)."
  },
  "objects": {
    "Offering": {
      "source": "viewer.events → Event (one Offering per recurring night, if wanted)",
      "kind": "ticketed_event",
      "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event",
      "note": "Optional: DICE events are dated, so most venues need only Events. Pointers are rooted at the SplitClub Offering.",
      "fields": [
        { "to": "/external_id", "from": "Event.id", "transform": "GraphQL ID (Node) → string, prefix dice_evt_", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/kind", "from": "const:ticketed_event" },
        { "to": "/title", "from": "Event.name", "transform": "restricted-access field; truncate to 120", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/description", "from": "Event.description", "transform": "truncate to 4000", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/booking_url", "from": "Event.url", "transform": "'Fan facing url for the event'; must be https", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/policy/min_age", "from": "Venue.ageLimit", "transform": "free-text String; map 18+ / 21+ to 18 / 21, else omit", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Venue", "unverified": true }
      ]
    },
    "Event": {
      "source": "viewer { events(where: EventWhereInput) } → Event",
      "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event",
      "note": "Pointers are rooted at the SplitClub Event. Post only state APPROVED and hidden false (EventState: DRAFT, DECLINED, SUBMITTED, REVIEW, APPROVED, ARCHIVED, CANCELLED). Times: the Datetime scalar is documented as 'ISO 8601 Date and time - YYYY-MM-DDThh:mm:ss', with no zone in the description; the page's placeholder example is \"2016-10-07T01:08:03Z\". Whether real values are UTC (Z) or venue-local is not confirmed. If a value has Z or an offset, pass it through; if it is naive, treat it as wall-clock time in venues[0].timezoneName and attach that zone's offset.",
      "fields": [
        { "to": "/external_id", "from": "Event.id", "transform": "prefix dice_evt_", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/title", "from": "Event.name", "transform": "restricted access; truncate to 120", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/description", "from": "Event.description", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/starts_at", "from": "Event.startDatetime", "transform": "restricted access. See note: Z/offset → as is; naive → + offset of venues[0].timezoneName", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Datetime", "unverified": true },
        { "to": "/ends_at", "from": "Event.endDatetime", "transform": "same as starts_at", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Datetime", "unverified": true },
        { "to": "/capacity", "from": "Event.totalTicketAllocationQty", "transform": "Int; total allocation, not tickets left", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/tiers", "from": "Event.ticketTypes[]", "transform": "see PriceTier", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-TicketType" },
        { "to": "/on_sale/starts_at", "from": "Event.onSaleDatetime", "transform": "same time handling as starts_at", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event", "unverified": true },
        { "to": "/on_sale/ends_at", "from": "Event.offSaleDatetime", "transform": "same time handling as starts_at", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event", "unverified": true },
        { "to": "/media/0/url", "from": "Event.images[]", "transform": "Image type fields not mapped here; take its URL field, type image", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Image", "unverified": true },
        { "to": "/booking_url", "from": "Event.url", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/metadata/dice_venue_timezone", "from": "Event.venues[0].timezoneName", "transform": "IANA zone used for the time conversion", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Venue" }
      ]
    },
    "PriceTier": {
      "source": "Event.ticketTypes[] → TicketType (and TicketType.priceTiers[] → PriceTier when priceTierType is time or allocation)",
      "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-TicketType",
      "note": "Pointers are rooted at the parent Event; /tiers/0 is each ticket type (GA, VIP, table). Skip archived ticket types. DICE price tiers are price steps of one ticket type (by time or by allocation sold), not separate ticket types: send the current step's price as the tier amount. Money: Order and Ticket fields say 'in cents' explicitly; TicketType.price / faceValue / doorSalesPrice and PriceTier.price are Int with no unit stated, so minor units is an inference.",
      "fields": [
        { "to": "/tiers/0/external_id", "from": "TicketType.id", "transform": "restricted access; prefix dice_tt_", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-TicketType" },
        { "to": "/tiers/0/label", "from": "TicketType.name", "transform": "restricted access; truncate to 80", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-TicketType" },
        { "to": "/tiers/0/amount", "from": "TicketType.price (or the active PriceTier.price)", "transform": "Int, assumed minor units (cents), copy as is. faceValue is the face value; price is what the fan pays", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-TicketType", "unverified": true },
        { "to": "/tiers/0/currency", "from": "Event.currency", "transform": "EventCostCurrency enum (USD, EUR, GBP…) → lower case", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-EventCostCurrency" },
        { "to": "/tiers/0/unit", "from": "const:per_person", "transform": "one ticket per fan; a table ticket type sold as one ticket would be per_group (venue confirms)" },
        { "to": "/tiers/0/fees/0", "from": "TicketType.price − TicketType.faceValue", "transform": "{type: service, amount: price − faceValue, included: true} when positive. The docs do not define the relation between price and faceValue", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-TicketType", "unverified": true }
      ]
    },
    "Checkout": {
      "source": "viewer { orders(where: OrderWhereInput) } → Order",
      "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Order",
      "unverified": true,
      "note": "Reconciliation only, and unverified as a flow: DICE's API cannot create orders, so a SplitClub checkout can at most be matched to a DICE order the venue made. Pointers are rooted at checkout_create.",
      "fields": [
        { "to": "/external_booking_id", "from": "Order.id", "transform": "prefix dice_ord_", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Order" },
        { "to": "/amount", "from": "Order.total", "transform": "'Total price with commissions in cents': copy as is. (fullPrice = without commissions, in cents)", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Order" },
        { "to": "/currency", "from": "Order.event.currency", "transform": "lower case", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event" },
        { "to": "/party_size", "from": "Order.quantity", "transform": "'Quantity of purchased tickets'; restricted access; must be 2..50", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Order" },
        { "to": "/offering_external_id", "from": "Order.event.id", "transform": "prefix dice_evt_", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Order" },
        { "to": "/pay_by", "from": "Order.event.startDatetime", "transform": "SplitClub deadline before the show; see Event time handling", "source_url": "https://partners-endpoint.dice.fm/graphql/docs/index.html#definition-Event", "unverified": true }
      ]
    }
  },
  "webhooks": {
    "supported": false,
    "note": "The partner API reference defines only queries (viewer, node) and no subscriptions, mutations or webhook types, so there is nothing to receive. Poll viewer.events and viewer.orders (filter OrderWhereInput on purchasedAt for increments). No signature applies."
  },
  "gaps": [
    "Read-only API: no endpoint creates, holds or issues DICE tickets, so a funded SplitClub group checkout cannot become DICE tickets. Needs a product decision with the venue or DICE's partner team.",
    "No webhooks; inventory and orders must be polled.",
    "Datetime scalar format is ambiguous ('YYYY-MM-DDThh:mm:ss' in the description, a Z-suffixed placeholder in the example). Check real responses before trusting the offset; venues[].timezoneName is available for the conversion.",
    "TicketType.price / faceValue / doorSalesPrice and PriceTier.price have no documented unit; only Order and Ticket amounts say 'in cents'.",
    "Many core fields (Event.name, Event.startDatetime, TicketType.id/name, Order.quantity/total) are 'available with restricted access'; how a token gets that access is not documented.",
    "There is no remaining-inventory field per ticket type (only totalTicketAllocationQty and ticket pools' allocation); tickets left would have to be computed from sold tickets.",
    "DICE's public developer presence is only this reference: there is no documented promoter write API, app registration, rate limit or partner programme page."
  ]
}
