Query account data and reports

Last verified
Last verified Oct 18, 2026

Export related business records and calculate reports through Management v1. Complete the quickstart and request the scopes needed by your integration. Every example below uses /api/graphql/management/v1 and a dedicated Management credential.

Export detailed orders

This query selects order details for a half-open creation-time window:

graphql
query ExportOrders($after: String, $filter: OrderFilter) {
  orders(first: 100, after: $after, filter: $filter) {
    nodes {
      id
      number
      state
      paymentState
      createdAt
      updatedAt
      tombstone
      contactId
      salesChannelId
      orderChannelId
      totalGrossValueCents
      currency
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}

Variables for October 2026 in UTC:

json
{ "after": null, "filter": { "createdSince": "2026-10-01T00:00:00Z", "createdBefore": "2026-11-01T00:00:00Z" } }

Omit the filter for all dates. Page until hasNextPage is false; replace after with each returned cursor while keeping filters fixed. Store each record by account and ID. Creation-date filters do not capture later changes to old orders; use incremental synchronization for ongoing exports.

Join orders to their items and customers

Fetch related records using the parent IDs:

graphql
query OrderDetails($orderId: ID!, $contactId: ID!) {
  order(id: $orderId) {
    id
    number
    totalGrossValueCents
    currency
  }
  orderItems(filter: { orderIds: [$orderId] }, first: 100) {
    nodes {
      id
      orderId
      offerType
      offerId
      offerName
      quantity
      span
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
  contact(id: $contactId) {
    id
    firstName
    lastName
    email
    customerId
  }
}

Use an exported order's ID and contactId. If it has no contact, omit the contact lookup. Paginate child collections too. For a warehouse, exporting each complete collection and joining locally is usually simpler than querying every parent separately.

Data relationshipJoin keys and next collection
Order → items → pricesorderItems.orderId → order ID; pricings.orderItemId → item ID.
Attendee → booked itemattendances.pricingId → pricing ID → order-item ID. Imported attendees may instead carry direct offerType/offerId.
TicketsRelated orderId, orderItemId, pricingId, contactId, and primaryAttendanceId.
Invoice → lines and paymentsinvoiceItems.invoiceId and payments.invoiceId; invoice orderId links back to the sale.
Receipt → linesreceiptItems.receiptId joins the receipt; productId identifies the product. Join orderItemId to orderItems.id for the offer via offerType and offerId.
Contact → organization/addresscontacts.customerId → customer ID; order/invoice billing and shipping address IDs → addresses.
Event → resourcesresourceRequirements.eventId → event ID; resourceSlots.requirementId → requirement ID; allocated resourceIds → resources. Internal preselection is shown as open, with no assigned resource IDs.
Custom answerscustomFieldResponses.ownerType/ownerId identify the owning record: RequestItem for BOOKING, Contact for CONTACT, and Attendance for ATTENDEE answers. For booking answers, join ownerId to orderItems.id, then orderItems.orderId to the order. customFieldValues.responseId and inputId join responses and input definitions.

Relationships may be null, and records can outlive related records. Preserve those records in your export. Do not discard an invoice simply because an associated order or contact is unavailable.

For historical billing/shipping details, select order billingAddressSnapshot/shippingAddressSnapshot or invoice billingAddressSnapshot with contacts:read. These snapshots can differ from the current address returned by an address ID.

Invoice items also expose net totals, discounts, and recorded tax components (taxes { salesTaxId included taxRate taxValueCents currency }). Payments expose recorded refunds with their refund invoice, amount, currency, and pending confirmation state. Use these details for financial reconciliation without retrieving payment-provider payloads.

Count orders by sales channel

Reports aggregate all matching source records, not the first page:

graphql
query OrderCounts($filter: OrderFilter) {
  orderReport(filter: $filter, metric: { measure: records, dimension: pos_id, aggregations: [count] }) {
    data {
      dimension
      label
      count
    }
  }
}

Use the same filter object as the order export when comparing populations; reports default to active source records. An illustrative row is {"dimension":"channel-id","label":"Online shop","count":"42"}. This counts orders, not automatically paid orders or tickets. Add states or paymentStates when your question requires those restrictions.

Query invoice and receipt-line revenue

Use revenueReport for gross invoiced/receipted line revenue, rather than interpreting order totals as settled payments:

graphql
query RevenueByChannel($filter: RevenueFilter, $currency: String!) {
  revenueReport(filter: $filter, currency: $currency, metric: { measure: revenue, dimension: pos_id, aggregations: [sum] }) {
    data {
      dimension
      label
      sum
      currency
    }
  }
}

Variables:

json
{ "currency": "EUR", "filter": { "dates": ["[2026-10-01,2026-11-01)"] } }

An illustrative row is {"dimension":"channel-id","label":"Online shop","sum":"12500","currency":"EUR"}. This represents EUR 125.00 gross line revenue, including line discounts and taxes. The explicit currency filters source records; the report performs no conversion. Run separately for each currency. Invoice/receipt-line revenue is not a payment settlement or bank reconciliation.

For revenue reports, dates filters booking dates, createdAtDates filters line creation dates, and visitDates filters visit dates. Date ranges include their lower bound and exclude their upper bound in the account's time zone. Additional filters select events, templates, admissions, products, vouchers, contacts, orders, and channels. See RevenueFilter in the generated reference.

Group attendance and custom answers

Use attendanceReport with records/count and check_in_status to count check-ins. Supply filter: {eventIds: [...]} or filter: {orderIds: [...]} to restrict the source. ticket_price aggregates the sold ticket prices and requires an explicit currency. Read attendances for the individual attendee records behind a count.

Order, contact, and attendance reports support customFieldDimension: {inputId: "...", inputScope: ..., includeBlank: false} instead of dimension, and an optional secondaryCustomFieldDimension. Discover inputs through customFieldInputs and choose the appropriate inputScope enum in the reference. Custom-field order reports support records only. Custom-field answers can also be exported directly without reporting enabled.

Filter customers and count matching accounts

This example selects company accounts by name or business identifier. It requires contacts:read; the report also requires reports:read and reporting enabled.

graphql
query CompanyCustomers {
  customers(first: 100, filter: { accountTypes: ["company"], text: "Museum", discarded: false }) {
    nodes {
      id
      name
      number
      accountType
      groupId
      guest
      buyerReference
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
  customerReport(filter: { accountTypes: ["company"], text: "Museum", discarded: false }, metric: { measure: records, dimension: account_type, aggregations: [count] }) {
    data {
      dimension
      count
    }
  }
}

Continue customer pagination for the complete list. The count covers all matches. Use addressReport to count addresses by country/city and invoiceReport to count invoices by payment state or publication date. Their filter inputs match addresses and invoices respectively.

Filter orders by a custom answer

Discover the input ID from customFieldInputs and confirm its field-set scope. This example requires orders:read, custom-fields:read, and custom fields enabled. Use a booking input that accepts the answer Museum:

graphql
query OrdersWithAnswer($inputId: ID!, $after: String) {
  orders(first: 100, after: $after, filter: { customAnswers: [{ inputId: $inputId, inputScope: BOOKING, values: ["Museum"] }] }) {
    nodes {
      id
      number
      contactId
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}

Pass {"inputId":"your-input-id","after":null} and paginate normally. An order appears once even when several items contain the answer. Use the same customAnswers filter with orderReport to count those orders. Replace values with missing: true to find orders without a nonblank answer. For a count of individual stored answers, use customFieldValueReport, grouping by input_id or value; repeated answers on different items count separately.

Troubleshooting

SymptomAction
Unknown field or inputUse the Management v1 endpoint and its generated schema, not a legacy query.
Not authorizedRequest every source scope used by the query, including additional report scopes listed in the reference.
Reporting is not enabledAsk support to enable reporting for the account. Record exports remain available.
Monetary report requires currencySupply the three-letter uppercase currency of the source amounts.
Too many groups or report timeoutNarrow the date range or source IDs, or use a less detailed grouping.
Totals differ from the back officeAlign date basis, time zone, states, discard filters, measure, grouping, and currency. Orders, attendances, invoices, and payments answer different questions.
Rate limit or temporary server errorRespect Retry-After, retry reads with bounded backoff, and retain the last completed page or reporting period.

Ready to Get Started?

Book a free demo or reach out — we’d love to hear from you.