Payment methods and your account

Which payment_method values your account accepts, the amount rule for three-decimal currencies, and how checkout, fees, refunds and disputes work on each kind of account.

Every Teyra Pay account uses the same integration: the same endpoints, objects, webhooks and checkout_url. When your account is approved, Teyra Pay connects it to the card-processing setup that fits your country and currencies. A few things depend on that setup, and this page lists all of them, so your code works on any account.

In short

Leave payment_method out unless you really need one method, handle 422 validation_error on POST /v1/payments, keep three-decimal amounts ending in 0, and confirm payments from the webhook or GET /v1/payments/:id, never from the redirect alone.

Payment methods by account

Methodpayment_methodAvailable on
Visa, Mastercard and other cardscardEvery account
Apple Payapple_payEvery account, on devices and browsers that support it
Google Paygoogle_payEvery account, on devices and browsers that support it
KNETknetDepends on your account: accounts that support it, for KWD
madamadaDepends on your account: accounts that support it, for SAR
BenefitbenefitDepends on your account: accounts that support it, for BHD
STC Paystc_payDepends on your account: accounts that support it

UAE accounts accept card, apple_pay and google_pay. Local methods such as KNET and mada are only available on accounts that support them. If you're not sure what your account supports, ask support@teyra.co, or try it in test mode: a method your account doesn't support is refused straight away (see below).

Asking for a method your account doesn't support

payment_method is optional. Without it, checkout shows every method your account supports for the currency and the customer's device, which is what most integrations want. If you do pass it and your account can't take that method, POST /v1/payments answers 422 and creates nothing:

{
  "error": {
    "code": "validation_error",
    "message": "This payment method is not available for your account.",
    "details": { "fields": { "payment_method": "unsupported" } }
  }
}

Fix it by leaving payment_method out, or by offering only the methods in the table above that your account supports. Don't retry the same request: the answer won't change.

What payment_method reports

Once a payment succeeds, payment_method says how the customer paid. On UAE accounts it is always card, apple_pay or google_pay. For Apple Pay and Google Pay, card holds the brand and last four digits of the card in the customer's wallet:

{ "payment_method": "apple_pay", "card": { "brand": "visa", "last4": "4242" } }

Build your code to accept any value from the full list in Payments, so nothing breaks if your account gains a method later.

Three-decimal amounts must end in 0 (some accounts)

On some accounts, including UAE accounts, amounts in the three-decimal currencies (KWD, BHD, OMR, JOD) must end in 0: 1250 (1.250 KWD) is accepted, 1255 (1.255 KWD) is not. Two-decimal currencies such as AED and SAR are not affected.

On those accounts, POST /v1/payments and POST /v1/payment-links (and payment links created in the dashboard) refuse such an amount before anything is created:

{
  "error": {
    "code": "validation_error",
    "message": "Amounts in this currency must end in 0 (for example 1.250, not 1.255).",
    "details": { "fields": { "amount": "unsupported" } }
  }
}

The simplest way to stay safe on any account is to round three-decimal prices to the nearest 10 fils (or baisa) before you send them, and to keep partial refunds in those currencies ending in 0 too:

const THREE_DECIMALS = new Set(['KWD', 'BHD', 'OMR', 'JOD']);

// 1255 KWD -> 1260; 1250 KWD -> 1250; AED amounts are unchanged
function payableAmount(minor, currency) {
  return THREE_DECIMALS.has(currency) ? Math.round(minor / 10) * 10 : minor;
}

See Money and currencies for minor units.

Checkout

The flow is the same on every account: create the payment, redirect to checkout_url, the customer comes back to your return_url with payment_id and status, and you confirm on your server. See Hosted checkout.

What the customer sees on UAE accounts:

  • Secure card fields in the Teyra Pay checkout page. The card number, expiry and CVV are typed into fields served by the card processor; they never reach your servers or Teyra Pay's.
  • Apple Pay and Google Pay as options in the same form when the customer's device and browser support them (Apple Pay in Safari with a card in Apple Wallet, Google Pay in a browser with a saved Google Pay card). Passing payment_method limits the page to that method.
  • 3-D Secure opens in a window on top of the checkout page when the customer's bank asks for it. The customer never leaves the page for the bank, and is sent to your return_url as soon as the payment is confirmed.
  • Declines are shown on the page with the bank's reason and a Try again button. The payment becomes failed (you get payment.failed), but it stays payable at the same checkout_url until expires_at, so a payment.succeeded can still follow.
  • Cancel works as on every account: the payment becomes canceled and the customer goes to your return_url with status=failed.

On accounts with local methods, KNET, Benefit and similar methods send the customer to their bank's page and back, and 3-D Secure for cards may also take place on the bank's page. Your code doesn't need to know which: both end at your return_url.

A payment can be processing for a short time when the customer comes back. Wait for the payment.succeeded or payment.failed webhook, or check again with GET /v1/payments/:id.

Fees and net amount

You pay one price on every account, whatever the payment method: the Teyra Pay fee, a percentage of the amount plus a fixed amount per payment. Your rate is shown under Business profile and Deposits in the dashboard. Processing costs are included in it; nothing else is deducted.

commission and net are set when the payment succeeds, in the payment.succeeded webhook and in GET /v1/payments/:id:

  • commission is the Teyra Pay fee for this payment: the percentage of amount, rounded to the nearest minor unit, plus the fixed amount. It's never more than amount.
  • net is amount − commission: what you receive for the payment.

For example, at 2.5% + 0.000 KWD, a 12.500 KWD payment (12500) has commission 313 and net 12187. Your balance is the sum of net less refunded amounts.

Refunds

Refunds work the same on every account: POST /v1/payments/:id/refunds, full or partial, with the same statuses, errors and refund.succeeded / refund.failed webhooks. See Refunds.

  • The refunded amount comes out of your balance. Teyra Pay's commission on the original payment isn't returned.
  • All four reason values are accepted on every account.
  • A refund starts as pending and usually becomes succeeded within seconds on UAE accounts. Card and wallet refunds take a few business days to appear on the customer's statement, depending on their bank.

Disputes

A dispute (chargeback) happens when a cardholder asks their bank to reverse a card, Apple Pay or Google Pay payment. On UAE accounts, every owner gets an email when a payment is disputed, and Refunds → Disputes in the dashboard shows each dispute's status and respond-by date. On other accounts, support contacts you. See Disputes for the statuses and what to do.

Testing

Test mode behaves like live mode for all of the above, so you can check your integration before you go live:

CheckHowExpected
Methods your account acceptsCreate test payments with each payment_method you plan to use201, or 422 with details.fields.payment_method = "unsupported" for a method your account doesn't support
Three-decimal amountsCreate a KWD test payment for 1255, then for 1250On accounts with the rule: 422 with details.fields.amount = "unsupported", then 201
Card payment and declinePay with a declined test card, click Try again, then pay with a successful oneThe decline reason on the page and payment.failed, then payment.succeeded for the same payment
3-D SecurePay with a test card that asks for authentication, then complete or fail the challenge in the windowComplete: succeeded. Fail: an error on the page with Try again, and failed
Apple Pay / Google PayOpen checkout_url on a supported deviceThe wallet button appears. In test mode no real money moves, even with a real card in the wallet
Wallet reportingPay with Apple Pay or Google Paypayment_method is apple_pay or google_pay, with the wallet card's brand and last4
Fee and net amountPay a test payment and read it with GET /v1/payments/:idcommission is your rate applied to amount, and net is amount − commission

Test card numbers depend on your account: see Testing.