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

# Change feed

> Recover missed changes with a durable, resumable, paginated feed of committed Customer and Receivable changes.

`GET /v1/clients/{clientCode}/changes` lists the changes PayPathIQ has committed for your Integration and Client. Use it to find out what changed after an outage. It needs `customers:read`, `receivables:read`, or both.

## What an event contains

An event is deliberately small. It names the resource, the kind of change and the accepted revision. It carries no Customer, contact or financial detail.

```json theme={null}
{
  "eventId": "6f1c2d4e-8a3b-4c5d-9e7f-0a1b2c3d4e5f",
  "type": "customer.created",
  "resource": { "type": "customer", "id": "CUS_123" },
  "revision": 1,
  "occurredAt": "2026-10-15T09:30:00.000Z"
}
```

To see the detail, read the resource with its own `GET`. That read is authorized when you make it, so a revoked grant or a missing scope cannot recover data through the feed or through an old cursor.

Today the feed carries `customer.created`, `customer.updated`, `receivable.created`, `receivable.updated`, `payment_request.created`, `payment_request.updated`, `reconciliation.created`, `reconciliation.updated` and `payment_delivery.created`. A hosted payment request is reported when it is created and each time its status changes (a payer starts a payment, the provider confirms it, or a newer request replaces it); fetch the request for its `status`. A Receivable lifecycle command, a Payment observation (including a refund or reversal) or a financial correction or raising or clearing a [missing-record flag](/concepts#complete-books-and-missing-records) is reported as `receivable.updated` for each Receivable it changes. A Payment observation that leaves money unapplied is also reported as `customer.updated` for the paying Customer. A [payment reconciliation](/concepts#payment-reconciliation) is reported as `reconciliation.created` and again as `reconciliation.updated` when a difference is resolved; recording, matching or holding a receipt line is also reported as `receivable.updated` for each Receivable it touches. A reported [delivery attempt](/concepts#partner-owned-delivery) is reported as `payment_delivery.created` for the Payment request. You only see the events for resource types whose read scope your grant holds. Other resource families will add their own event types when they ship.

## Read the feed

1. Request the feed without a cursor to start at the oldest retained change.
2. Process every event in `data`, then store `nextCursor`.
3. Send the stored value as `cursor` on the next request. Keep going while `hasMore` is `true`; poll at your own pace when it is `false`.

`nextCursor` is always present, including on an empty page. Treat it as opaque. Use `limit` (1 to 500, default 100) to size pages.

## Ordering, duplicates and concurrent writes

* Events appear in commit order. A change becomes visible only after the mutation that produced it commits, and a rolled-back mutation produces no event. A page never skips a change that commits while you are paginating; you will receive it on a later page.
* Delivery is at least once. Discard an `eventId` you have already handled.
* `revision` is the resource's accepted revision at that time. Lifecycle commands do not change it, so two events for one resource can share a revision.

## Resynchronize after an expired cursor

Changes are retained for 30 days. A cursor that points before the oldest retained change returns [`410 change_cursor_expired`](/problems/change_cursor_expired). To recover:

1. Request `GET /v1/clients/{clientCode}/changes?from=latest`. The response has no events and a `nextCursor` positioned after every change committed so far.
2. Read the Customers and Receivables you need.
3. Resume the feed from the cursor in step 1.

Taking the cursor first means a change that commits while you are reading is delivered by the feed rather than missed. A cursor that was not issued for your Client returns [`422 invalid_change_cursor`](/problems/invalid_change_cursor).

## Webhooks

The feed is the recovery path for [webhooks](/webhooks). A webhook notification carries the same `eventId`, so you can treat the feed as authoritative and use notifications only to poll sooner.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.