Skip to main content

Credit Memo Events

Credit memo events are triggered whenever a credit memo is created, or its status or remaining balance changes — regardless of whether the change came from your connector's API call, a payer applying it at checkout, or its expiration date passing. A separate event fires when a credit memo is applied toward a payment.

Credit Memo Status Overview

Credit memo statuses can be found in the webhook payload at resource.status:

StatusDescription
activeCredit memo is available for the payer to apply at checkout
paidCredit memo has been fully consumed — amountRemaining reached zero
canceledCredit memo was canceled via the API and is no longer available at checkout
expiredCredit memo's expirationDate has passed; no longer available at checkout

Event: Credit Memo Status — Created

This event is triggered when a credit memo is created, whether via POST /creditMemos or CSV import.

{
"object": "event",
"id": "wc55vzwa0iahpy8j5oxe4ju5",
"resource": {
"object": "creditMemo",
"id": "qt3zj2aza5flqbit40l99myq",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1001",
"extKey": "CM-1001",
"amount": 100,
"amountRemaining": 100,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-30T21:16:04.000Z"
},
"created": "2026-07-30T21:16:40.000Z",
"lastUpdated": "2026-07-30T21:16:40.000Z"
},
"diff": {
"previous": {},
"changes": {
"object": "creditMemo",
"id": "qt3zj2aza5flqbit40l99myq",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1001",
"extKey": "CM-1001",
"amount": 100,
"amountRemaining": 100,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-30T21:16:04.000Z"
},
"created": "2026-07-30T21:16:40.000Z",
"lastUpdated": "2026-07-30T21:16:40.000Z"
}
},
"sourceId": "qt3zj2aza5flqbit40l99myq",
"sourceType": "CreditMemo",
"status": "active",
"created": "2026-07-30T21:16:40.000Z",
"lastUpdated": "2026-07-30T21:16:40.000Z",
"eventType": "credit_memo.created"
}

On credit_memo.created, diff.changes mirrors the entire resource object (there's no "previous" state to diff against) — it is not a trimmed subset. Only on credit_memo.updated does diff.changes contain just the fields that actually changed (see below).

Event: Credit Memo Status — Updated (Balance Change)

This event is triggered whenever amountRemaining or status changes for any reason — your connector updating it via PUT /creditMemos/:id, a payer partially applying it at checkout, full consumption, or expiration. diff.previous is the full prior record snapshot (same shape as resource); diff.changes contains only the fields that actually differ between that snapshot and the current one. In practice this sometimes includes created, lastUpdated, or a nested payerCustomer.lastUpdated even when nothing about your own integration changed those — treat diff.changes as "whatever differed," not a curated list of business-meaningful fields, and key your own logic off the specific field you care about (status, amountRemaining) rather than assuming diff.changes' presence/absence of other fields means anything.

Partial balance change (a payer applied part of the credit memo at checkout):

{
"object": "event",
"id": "2zavwqh9euzmmg7gfy7q84yl",
"resource": {
"object": "creditMemo",
"id": "gqrs52yfb5c1mkd3vfgxlldl",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1002",
"extKey": "CM-1002",
"amount": 500,
"amountRemaining": 300,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T20:44:36.000Z",
"lastUpdated": "2026-07-30T20:44:36.000Z"
},
"diff": {
"previous": {
"object": "creditMemo",
"id": "gqrs52yfb5c1mkd3vfgxlldl",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1002",
"extKey": "CM-1002",
"amount": 500,
"amountRemaining": 500,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T20:13:59.000Z",
"lastUpdated": "2026-07-30T20:13:59.000Z"
},
"changes": {
"amountRemaining": 300,
"created": "2026-07-30T20:44:36.000Z",
"lastUpdated": "2026-07-30T20:44:36.000Z"
}
},
"sourceId": "gqrs52yfb5c1mkd3vfgxlldl",
"sourceType": "CreditMemo",
"status": "active",
"created": "2026-07-30T20:44:36.000Z",
"lastUpdated": "2026-07-30T20:44:36.000Z",
"eventType": "credit_memo.updated"
}

Full consumption (status flips to paid and amountRemaining reaches zero in the same event — check both fields, not just one):

{
"object": "event",
"id": "6q1m5pfnq2vrmzicw1oqcitj",
"resource": {
"object": "creditMemo",
"id": "bf2v1r4u2e0uob4q7qqz2bwz",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "paid",
"extId": "CM-1003",
"extKey": "CM-1003",
"amount": 200,
"amountRemaining": 0,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T21:05:12.000Z",
"lastUpdated": "2026-07-30T21:05:12.000Z"
},
"diff": {
"previous": {
"object": "creditMemo",
"id": "bf2v1r4u2e0uob4q7qqz2bwz",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1003",
"extKey": "CM-1003",
"amount": 200,
"amountRemaining": 200,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T20:13:59.000Z",
"lastUpdated": "2026-07-30T20:13:59.000Z"
},
"changes": {
"status": "paid",
"amountRemaining": 0,
"created": "2026-07-30T21:05:12.000Z",
"lastUpdated": "2026-07-30T21:05:12.000Z"
}
},
"sourceId": "bf2v1r4u2e0uob4q7qqz2bwz",
"sourceType": "CreditMemo",
"status": "active",
"created": "2026-07-30T21:05:12.000Z",
"lastUpdated": "2026-07-30T21:05:12.000Z",
"eventType": "credit_memo.updated"
}

Expiration (fired by a daily job when expirationDate passes — not triggered by any API call your connector makes):

{
"object": "event",
"id": "16u91yrpq5pam6s9ycjmel71",
"resource": {
"object": "creditMemo",
"id": "75veoldu45evi22zoh1rebhs",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "expired",
"extId": "CM-1004",
"extKey": "CM-1004",
"amount": 100,
"amountRemaining": 100,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"expirationDate": "2026-07-29T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-30T21:16:04.000Z"
},
"created": "2026-07-31T00:00:00.000Z",
"lastUpdated": "2026-07-31T00:00:00.000Z"
},
"diff": {
"previous": {
"object": "creditMemo",
"id": "75veoldu45evi22zoh1rebhs",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1004",
"extKey": "CM-1004",
"amount": 100,
"amountRemaining": 100,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"expirationDate": "2026-07-29T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T20:13:59.000Z",
"lastUpdated": "2026-07-30T20:13:59.000Z"
},
"changes": {
"status": "expired",
"payerCustomer": {
"lastUpdated": "2026-07-30T21:16:04.000Z"
},
"created": "2026-07-31T00:00:00.000Z",
"lastUpdated": "2026-07-31T00:00:00.000Z"
}
},
"sourceId": "75veoldu45evi22zoh1rebhs",
"sourceType": "CreditMemo",
"status": "active",
"created": "2026-07-31T00:00:00.000Z",
"lastUpdated": "2026-07-31T00:00:00.000Z",
"eventType": "credit_memo.updated"
}

