Integration rules

Rules for the three v1 contracts: first what holds on all of them, then what each one adds. v2 has its own rules — switch the version selector to v2.

Every v1 contract

  1. HTTP 2xx is not a final outcome. Read the status field. On payouts a validation failure is even returned as HTTP 200 — the outcome is inside the XML body.
  2. Only a final status is an outcome. The final set differs per contract; see the table below. Never treat a non-terminal value as success.
  3. A timeout tells you nothing. It does not mean failure, it does not cancel anything. Retry the identical request; never create a replacement transaction.
  4. Your own reference is unique. merchant_transaction_id (Apple Pay, Google Pay), reference (card payments) and id (payouts) identify one business transaction. Generate it once, persist it before you call.
  5. An unknown status leaves the transaction unresolved. Keep polling, keep accepting callbacks, do not decide it failed.
  6. Sign the exact bytes. Re-serializing, pretty-printing, or sorting keys changes the signature.
  7. Callback handlers are idempotent. Deliveries can repeat on every contract. Do not rely on their order.
  8. A callback is a notification, not proof. Re-read the transaction before releasing goods or crediting an account.

Final statuses by contract

Pay-ins are one area with three methods, but not one contract: Apple Pay and Google Pay share a status vocabulary, card payments have their own, and payouts a third.

Contract Not final Final
Pay-ins — Apple Pay, Google Pay pending (deprecated: order_scheduled, redirect_pending) paid, order_failed, refunded
Pay-ins — card payments 0, 1, 8, 15 3 paid, 4 refunded, 98 expired, 99 failed
Payouts OK, PROCESSING PAID, NOT_PAID, ERROR

OK on a payout means accepted for processing, not completed. The result arrives later, by callback or check.

Pay-ins — Apple Pay and Google Pay

  • Two headers: Sdk-Partner-Token (service_id:secret) and X-Signature.
  • X-Signature is HMAC-SHA256 of the compact JSON body, keyed with your Sign Key, lowercase hex. Sign the field order you transmit; sorting the keys produces a different signature. Keep null values in the signed payload.
  • GET requests carry no body and need only Sdk-Partner-Token.
  • When a create or GET /sdk-partner/alternative-mobile-pay/mobile-pay/{id}/status response carries redirect_data, send the buyer to redirect_data.url — in any non-final status. Some payments start only after the buyer opens it and end order_failed after 10 minutes without it. The buyer returning is not confirmation.
  • Poll GET /sdk-partner/alternative-mobile-pay/mobile-pay/{id}/status from 5 seconds after the create until the status is final. A webhook can bring the result sooner; delivery can be delayed.
  • Replay the same merchant_refund_id to make a refund idempotent.

Pay-ins — card payments

  • Credentials are api_key and secret_key, issued separately from the Apple Pay and Google Pay ones. They do not authenticate against each other.
  • Every request carries two fields: data, the request JSON base64-encoded, and sign, its signature. api_key goes inside the encoded data, not beside it.
  • sign is hash_hmac with the MD5 algorithm over the base64 string, keyed with secret_key. Sign the encoded string, not the JSON before encoding.
  • Verify sign on callbacks the same way before trusting the payload.
  • status is an integer, not a string. 1 is authorization — funds locked, not taken. The payment is complete at 3.
  • 8 means the provider had a temporary problem and returns a payment form link to redirect the payer to. It is not a failure.
  • 15 means a refund is still processing, which can take 1–7 days.

Payouts

  • hash is MD5 of specific fields concatenated with no delimiter, plus secret_key. The field set differs per endpoint. Empty fields are skipped silently, which is why a wrong hash usually means a field you left blank.
  • Responses are XML even when the request was JSON.
  • Repeating an id returns the existing payout with its current status. There is no check that the body matches, so a retry with a changed amount silently returns the old payout. Never change the body on retry.
  • Callbacks are form-urlencoded POST with RESULT 1/0 and an MD5 HASH. Up to 15 retries over about two days.
  • Reconcile with check when a callback is lost.