Skip to main content

Payments and their statuses

The payment object, its payment methods and destination, the unique amount, how receipts and deposits complete it, and every status a payment can be in.

A payment is one amount you want to receive, for one order. Your customer pays it card to card or by bank transfer, straight to your card or account, and sends a receipt. Money that your team approves from a receipt, or that a bank SMS shows arrived, is a deposit. A payment collects deposits until they reach its amount, which is why a wrong transfer is never a dead end.

Creating a payment

POST /v1/payments takes:

Creating a payment
ParameterDescription
amountRequired. Integer rial, from 10,000 to 2,000,000,000.
referenceYour order id, up to 100 characters. Shown on the checkout and searchable in the dashboard.
descriptionUp to 500 characters.
customer or customer_detailsAn existing customer id (cus_…), or { name, phone, email }.
return_url, cancel_urlWhere the checkout sends the customer back, with a signed status. See hosted checkout.
expires_inSeconds the checkout stays open, 300 to 86,400. Defaults to your checkout setting (30 minutes).
allow_partialTrack several deposits toward the amount. Defaults to your payments setting (on).
cardA destination id (card_…): a card or an account that takes one of your enabled payment methods. Defaults to your routing (your default destination, round robin or least used).
metadataUp to 50 string keys of 40 characters, values up to 500.
curl https://a.bezanbecard.com/v1/payments \
  -H "Authorization: Bearer sk_test_…" \
  -H "Idempotency-Key: order-1042" \
  -H "Content-Type: application/json" \
  -d '{"amount":12500000,"reference":"1042","customer_details":{"name":"Test Customer","phone":"09900001234"},"metadata":{"order_id":"1042"}}'

Methods and destination

payment_method_types says how the customer may pay: card (card to card) and transfer (Pol, Paya, Satna or a same-bank transfer to the IBAN). It is fixed when the payment is created, from the methods you enabled that its destination takes.