Event: Credit Memo Status — Canceled

This event is triggered by PATCH /creditMemos/:id/cancel. A canceled credit memo is no longer available at checkout.

{
"object": "event",
"id": "f3n7cq2ub51xr0m48kzy6t9a",
"resource": {
"object": "creditMemo",
"id": "hb2k9r4v0e3pxo7d5j1w8n6q",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "canceled",
"extId": "CM-1005",
"extKey": "CM-1005",
"amount": 150,
"amountRemaining": 150,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T18:02:11.000Z",
"lastUpdated": "2026-07-30T18:10:45.000Z"
},
"diff": {
"previous": {
"object": "creditMemo",
"id": "hb2k9r4v0e3pxo7d5j1w8n6q",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1005",
"extKey": "CM-1005",
"amount": 150,
"amountRemaining": 150,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T18:02:11.000Z",
"lastUpdated": "2026-07-30T18:02:11.000Z"
},
"changes": {
"status": "canceled",
"lastUpdated": "2026-07-30T18:10:45.000Z"
}
},
"sourceId": "hb2k9r4v0e3pxo7d5j1w8n6q",
"sourceType": "CreditMemo",
"status": "active",
"created": "2026-07-30T18:10:45.000Z",
"lastUpdated": "2026-07-30T18:10:45.000Z",
"eventType": "credit_memo.canceled"
}

Event: Credit Memo Status — Activated

This event is triggered by PATCH /creditMemos/:id/activate — typically re-activating a previously canceled credit memo.

