Skip to Content
SandboxOne-time paymentsSandbox knobs (test_info)

Sandbox knobs: test_info

XML: <TestInfo> inside CreateInvoiceRequest · JSON: the test_info object in the request body.

Every test knob lives in a single block, so when you move to production you just drop the whole block — the rest of the request stays the same. Production has no such block.

JSONXMLValuesEffect
expected_billing_resultExpectedBillingResultSuccess, Failed, SuccessSequencePayment, FailedSequencePaymentBilling outcome. With Failed* the callback arrives with PaymentStatus=FAILED / payment_status=NOT_PAID and code 210 PAYMENT_CHANNEL_NOT_ENOUGH_MONEY
callback_delay_secondsCallbackDelaySecondsinteger 0–60, default 10Delay before the first callback delivery. 0 means the next worker cycle (handy for demos), a large value helps debugging retries
callback_url—https://…Callback address instead of the one configured for the project. Only for partners with an explicit permission — see below

An invalid value never breaks the request: the mock logs a warning and falls back to the default.

Invoice state

GET /invoices/{invoice_id} and XML GetInvoice return the state of the stored invoice. The XML flow differs in one thing: the deferred billing outcome arrives not after callback_delay_seconds but 6 seconds after the first GetInvoice. Resolved in this order:

Whenstatuspayment_status
Right after creation (MSISDN)CreatedNOT_PAID
Card or SBP — before paymentWaitPaymentConfirmationNOT_PAID
After callback_delay_seconds, outcome Success*ProcessedPAID
After callback_delay_seconds, outcome Failed*FailedNOT_PAID + result_code=210
After paying on the checkout pageProcessedPAID
Card error (reserved last 4 digits)CancelledNOT_PAID
After cancel / refundCancelled / RefundNOT_PAID / PAID

An unknown invoice_id returns 404 with error.code = INVOICE_NOT_FOUND. Lookup by merchant_order_id is scoped to your project.

Your own callback address

The callback_url field is enabled on request and does not work with the demo credentials from “Access and test data”: those login and secret are public, and the field makes the sandbox send a request to an arbitrary address. For non-public credentials the flag is set in the Admin UI; otherwise the response is 400 TEST_CALLBACK_URL_FORBIDDEN.

The address is validated twice — when the request is accepted and again right before delivery (DNS may have changed in between):

RequirementOtherwise
https scheme only400 TEST_CALLBACK_URL_REJECTED
Host resolves and the resulting IP is public — private and reserved ranges (10/8, 172.16/12, 192.168/16, 127/8, 169.254/16, ::1, fc00::/7) are rejected400 TEST_CALLBACK_URL_REJECTED
At most 30 callbacks to a request-supplied address per minute per projectTEST_CALLBACK_URL_RATE_LIMITED
Redirects are not followed, delivery timeout is 5 secondsdelivery counts as failed

The rejection happens before the invoice is created: if the request was rejected, no invoice exists and you can retry it as is.

Sandbox block (JSON)
{ "client_ip": "10.20.30.40", "customer": { "type": "mobile_phone", "msisdn": "79600000000" }, "order": { "merchant_order_id": "ORDER-001", "price": { "amount": "99.00", "currency": "RUB", "vat_included": true } }, "test_info": { "expected_billing_result": "Failed", "callback_delay_seconds": 0, "callback_url": "https://dev-42.example.com/callbacks" } }
Callback address rejected
HTTP/1.1 400 Bad Request { "success": false, "error": { "code": "TEST_CALLBACK_URL_REJECTED", "message": "test_info.callback_url rejected: address 10.0.0.5 belongs to a private or reserved range" } }