Skip to content

Payment Statuses

Baiyar has three separate status fields, at three different levels. Mixing them up is the most common source of confusion when checking whether a customer has paid:

Field Answers
Transaction.status Has this payment succeeded, failed, or is it still open?
Transaction.current_attempt.status What happened on the specific attempt currently in flight?
PaymentLink.status Is this link itself still payable?

This is the field to poll or watch webhooks for. It’s the overall outcome of one payment (created via a payment link or a direct payment):

Status Meaning
pending Just created; the first attempt hasn’t returned from the provider yet — transient, rarely observed
processing An attempt is in flight (the customer has valid, unexpired instructions)
succeeded Terminal. One attempt was paid — triggers payment.paid
failed The latest attempt didn’t succeed and none is in flight — the customer can still retry with a new attempt, as long as the transaction itself hasn’t expired
expired Terminal. The transaction’s own deadline passed without success — triggers payment.failed

failed is not terminal by itself — see Direct Payments for retrying with a new payment_method. Only succeeded and expired end a transaction for good.

current_attempt.status on the same response is the provider-facing status of the specific try underlying the transaction above — useful for understanding why a transaction is failed or building a more detailed UI:

Status Meaning
pending Awaiting customer action
paid This attempt succeeded — its transaction is now succeeded too
failed This attempt didn’t succeed
expired This attempt’s own window passed
cancelled Superseded by a method change, or explicitly reset
Section titled “Payment link status — separate on purpose”

A payment link’s own status tracks whether the link is still usable — not whether it’s been paid:

Status Meaning
active Payable now — stays active even after a single-use link’s one payment succeeds
cancelled Cancelled via POST /v1/payment-links/{id}/cancel
inactive Past its expires_at

To know whether a single-use link has actually been paid, check the transaction’s status, not the link’s — the link field deliberately doesn’t flip for that.