Integration rules
The single list of rules for v2. Other pages refer to them by number: R1…R20. Each rule is backed by the OpenAPI document.
Access
-
R1. A key is a shop.
Authorization: Bearer <shop_key>. A shop is payin or payout, with one currency. The other shop type's endpoints return403 method_not_enabled. -
R2. Sandbox and production keys never mix.
psbox_…works only on the sandbox host,plive_…only on production. -
R3. The endpoint is the method. One create endpoint per method; the body has no method field.
A method not enabled for the shop returns
403 method_not_enabled.
Creating
-
R4.
merchant_referenceis the idempotency key of a create. Generate it once, save it, then call. Repeating the call with the same reference and body returns the existing transaction (Idempotent-Replayed: true); a different body returns409 merchant_reference_conflict. It never expires and is unique per merchant across payins, refunds, payouts and pay sessions. -
R5.
captureandvoidare safe to repeat. A repeat while the action is in progress, or after it, returns the payin in its current status. - R6. A timeout tells you nothing. Resend the identical request; never create a replacement transaction.
- R7. Amounts are strings in major units, at most two decimals:
"100.50".
Outcome
- R8.
2xxis not an outcome. Readdata.status. Final:completedandfailed. -
R9. A decline is a status, not an error. The request succeeds; the transaction ends
failedwith the reason instatus_details.code. A voided hold and a payer who rejected arefailedtoo. -
R10.
requires_actionnames the step innext_action:redirectorawait_confirmation. Open a redirect as a full page, never in an iframe, beforenext_action.expires_atwhen it is set — see Payer actions. -
R11.
authorizedis a card hold, not a payment. Callcaptureorvoid. A rejected capture or void returns the payin toauthorized. -
R12. A refund is its own transaction. When it completes, the payin moves from
completedtorefundedandrefunded_amountgrows. -
R13. Unknown enum values are expected. An unknown status is not final; an unknown
status_details.codeis a decline; an unknownnext_action.type— stop and ask; an unknown event type — re-read the transaction.
Errors
-
R14. Branch on
error.code, never onmessage. Retry only429and500, with the identical request; on429waitRetry-After.
Webhooks
-
R15. Verify first. Pick the shop's signing secret by the URL or
shop_idin the body.Webhook-Signature: t=…,v1=…—v1is lowercase hex HMAC-SHA256 of<t>.<raw body>over the bytes received; reject atmore than 5 minutes off; accept either of twov1. -
R16. Acknowledge fast. Persist the event, answer
2xxwithin 30 seconds, process after. Otherwise up to 15 redeliveries over about two days — 16 attempts in total. -
R17. Deduplicate on the event
id, and mark an event processed only after it is processed. Do not rely on delivery order. -
R18. A signed webhook is the result. After the signature check (R15), act on
data.object— it is the full transaction. Read the transaction only when the event type is unknown. A late non-final event never overrides a final status.
Reconciliation
-
R19. Sync by change time.
listTransactionswithorder=updated_asc,updated_from= the end of the last window minus 5 minutes,updated_to= now; deduplicate onid. A final status never changes, except a payincompleted→refunded. -
R20. Webhooks are the channel; reading is the fallback. Learn about status changes from
webhooks. If no webhook has come for a minute, you can start polling
retrieveTransactionuntil the status is final. Polling instead of webhooks loads the API and gets429 rate_limited. Missed webhooks are also caught by the sync (R19).