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

# Orders & Payments

> GraphQL query examples for orders, payments, and refund tickets

## One-Time Orders

### List Completed Orders

```graphql theme={"system"}
query($storeId: String!) {
  onetimeOrders(
    storeId: $storeId
    filter: { status: { eq: "completed" } }
    limit: 50
  ) {
    id
    buyerEmail
    currency
    priceSnapshot {
      currency
      subtotal
      taxAmount
      total
      taxCategory
    }
    status
    createdAt
  }
  onetimeOrdersCount(storeId: $storeId)
}
```

**Variables:**

```json theme={"system"}
{ "storeId": "STO_3bVzrkD0FJjFdZNLk8Ualx" }
```

### Filter by Date Range

```graphql theme={"system"}
query($storeId: String!) {
  onetimeOrders(
    storeId: $storeId
    filter: {
      createdAt: {
        gte: "2026-01-01T00:00:00.000Z"
        lte: "2026-03-31T23:59:59.999Z"
      }
    }
  ) {
    id
    buyerEmail
    status
    createdAt
  }
}
```

### Look Up One-Time Order by Your Business Number (`orderMerchantExternalId`)

Pass the same `orderMerchantExternalId` you attached at checkout creation.

```graphql theme={"system"}
query($storeId: String!, $ref: String!) {
  onetimeOrders(
    storeId: $storeId
    filter: { orderMerchantExternalId: { eq: $ref } }
  ) {
    id
    buyerEmail
    status
    orderMerchantExternalId
    createdAt
  }
}
```

**Variables:**

```json theme={"system"}
{ "storeId": "STO_3bVzrkD0FJjFdZNLk8Ualx", "ref": "ORDER-2026-00891" }
```

### SDK Example

```typescript theme={"system"}
const result = await client.graphql.query<{
  onetimeOrders: Array<{
    id: string;
    buyerEmail: string;
    priceSnapshot: { total: number; currency: string };
    status: string;
  }>;
}>({
  query: `query($storeId: String!) {
    onetimeOrders(storeId: $storeId, filter: { status: { eq: "completed" } }) {
      id buyerEmail priceSnapshot { total currency } status
    }
  }`,
  variables: { storeId: "STO_3bVzrkD0FJjFdZNLk8Ualx" },
});
```

***

## Subscription Orders

### List Active Subscriptions

```graphql theme={"system"}
query($storeId: String!) {
  subscriptionOrders(
    storeId: $storeId
    filter: { status: { in: ["active"] } }
  ) {
    id
    buyerEmail
    status
    billingPeriod
    createdAt
  }
  subscriptionOrdersCount(storeId: $storeId)
}
```

### Filter Canceling Subscriptions

```graphql theme={"system"}
query($storeId: String!) {
  subscriptionOrders(
    storeId: $storeId
    filter: { status: { eq: "canceling" } }
  ) {
    id
    buyerEmail
    status
    createdAt
  }
}
```

### Look Up Subscription Order by Your Business Number (`orderMerchantExternalId`)

Pass the same `orderMerchantExternalId` you attached at checkout creation. Every renewal payment that follows inherits the same value, so a single business reference resolves the whole subscription lifecycle.

```graphql theme={"system"}
query($storeId: String!, $ref: String!) {
  subscriptionOrders(
    storeId: $storeId
    filter: { orderMerchantExternalId: { eq: $ref } }
  ) {
    id
    buyerEmail
    status
    billingPeriod
    orderMerchantExternalId
    createdAt
  }
}
```

**Variables:**

```json theme={"system"}
{ "storeId": "STO_3bVzrkD0FJjFdZNLk8Ualx", "ref": "SUB-2026-01045" }
```

***

## Payments

### List Successful Payments

```graphql theme={"system"}
query {
  payments(
    filter: { status: { eq: "succeeded" } }
    limit: 100
  ) {
    id
    orderId
    status
    refundStatus
    snapshotAmountDetails {
      subtotal
      taxAmount
      total
      currency
    }
    createdAt
  }
  paymentsCount(filter: { status: { eq: "succeeded" } })
}
```

