Testing
Test your integration end to end with test keys, the test checkout page and test cards, without moving real money.
Everything you build can be tested before your account is approved. Use a test secret key (sk_test_…): payments, refunds, payment links and webhooks behave like live mode, but no money moves and every object has "livemode": false. See Test mode and live mode.
The test checkout page
In test mode, checkout_url opens the same Teyra Pay checkout page your customers will see in live mode, marked with a TEST badge and the note "Test mode — no real money moves". The secure card fields are connected to the card processor's test environment, so only test cards work and no real money moves.
| What you do on the page | Result | Customer is sent to | Webhook |
|---|---|---|---|
| Pay with a test card that succeeds | status becomes succeeded, paid_at is set | return_url?payment_id=…&status=succeeded | payment.succeeded |
| Pay with a test card that is declined | status becomes failed, with failure_code and failure_message | return_url?payment_id=…&status=failed | payment.failed |
| Click Cancel | status becomes canceled | return_url?payment_id=…&status=failed | payment.canceled |
A canceled payment returns status=failed in the redirect, because the redirect only carries succeeded, failed or processing. Your server reads the exact status (canceled) from GET /v1/payments/:id.
A failed or canceled payment can still be paid at the same checkout_url until expires_at, so a payment.failed event can be followed by payment.succeeded. See Payments.
This lets you test every branch of your return page and webhook handler in a few minutes.
Test scenarios
Run through these before going live:
| Scenario | How to test | Expected |
|---|---|---|
| Successful payment | Pay with a successful test card | Order marked paid once, by the return page or the webhook, whichever comes first. |
| Declined payment | Pay with a declined test card | Customer sees a failure page and can try again. |
| Canceled payment | Click Cancel on the checkout page | Order stays unpaid; customer can try again. |
| Retry after a decline | Decline once, then open the same checkout_url and pay with a successful card | payment.failed, then payment.succeeded; the order ends up paid. |
| Customer never returns | Pay, then close the tab before the redirect finishes | The payment.succeeded webhook still marks the order paid. |
| Expired payment | Create a payment with "expires_in_minutes": 5 (the minimum) and wait | payment.expired webhook; checkout shows "This payment has expired". |
| Forged redirect | Open your return URL with ?payment_id=<a failed payment>&status=succeeded | Order is not marked paid. |
| Duplicate webhook | Retry a delivery from Developers → Webhooks | Order is processed only once. |
| Full and partial refunds | Refund a succeeded test payment | amount_refunded updates; refund.succeeded webhook. |
| Over-refund | Refund more than what remains | 422 refund_exceeds_amount. |
| Network retry | Send the same POST twice with the same Idempotency-Key | One payment; identical responses, the second with the Idempotent-Replayed: true header. |
| Three-decimal currency | Create a KWD payment for 1500 | Checkout shows 1.500 KWD. |
| Amount ending in 5 | Create a KWD payment for 1505 | On accounts with the three-decimal rule: 422 validation_error with details.fields.amount. Otherwise 201. |
| Unsupported method | Create a payment with a payment_method your account doesn't offer, such as knet on a UAE account | 422 validation_error with details.fields.payment_method = "unsupported". |
| 3-D Secure | Pay with a test card that asks for authentication | The challenge opens (in a window on the page or on the bank's page, depending on your account); completing it succeeds, failing it declines. |
| Apple Pay / Google Pay | Open checkout_url on a device with a wallet set up | The wallet option appears; payment_method is apple_pay or google_pay with the wallet card's brand and last4. In test mode no real money moves. |
Test cards
Test cards depend on the country of your account. Unless the table says otherwise, use any future expiry date and any 3-digit CVV. Never type real card numbers into the card fields in test mode.
Kuwait accounts
| Card | Number | Expiry | Result |
|---|---|---|---|
| Visa | 4508 7500 1574 1019 | Any future date | Success, after the 3-D Secure test page |
| Mastercard | 5123 4500 0000 0008 | 01/39 | Success, after the 3-D Secure test page |
| Mastercard | 5123 4500 0000 0008 | 05/39 | Declined |
On the 3-D Secure test page, approve the authentication to complete the payment; reject it to see a declined payment.
KNET, mada and other local methods have their own test credentials. Email support@teyra.co for the ones your account supports.
UAE accounts
| Card | Number | Result |
|---|---|---|
| Visa | 4242 4242 4242 4242 | Success |
| Visa | 4000 0027 6000 3184 | Asks for 3-D Secure; approve it to succeed, fail it to decline |
| Visa | 4000 0000 0000 0002 | Declined |
| Visa | 4000 0000 0000 9995 | Declined: insufficient funds |
KNET and other local methods can only be tested on accounts that support them. See Payment methods and your account for a checklist.
Test webhooks
- Use Send test event in Developers → Webhooks to send a signed
payment.succeededevent to an endpoint. - Every test payment you complete sends real test-mode events to your test-mode endpoints.
- Check delivery attempts, response codes and retry times in the deliveries list.
See Webhooks.