{
"object": "event",
"id": "a8x2m6y0q4b7vk1p9d3n5r0e",
"resource": {
"object": "creditMemo",
"id": "hb2k9r4v0e3pxo7d5j1w8n6q",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"extId": "CM-1005",
"extKey": "CM-1005",
"amount": 150,
"amountRemaining": 150,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T18:02:11.000Z",
"lastUpdated": "2026-07-30T19:20:03.000Z"
},
"diff": {
"previous": {
"object": "creditMemo",
"id": "hb2k9r4v0e3pxo7d5j1w8n6q",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "canceled",
"extId": "CM-1005",
"extKey": "CM-1005",
"amount": 150,
"amountRemaining": 150,
"currency": "USD",
"extCreationDate": "2026-07-30T00:00:00.000Z",
"extPostedDate": "2026-07-30T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"payerCustomer": {
"object": "payerCustomer",
"id": "1dlqioq9unsfq8ucwcj8gna6",
"name": "Acme Testing LLC",
"erpCustomerId": "CUST-001",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "active",
"created": "2026-07-23T23:05:11.000Z",
"lastUpdated": "2026-07-23T23:05:14.000Z"
},
"created": "2026-07-30T18:02:11.000Z",
"lastUpdated": "2026-07-30T18:10:45.000Z"
},
"changes": {
"status": "active",
"lastUpdated": "2026-07-30T19:20:03.000Z"
}
},
"sourceId": "hb2k9r4v0e3pxo7d5j1w8n6q",
"sourceType": "CreditMemo",
"status": "active",
"created": "2026-07-30T19:20:03.000Z",
"lastUpdated": "2026-07-30T19:20:03.000Z",
"eventType": "credit_memo.activated"
}

Event: Credit Memo Applied to a Payment

