Payments

The Payment object, its statuses and how a payment moves from creation to a final result.

A Payment represents one attempt to collect money from a customer. You create it from your server, the customer pays on the hosted checkout, and the payment ends as succeeded or expired.

Lifecycle

Open
requires_payment

Created. Waiting for the customer to pay at checkout_url.

In flight
processing

The customer submitted payment. The result is not final yet.

Result
succeeded

Money captured. Final. Safe to fulfil. Refunds allowed.

failed

Declined or errored. See failure_code. Can still be paid at checkout_url until expires_at.

canceled

The customer canceled at checkout. Can still be paid until expires_at.

expired

Not paid before expires_at. Final.

Payment status lifecycle
StatusFinalMeaningWhat to do
requires_paymentNoCreated. Waiting for the customer at checkout_url.Redirect the customer to checkout_url.
processingNoThe customer submitted payment; the result is not known yet.Show "We're confirming your payment" and wait for the webhook.
succeededYesMoney captured.Fulfil the order. Refunds are possible.
failedNoDeclined or errored. failure_code and failure_message explain why.Let the customer try again at the same checkout_url until expires_at.
canceledNoThe customer clicked Cancel at checkout.Offer to try again at the same checkout_url.
expiredYesNot paid before expires_at.Create a new payment if the customer comes back.

succeeded and expired are final and never change. failed and canceled are not: until expires_at, the customer can open the same checkout_url and pay again, and the payment can still become succeeded. Don't close the order on payment.failed or payment.canceled; wait for payment.succeeded or payment.expired.

Refunds don't change status: they increase amount_refunded instead. A payment with amount_refunded equal to amount is fully refunded; anything in between is partially refunded. See Refunds.

Each of these status changes sends a webhook event: payment.succeeded, payment.failed, payment.canceled or payment.expired.

Create a payment

POST /v1/payments

ParameterTypeRequiredDescription
amountintegerYesAmount in minor units. 12500 with KWD is 12.500 KWD.
currencystringYesKWD, SAR, AED, QAR, BHD, OMR, JOD or EGP.
return_urlstringYesURL the customer returns to after checkout, up to 2,000 characters. Must be https:// in live mode; test mode also accepts http://. See Return URL handling.
descriptionstringNoUp to 500 characters. Shown to the customer at checkout and in your dashboard.
referencestringNoYour own ID, such as the order number, up to 100 characters. You can filter payments by it.
customerobjectNoname, email, phone (international format, for example +96550000000). All optional.
payment_methodstringNoOffer only this method at checkout: knet, mada, card, apple_pay, google_pay, benefit, stc_pay. Which ones you can use depends on your account; a method your account doesn't support returns 422 validation_error. See Payment methods and your account.
languagestringNoCheckout language: en or ar.
send_emailbooleanNotrue emails the payment to customer.email as an invoice with a Pay now button. Default false. Requires customer.email. See Invoice and receipt emails.
metadataobjectNoUp to 20 string key/value pairs. See Metadata.
expires_in_minutesintegerNoHow long the customer has to pay, from 5 to 43200 (30 days). Default 60.

On some accounts, amounts in three-decimal currencies (KWD, BHD, OMR, JOD) must end in 0, or the request fails with 422 validation_error (details.fields.amount). See Three-decimal amounts.

The response is 201 Created with the Payment. Send an Idempotency-Key header so retries never create a second payment (Idempotency).

The Payment object

{
  "id": "pay_01JBX4T9W2",
  "object": "payment",
  "livemode": false,
  "amount": 12500,
  "currency": "KWD",
  "amount_refunded": 0,
  "status": "succeeded",
  "description": "Order #1042",
  "reference": "1042",
  "customer": { "name": "Sara Ali", "email": "sara@example.com", "phone": "+96550000000" },
  "payment_method": "card",
  "card": { "brand": "visa", "last4": "1019" },
  "channel": "api",
  "checkout_url": "https://api.teyra.co/checkout/pay_01JBX4T9W2",
  "return_url": "https://shop.example.com/thanks",
  "failure_code": null,
  "failure_message": null,
  "commission": 313,
  "net": 12187,
  "metadata": { "order_id": "1042" },
  "payment_link_id": null,
  "created_at": "2026-10-28T14:07:00.000Z",
  "paid_at": "2026-10-28T14:08:12.000Z",
  "expires_at": "2026-10-28T15:07:00.000Z"
}
FieldDescription
idUnique ID, prefixed pay_.
livemodefalse for test payments, true for live payments.
amount, currencyWhat the customer pays, in minor units.
amount_refundedTotal refunded so far, from 0 up to amount.
statusSee Lifecycle.
payment_methodHow the customer paid, once known: card, mada, knet, apple_pay, google_pay, benefit, stc_pay, or null. For Apple Pay and Google Pay, card holds the wallet card's brand and last four digits.
cardFor card payments, brand and last4 only. Teyra Pay never exposes full card numbers.
channelWhere the payment came from: api, payment_link, shopify, woocommerce or dashboard.
checkout_urlTeyra Pay hosted checkout for this payment.
failure_code, failure_messageWhy the payment failed, when status is failed.
commission, netSet once the payment succeeds, in minor units. commission is the Teyra Pay fee: your rate (a percentage plus a fixed amount per payment), the only fee taken from the payment. net is what you receive: amount − commission. See Fees and net amount.
payment_link_idThe payment link that created this payment, if any.
paid_at, expires_atWhen the payment succeeded, and the deadline to pay.

Retrieve and list payments

# One payment
curl https://api.teyra.co/v1/payments/pay_01JBX4T9W2 \
  -H "Authorization: Bearer $TEYRA_SECRET_KEY"

# Succeeded payments created in October 2026
curl -G https://api.teyra.co/v1/payments \
  -H "Authorization: Bearer $TEYRA_SECRET_KEY" \
  -d status=succeeded \
  -d created_gte=2026-10-01T00:00:00Z \
  -d created_lte=2026-10-31T23:59:59Z \
  -d limit=50

GET /v1/payments filters: status, reference, created_gte, created_lte, plus limit and cursor (Pagination). An unknown ID, or one from the other mode, returns 404 payment_not_found.

Next