Skip to main content
Meridian sends a webhook every time a payment link transaction changes status. Each webhook carries both the payment link and the transaction, so you can tie a payment to its link without another API call. This works for single and recurring links.

Before you start

Ask Meridian to register an endpoint for each event you want. Meridian registers endpoints per event name, so register all four to follow a payment end to end:
  • payment_link_transaction_created
  • payment_link_transaction_status_updated
  • payment_link_transaction_succeeded
  • payment_link_transaction_failed
Meridian signs these webhooks the same way as every other webhook. See Security to verify them.

Route the event

Every delivery includes these headers: The body has no envelope. It is a JSON object with paymentLink and transaction, and the event name is only in the X-Meridian-Event-Type header. Read the header first, then act on transaction.status.
paymentLink is the same object the Payment Links API returns. See Payment Link Transaction for the full schema and an example of each event. Amounts are decimal strings, timestamps are UTC, and fields with no value are sent as null instead of being omitted. The payload does not include payer names, bank accounts, or instrument details.

Status flow

A successful payment moves through these statuses: PENDING → PROCESSING → USER_DEDUCTED → COMPLETED

Failures

A transaction that reaches FAILED, DEBIT_FAILED, RETURNED, or REVERSED sends payment_link_transaction_failed. The statusReason field holds the failure reason when there is one. For example, a failed payment sends status: FAILED, previousStatus: PROCESSING, and statusReason: INSUFFICIENT_FUNDS.

Reversals

A reversal sends payment_link_transaction_status_updated at REVERSAL_IN_PROGRESS. It sends payment_link_transaction_failed only when it reaches REVERSED.

Other statuses

These statuses also send payment_link_transaction_status_updated: PENDING_MANUAL_REVIEW, EDD_REQUIRED, REFUND_IN_PROGRESS, REFUNDED, PARTIALLY_REFUNDED, TIMED_OUT_REVERSAL_DECISION_PENDING, RETURN_IN_PROGRESS, and NOT_RECEIVED.

Handle the webhooks correctly

1

Treat transaction.status as the source of truth

Use transaction.status and transaction.previousStatus to decide what happened, not the event name alone.
2

Expect repeated failed events

Each failure status is its own change, so one transaction can send payment_link_transaction_failed more than once. For example, FAILED then DEBIT_FAILED, or COMPLETED then RETURNED after an ACH return. Handle repeated failed events for the same transaction.id.
3

Don't trust paymentLink.status for the outcome

paymentLink is a snapshot from when Meridian sent the webhook. Meridian updates the link and the transaction separately, so the link’s status can lag the transaction. In payment_link_transaction_created the link can still be ACTIVE, and in payment_link_transaction_failed it can show its previous status. Fetch the link through the API if you need its final state.
4

Process idempotently

Key on transaction.id plus transaction.status. Each status change sends exactly one event, but retries can still deliver the same webhook more than once.
5

Order by updatedAt

Meridian does not guarantee delivery order. Use transaction.updatedAt to order events for the same transaction.
6

Reconcile through the API

Delivery is best effort. Meridian retries a failed delivery up to 3 times, a few hundred milliseconds apart. It is not a guaranteed, replayable queue, so periodically reconcile your records through the API.

Behavior change

Payment link transactions no longer send the generic transaction_created, transaction_succeeded, and transaction_failed events. They send the payment_link_transaction_* events instead. REVERSAL_IN_PROGRESS used to be reported as a failure and is now a payment_link_transaction_status_updated event. Statuses such as PROCESSING and USER_DEDUCTED were not reported before. The transaction_* events still exist and are unchanged for Meridian Accounts.