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

# Trace payment and invoice history

> Use GraphQL to reconcile payment retries, invoice chargebacks, and Shopify invoice line attributes.

Use payment history to reconcile a subscription's charges with your payment provider or accounting system. Authenticate with a [project API access token](/integrations/api-access-tokens) that can read payments.

## Query payment history

This query returns payments for one subscription, their original payment and retry attempts, and the associated invoice:

```graphql theme={null}
query PaymentHistory($subscriptionId: ID!, $after: String) {
  payments(subscriptionId: $subscriptionId, first: 20, after: $after) {
    nodes {
      id
      paymentId
      paymentStatus
      amountCents
      currency
      createdAt
      retriedPayment { id }
      originalPayment {
        id
        retryAttempts {
          id
          paymentId
          paymentStatus
          createdAt
        }
      }
      invoice {
        id
        invoiceStatus
        paidAt
        chargedBackAt
        invoiceLineItems {
          id
          description
          metadata
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

Example variables:

```json theme={null}
{ "subscriptionId": "123456", "after": null }
```

When `hasNextPage` is true, pass `endCursor` as `after` to retrieve the next page.

## Follow retries

* `originalPayment` returns the original payment, or the current payment itself when it is not a retry.
* `retriedPayment` returns the original payment for a retry; it is null for an original payment.
* Query `retryAttempts` on the original payment to get its attempts from oldest to newest.
* `paymentId` is the payment provider's reference, while `id` identifies the Firmhouse payment.

The original payment and its retries refer to the same invoice. Group records by `originalPayment.id` when reconciling a payment chain, rather than treating every retry as a separate invoice. Use each attempt's status to distinguish successful charges from failed or pending attempts.

## Read chargeback timestamps

`paidAt` remains available after an invoice is charged back. `chargedBackAt` records the most recent chargeback transition; it is not a full chargeback event history. Read `invoiceStatus` for the invoice's current status and consult your payment provider for the chargeback reason.

An invoice or timestamp can be null when it does not apply to the payment.

## Read Shopify line attributes

Shopify invoice line items can include `shopify_custom_attributes` inside their `metadata` JSON. These are the originating Shopify order line's custom attributes, useful for preserving external fulfillment or accounting references.

For example:

```json theme={null}
{
  "shopify_custom_attributes": [
    { "key": "physical_sku", "value": "REFILL-250" }
  ]
}
```

Handle missing or empty metadata: existing invoices are not backfilled, and lines without Shopify custom attributes do not contain this key. These attributes provide context; they do not change product, price, or tax calculations.