### Filter by Date Range

```graphql theme={"system"}
query {
  payments(
    filter: {
      status: { eq: "succeeded" }
      createdAt: {
        gte: "2026-01-01T00:00:00.000Z"
        lte: "2026-03-31T23:59:59.999Z"
      }
    }
  ) {
    id
    orderId
    snapshotAmountDetails {
      subtotal
      taxAmount
      total
      currency
    }
    createdAt
  }
}
```

### Look Up Payment by Waffo Payment ID

```graphql theme={"system"}
query($paymentId: String!) {
  payment(id: $paymentId) {
    id
    orderId
    status
    refundStatus
    orderMerchantExternalId
    snapshotAmountDetails { total currency }
  }
}
```

**Variables:**

```json theme={"system"}
{ "paymentId": "PAY_6eYCunG3IMmIgcQOnaXdoA" }
```

### Look Up Payment by Your Business Number (`orderMerchantExternalId`)

Pass the same `orderMerchantExternalId` you attached at checkout creation. Field name mirrors webhook payload `data.orderMerchantExternalId`.

```graphql theme={"system"}
query($ref: String!) {
  payments(filter: { orderMerchantExternalId: { eq: $ref } }) {
    id
    orderId
    status
    refundStatus
    orderMerchantExternalId
    createdAt
  }
}
```

**Variables:**

```json theme={"system"}
{ "ref": "ORDER-2026-00891" }
```

<Note>
  For subscription orders, every renewal payment **inherits the same `orderMerchantExternalId`** set at checkout. The query above returns the full payment history for the same business reference, ordered by `createdAt DESC`.
</Note>

***

## Aggregations & Sorting

### Aggregate Payments by Day

`paymentsAggregate` returns `count` plus `amount` metrics (`sum`, `avg`, `min`, `max`) over all matching rows, optionally grouped by up to 2 dimensions. Available dimensions: `status`, `currency`, `payment_method_type`, `card_brand`, `store`, and the time dimension `created_period`. `granularity` (`day`, `week`, `month`, `quarter`, `year`; default `day`) only applies to the time dimension.

```graphql theme={"system"}
query {
  paymentsAggregate(
    filter: { status: { eq: "succeeded" }, currency: { eq: "USD" } }
    groupBy: [created_period]
    granularity: day
  ) {
    count
    amount { sum avg min max }
    groups {
      keys { dimension value }
      count
      amount { sum }
    }
    isTruncated
  }
}
```

<Note>
  Aggregate `amount` values are integer strings in **minor currency units** (e.g. cents). Amounts are summed across whatever rows match the filter, so group or filter by `currency` when multiple currencies are involved. Groups are sorted by `count` descending and capped at 100 (`isTruncated` flags truncation); the top-level `count`/`amount` always cover all matching rows. Other entities expose the same shape: `refundsAggregate`, `onetimeOrdersAggregate`, `subscriptionOrdersAggregate`, `payoutTicketsAggregate`, `settlementBatchesAggregate`, `webhookDeliveriesAggregate`, `emailDeliveriesAggregate`.
</Note>

### Sort with `orderBy`

List queries that support sorting accept `orderBy: [XxxOrderBy!]` (an enum whitelist), defaulting to `created_at DESC`. For payments the options are `created_at_desc`, `created_at_asc`, `amount_desc`, `amount_asc`.

```graphql theme={"system"}
query {
  payments(
    filter: { status: { eq: "succeeded" } }
    orderBy: [amount_desc]
    limit: 20
  ) {
    id
    status
    snapshotAmountDetails { total currency }
    createdAt
  }
}
```

***

## Refunds (executed records)

Refund records (`order.refunds`) are written after the PSP confirms the refund. They are **separate from refund tickets** — tickets carry the request lifecycle, refund records carry the executed result.

### Look Up Refund by Waffo Refund ID

`Refund` exposes both business numbers as flat fields (`orderMerchantExternalId` from the originating order, `refundTicketMerchantExternalId` from the originating refund ticket) — same naming as the webhook payload.

