Skip to content

Telr

Setup guide for the telr payments provider. The shared API (initiate_payment, verify_payment, refund_payment, webhooks, hooks, saved methods) is documented in Payments.

The telr provider supports one-time payments through Telr’s Hosted Payment Page (initiate_payment, verify_payment) and webhooks (Telr’s transaction advice), in the Gulf and other currencies your store accepts (AED, SAR, KWD, BHD, OMR, JOD, QAR, EGP, USD, …). GET /payments/providers reports no optional capability.

Feature Status
One-time payments (Hosted Payment Page), verify Supported
refund_payment Not supported (NOT_SUPPORTED, 501): refunds need Telr’s Remote API, enabled per store; refund in the Telr admin and the transaction advice records it
Subscriptions, disputes, billing portal Not supported (NOT_SUPPORTED, 501)
Saved payment methods, charge_off_session Not supported (NOT_SUPPORTED, 501)

It needs no extra install: it calls https://secure.telr.com/gateway/order.json directly over HTTP, following Telr’s integration docs as of September 2026.

Why plain HTTP (no Telr SDK). Telr publishes no Python SDK.

1. Get credentials. In the Telr Merchant Administration System (MAS), note the store id and create an authentication key for the Hosted Payment Page.

2. Set the transaction advice. In MAS, Payment Page (or Security) -> Transaction advice, set the URL to https://your-domain.com/payments/webhook/telr (/payments/webhook/<instance> for another instance name) and set a secret key, which signs each advice’s tran_check.

3. Configure the instance and secrets. In kirak.json:

"telr": {
"type": "telr",
"store_id": "15996",
"environment": "test",
"success_url": "https://your-domain.com/payment/return"
}

store_id is the numeric store id. environment is test (the default, which marks orders test) or live. success_url is required and must be absolute: Telr returns the buyer to it after paying, declining or cancelling. Anything else is a CONFIGURATION_ERROR at startup. In the environment:

Terminal window
KIRAK_PAYMENT_TELR_AUTH_KEY=<the authentication key>
KIRAK_PAYMENT_TELR_ADVICE_SECRET=<the transaction advice secret key>

For an instance with another name the variables are KIRAK_PAYMENT_<INSTANCE>_AUTH_KEY and KIRAK_PAYMENT_<INSTANCE>_ADVICE_SECRET. Both are required.

4. Use it:

result = await kirak.payments.initiate_payment({
"provider": "telr",
"user_id": "42", "amount": 1500, "currency": "KWD", # fils: KWD 1.500
"name": "Pro Plan", "type": "one_time",
})
reference = result["data"]["reference"] # the cart id, kirak-<32 hex>
# redirect the buyer to result["data"]["url"] at once (the order is short lived)
# On the return page: completes the row if the order was paid
await kirak.payments.verify_payment({"provider": "telr", "payment_id": reference})

Payments. initiate_payment stores a random cart id (kirak-<32 hex>) on the PENDING row before calling order.json (method: "create", amount x quantity as a major-unit decimal string, description = name, the return URLs), then keeps Telr’s order ref on the row and returns the payment page url. An error answer marks the row FAILED (TELR_ERROR, 400); a timeout, 5xx or 429 leaves it PENDING.

The order is always read with order.json method: "check" before the row changes: a Paid order with the row’s cart id, currency and an amount of at least amount x quantity, whose transaction is authorised (A or H), completes the row once; an Expired or Cancelled order fails it. Telr retries a transaction advice only 3 times, 5 seconds apart, so verify_payment (payment_id = the cart id) is the main completion path: call it when the buyer returns. It reports no event: the first authorised sale advice of that transaction still reports payment_completed once, so fulfil on the event and use verify_payment’s status only for the return page. If no advice arrives (all three attempts failed), there is no event.

Transaction advice. Each advice (a form POST) must carry a tran_check equal to the SHA1 hex of <secret>:<tran_store>:<tran_type>:<tran_class>: <tran_test>:<tran_ref>:<tran_prevref>:<tran_firstref>:<tran_currency>: <tran_amount>:<tran_cartid>:<tran_desc>:<tran_status>:<tran_authcode>: <tran_authmessage> (missing fields empty) and name this instance’s store; a missing check is MISSING_WEBHOOK_SIGNATURE, a wrong one INVALID_WEBHOOK_SIGNATURE (400). An authorised sale advice runs the same check (payment_completed, with amount and currency, when it completes the row); an order the check does not show paid yet fails the advice (500) so Telr sends it again, while a paid order that does not match is acknowledged (order.not_paid). An authorised refund advice of the transaction that completed the row is recorded (keyed by its tran_ref, with a running total; refund_completed). Advices are deduplicated on tran_type + tran_ref.

Currencies. Telr amounts are major-unit decimal strings with ISO 4217 decimals; KWD, BHD, OMR and JOD have three (1500 fils = "1.500").

Known limits.

  • refund_payment is not supported; refunds made in the Telr admin are recorded from their advice.
  • The order status codes (3 Paid, -1 Expired, -2 Cancelled) follow Telr’s Hosted Payment Page documentation and are on the sandbox checklist.
  • Subscriptions (repeat billing), saved cards and off-session charges are not supported.

after_webhook receives these provider-neutral event names (see Webhook Hooks):

Telr reports payment_completed (an authorised sale transaction advice whose check completes the row, event_type transaction_advice; a declined one reports none, with advice.declined, and a paid order that does not match none, with order.not_paid; one not paid yet fails the advice so Telr retries), payment_failed (an expired or cancelled order, order.ended) and refund_completed (an authorised refund advice, refund.recorded); verify_payment reports no event, but a payment it completed is reported by the first sale advice of its transaction.