When a payer applies one or more credit memos toward an invoice, Paystand fires receivable_transactions.created — the same event type used for cash/card payments — rather than a separate credit-memo-specific event type. Which shape you receive depends on how the invoice was paid:

  • Credits-only payment (100% covered by credit memo(s)): one receivable_transactions.created event per credit memo consumed, resourceType: "CreditMemo", amountApplied scoped to that credit memo's own contribution. resource.paymentId on a credits-only payment is a synthetic identifier in the form credit-payment-<timestamp>-<suffix> (e.g. credit-payment-1785877390226-lb3r151pp) — it does not correspond to a fetchable Payment record, since no real Payment was created.
  • Mixed credit + cash/card payment: one receivable_transactions.created event with resourceType: "Payment" (fired synchronously, amountApplied equal to the full combined amount — credit plus cash), and one additional receivable_transactions.created event per contributing credit memo with resourceType: "CreditMemo" (fired asynchronously, typically arriving about a second after the Payment-typed event — don't treat this delay as a delivery failure). Here resource.paymentId is a real Payment ID, shared by both the Payment-typed event and its CreditMemo-typed sibling(s) — correlate on that field: the credit-covered amount is the sum of the CreditMemo-typed events' amountApplied, and the residual cash/card amount is the Payment-typed event's amountApplied minus that sum.

This holds for any number of credit memos applied to one payment — each fires its own CreditMemo-typed event, individually attributable by resource.resourceId (the credit memo's ID) and amountApplied.

Payment-typed event (fired synchronously; note the payment sub-object, no creditMemo object):

{
"object": "event",
"id": "2ymy3bg3aizkm0mexwh79hei",
"resource": {
"object": "receivableTransaction",
"id": "pb1kbhjyq3asjbndsh5tlc1w",
"receivableId": "3fkjddnmluqrn3y06rl72n3a",
"paymentId": "89lu5vyiqq85qbtyqezcrdow",
"resourceId": "89lu5vyiqq85qbtyqezcrdow",
"resourceType": "Payment",
"paymentOrigin": "reminder",
"amountApplied": "150.00",
"status": "active",
"created": "2026-07-30T22:26:47.000Z",
"lastUpdated": "2026-07-30T22:26:47.000Z",
"receivable": {
"object": "receivable",
"id": "3fkjddnmluqrn3y06rl72n3a",
"amount": "150.00",
"currency": "USD",
"payerEmail": "payer@example.com",
"dateDue": "2026-08-30T00:00:00.000Z",
"datePaid": "2026-07-30T22:26:47.000Z",
"amountPaid": "150.00",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "paid",
"created": "2026-07-25T18:02:11.000Z",
"lastUpdated": "2026-07-30T22:26:47.000Z",
"extId": "INV-9001",
"extCustomerId": "CUST-001"
},
"payment": {
"object": "payment",
"id": "89lu5vyiqq85qbtyqezcrdow",
"amount": "102.00",
"currency": "USD",
"sourceType": "Bank",
"status": "posted",
"datePosted": "2026-07-30T22:26:46.000Z"
}
},
"sourceId": "pb1kbhjyq3asjbndsh5tlc1w",
"sourceType": "ReceivableTransactions",
"status": "active",
"created": "2026-07-30T22:26:47.000Z",
"lastUpdated": "2026-07-30T22:26:47.000Z",
"eventType": "receivable_transactions.created"
}

Sibling CreditMemo-typed event, same paymentId (fired asynchronously; note the creditMemo sub-object, no payment object):

{
"object": "event",
"id": "9fjq3nz6wg1lk0xm7c2p5btr",
"resource": {
"object": "receivableTransaction",
"id": "hs3vn8xj7q1amewz0k4t2pcy",
"receivableId": "lsbibdvw3qzgnt4naihwhkbc",
"paymentId": "89lu5vyiqq85qbtyqezcrdow",
"resourceId": "6ep3mgo999n5mrkd8u7swnb3",
"resourceType": "CreditMemo",
"paymentOrigin": "reminder",
"amountApplied": "50.00",
"status": "active",
"created": "2026-07-30T22:26:48.000Z",
"lastUpdated": "2026-07-30T22:26:48.000Z",
"receivable": {
"object": "receivable",
"id": "lsbibdvw3qzgnt4naihwhkbc",
"amount": "150.00",
"currency": "USD",
"payerEmail": "payer@example.com",
"dateDue": "2026-08-30T00:00:00.000Z",
"datePaid": "2026-07-30T22:26:47.000Z",
"amountPaid": "150.00",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "paid",
"created": "2026-07-25T18:02:11.000Z",
"lastUpdated": "2026-07-30T22:26:47.000Z",
"extId": "INV-9001",
"extCustomerId": "CUST-001"
},
"creditMemo": {
"object": "creditMemo",
"id": "6ep3mgo999n5mrkd8u7swnb3",
"ownerId": "fcuuehw5okkrjn7zxy04mxns",
"status": "paid",
"extId": "CM-1006",
"extKey": "CM-1006",
"amount": 50,
"amountRemaining": 0,
"currency": "USD",
"extCreationDate": "2026-07-28T00:00:00.000Z",
"extPostedDate": "2026-07-28T00:00:00.000Z",
"erpName": "PaystandLiteSync",
"created": "2026-07-28T15:10:00.000Z",
"lastUpdated": "2026-07-30T22:26:48.000Z"
}
},
"sourceId": "hs3vn8xj7q1amewz0k4t2pcy",
"sourceType": "ReceivableTransactions",
"status": "active",
"created": "2026-07-30T22:26:48.000Z",
"lastUpdated": "2026-07-30T22:26:48.000Z",
"eventType": "receivable_transactions.created"
}

In both event shapes, resource.receivable always reflects the receivable's actual post-payment state (amountPaid, status) — this holds the same way whether the payment was fully or partially covered by credit memos.

Key Credit Memo Event Fields

FieldDescription
resource.idUnique credit memo identifier
resource.extIdYour ERP's credit memo ID
resource.statusCurrent credit memo status (active, paid, canceled, expired)
resource.amountOriginal credit memo amount
resource.amountRemainingRemaining unapplied balance
resource.currencyCurrency code
diff.changesWhat changed in this event — only present for fields that actually changed
sourceTypeAlways "CreditMemo" for credit memo lifecycle events
eventTypecredit_memo.created, credit_memo.updated, credit_memo.canceled, or credit_memo.activated
resource.paymentId (payment-application events)On a mixed payment, a real Payment ID shared between the Payment-typed event and its CreditMemo-typed sibling(s). On a credits-only payment, a synthetic credit-payment-<timestamp>-<suffix> identifier — not a fetchable Payment record.
resource.creditMemo (payment-application events, resourceType: "CreditMemo" only)The full contributing credit memo record — same fields as resource on a credit_memo.* lifecycle event (id, ownerId, status, extId, extKey, amount, amountRemaining, currency, extCreationDate, extPostedDate, erpName, created, lastUpdated)

Handling Credit Memo Events

Best Practices

  1. Use the credit memo ID for idempotency: Track processed events using resource.id
  2. Check both status and amountRemaining on credit_memo.updated: full consumption changes both in the same event
  3. Correlate payment-application events by paymentId, not by assuming exactly one event per payment — a mixed credit+cash payment fires a Payment-typed event plus one CreditMemo-typed event per contributing credit memo
  4. Don't assume synchronous delivery: the CreditMemo-typed event(s) on a mixed payment arrive asynchronously, shortly after the Payment-typed event — wait briefly before concluding an expected event didn't fire
  5. These events fire regardless of merchant type or origin (CSV import, native ERP, or Paystand X API connector) — filter on your own ownerId/extId if you only care about credit memos you created

Common Use Cases

  • ERP reconciliation: Update your ERP's credit memo balance when credit_memo.updated fires
  • Payment attribution: Use the paymentId correlation to split a mixed payment's cash and credit portions in your accounting system
  • Expiration handling: React to credit_memo.updated events where diff.changes.status === "expired" without polling for expiration yourself