```graphql theme={"system"}
query($refundId: String!) {
  refund(id: $refundId) {
    id
    paymentId
    ticketId
    status
    orderMerchantExternalId
    refundTicketMerchantExternalId
    pspAmountDetails { amount currency }
    createdAt
  }
}
```

**Variables:**

```json theme={"system"}
{ "refundId": "RFD_8aHbCcDdEeFfGgHhIiJjKk" }
```

### Look Up Refunds by Payment (Waffo Payment ID)

```graphql theme={"system"}
query($paymentId: String!) {
  refunds(filter: { paymentId: { eq: $paymentId } }) {
    id
    status
    orderMerchantExternalId
    refundTicketMerchantExternalId
    pspAmountDetails { amount currency }
    createdAt
  }
}
```

### Look Up Refunds by Your Business Number

Match by **the refund ticket's business reference** (what you attached when creating the refund ticket) — use the `refundTicketMerchantExternalId` filter:

```graphql theme={"system"}
query($ref: String!) {
  refunds(filter: { refundTicketMerchantExternalId: { eq: $ref } }) {
    id
    paymentId
    ticketId
    status
    orderMerchantExternalId
    refundTicketMerchantExternalId
    pspAmountDetails { amount currency }
    createdAt
  }
}
```

Or match by **the order's business reference** (returns all refunds against any payment carrying that reference, useful for subscription renewals) — filter at the payment layer and read its nested refunds:

```graphql theme={"system"}
query($paymentRef: String!) {
  payments(filter: { orderMerchantExternalId: { eq: $paymentRef } }) {
    id
    orderMerchantExternalId
    refunds {
      id
      status
      refundTicketMerchantExternalId
      pspAmountDetails { amount currency }
      createdAt
    }
  }
}
```

***

## Refund Tickets

### List All Refund Tickets

```graphql theme={"system"}
query {
  refundTickets {
    id
    paymentId
    status
    requestedAmount
    reason
    createdAt
  }
  refundTicketsCount
}
```

### Filter Pending Refunds

```graphql theme={"system"}
query {
  refundTickets(filter: { status: { eq: "pending" } }) {
    id
    paymentId
    requestedAmount
    reason
    createdAt
  }
}
```

### Refunds for a Specific Payment

```graphql theme={"system"}
query($paymentId: String!) {
  refundTickets(filter: { subjectId: { eq: $paymentId } }) {
    id
    status
    refundTicketMerchantExternalId
    versionData {
      reason
      requestedAmount { amount currency }
    }
    createdAt
  }
}
```

**Variables:**

```json theme={"system"}
{ "paymentId": "PAY_6eYCunG3IMmIgcQOnaXdoA" }
```

### Look Up Refund Tickets by Your Business Number (`refundTicketMerchantExternalId`)

```graphql theme={"system"}
query($ref: String!) {
  refundTickets(filter: { refundTicketMerchantExternalId: { eq: $ref } }) {
    id
    status
    refundTicketMerchantExternalId
    versionData {
      reason
      requestedAmount { amount currency }
    }
    reviewNote
    rejectReason
    executedAt
    createdAt
  }
}
```

**Variables:**

```json theme={"system"}
{ "ref": "REF-2026-00891" }
```

<Tip>
  `RefundTicket` (the request) and `Refund` (the executed record) are **two different GraphQL types**, but their business-side identifiers share the same flat names as the webhook payload: `refundTicketMerchantExternalId` on both `RefundTicket` and `Refund`; `orderMerchantExternalId` is additionally exposed on `Refund` (inherited from the originating order). Webhook payloads carry the same two values as `data.orderMerchantExternalId` and `data.refundTicketMerchantExternalId`.
</Tip>

***

## Checkout Sessions

### Query Session Details

```graphql theme={"system"}
query($sessionId: ID!) {
  checkoutSession(id: $sessionId) {
    id
    productType
    currency
    status
    expiresAt
    createdAt
  }
}
```

**Variables:**

```json theme={"system"}
{ "sessionId": "cs_550e8400-e29b-41d4-a716-446655440000" }
```