destination names where the money goes: card (the destination's id), type (card or account), bank, last4 (null for an account), iban_last4 and holder_name. With a secret key it also carries the full pan and iban for a custom checkout. Bank transfers has the details.

The unique amount

A receipt or a bank SMS says how much arrived on which card or account, and little else. To keep transfers apart, every payment asks for an amount no other open payment on the same destination is asking for: expected_amount. It is amount plus a small unique sum (by default between 1,000 and 99,990 rial, in steps of 10; you can choose to subtract it instead in the payments settings).

The customer pays exactly expected_amount, and paying it in full counts as paying amount in full: the unique sum never shows up as an overpayment. The hosted checkout shows the figure and copies it with one tap. If you build your own checkout, show expected_amount (never amount) and the exact rial figure.

You can turn unique amounts off in the payments settings. expected_amount then equals amount: simpler for the customer, but a bank SMS can no longer tell apart two open payments of the same amount. See unique amounts on or off.

How a payment is completed

  1. The customer pays from their bank app and sends a receipt on the checkout. The payment becomes Awaiting approvalprocessing.
  2. A member of your team approves the receipt in Receipts. The approval puts a deposit of that amount on the payment.
  3. The payment is recomputed from its deposits: Succeededsucceeded when they reach amount, Partially paidpartially_paid with a top-up when they fall short, an overpayment when they pass it.

Your team can also reject the receipt (the payment waits for another), approve a payment directly, or attach a deposit by hand. See receipts and review and corrections.

How a bank deposit is matched

A deposit also arrives without a receipt: from the optional SMS app, when you record one by hand, or when you simulate one in test mode. Bezanbecard then looks at the open payments on that card or account, in this order, and stops at the first rule that finds exactly one:

  1. Exact amount. A payment whose current expected_amount equals the deposit.
  2. An earlier amount. A payment that asked for this amount before a top-up replaced it.
  3. Payer card and claim. The SMS names the payer's card, and one payment had a customer report a card-to-card transfer with the same last four digits in the last two hours. This is how wrong amounts are caught: less becomes a partial payment, more an overpaid success.
  4. A single recent claim. One payment is waiting with a recent claim and the deposit is within half of its amount either way. A Paya or Satna claim stays recent longer. This is only a suggestion: the payment goes to review and a person confirms it.

A rule that finds two candidates never guesses. A deposit no rule matches waits in the dashboard's Review and fix inbox with suggestions, where you attach it by hand. When a receipt on the payment fits the deposit, the SMS corroborates the receipt instead of counting a second time.

With automatic approval off (the default), a deposit these rules match in full does not complete the payment by itself: the payment goes to review with auto_disabled and a person approves it.

Statuses

Statuses
StatusMeaning
Awaiting transferrequires_paymentWaiting for the customer to pay expected_amount and send a receipt.
Awaiting approvalprocessingThe customer sent a receipt, or said they paid. Waiting for your team's review.
Partially paidpartially_paidDeposits so far are below amount. amount_remaining is still due, with a fresh unique amount for it.
Needs reviewrequires_reviewA person needs to decide. review.reason says why.
SucceededsucceededDeposits reached amount, or a member approved the payment.
CanceledcanceledYou canceled it before it succeeded.
ExpiredexpiredNothing arrived and no receipt was sent before the checkout closed.

A payment with a pending receipt stays processing until your team decides; no timer moves it. A canceled or expired payment still catches a late transfer until the grace period after its checkout's expiry ends (60 minutes by default, and longer after a Paya or Satna claim: see the transfer wait window), and reopens. After that only a manual attach reaches it.

Review reasons

Review reasons
review.reasonWhy the payment waits for a person
no_smsOnly for an "I have paid" claim stored before receipts: no matching bank SMS arrived in the time such a transfer usually takes, or by the end of grace. A receipt without a file, from the checkout or /claim, waits in your Receipts queue (the payment stays Awaiting approvalprocessing) until a member decides.
expired_partialPart of the money arrived and the checkout closed before the rest did.
partial_disabledA deposit below the amount arrived while partial payments are off for this payment.
payer_mismatchThe deposit was matched automatically, but the payer's card is not one the customer claimed.
amount_mismatchRule 4 above: a suggested deposit waits for your confirmation.
auto_disabledA deposit the rules matched covers the full amount; with automatic approval off (the default), a person approves it.
detachedA correction took every deposit off a payment that had succeeded.

Corrections covers what you can do about each.

Amount fields

Amount fields
FieldDescription
amountWhat you asked for. Never changes.
amount_receivedThe money matched to the payment (approved receipts and bank deposits), summed from its deposits.
amount_remainingWhat is still due.
amount_overpaidWhat arrived beyond amount. See overpayments.
amount_shortfallWhat you forgave when you approved the payment without the full amount.
expected_amountThe exact amount to transfer (unique on the destination); null once the payment is terminal or past grace. It stays set while a receipt is under review (processing) and in requires_review, so ask for a transfer by status (requires_payment, partially_paid).

These are recomputed from the matched deposits on every change, never added up step by step, so a correction always leaves them right.

Reading, listing and updating

GET /v1/payments/:id returns one payment; add expand[]=deposits for the full deposit objects, expand[]=receipts for its receipts and expand[]=customer for the customer. GET /v1/payments lists them newest first and filters by status, customer, reference and created (see pagination).

POST /v1/payments/:id changes description, metadata and customer_details while the payment is open. POST /v1/payments/:id/cancel cancels an open payment, with an optional reason of 3 to 500 characters; if money had already arrived, the payment records it as owed back to the customer.

Events

Every status change emits an event your webhook endpoints receive: payment.created, payment.processing, payment.partially_paid, payment.requires_review, payment.succeeded, payment.overpaid, payment.overpayment_resolved, payment.canceled, payment.expired and payment.updated. Receipts emit their own: receipt.created, receipt.approved and receipt.rejected.