sandbox

Stable. Describes behaviour that is built and covered by tests in this repository.

API reference

POST /v1/sandbox/close-period #

Sandbox only — close a period now and run the real billing flow

Lowers the period's cutoff to now + 5 s, then billing runs exactly as at month end: watermark (starting 30 s after the new cutoff), rating, numbering (SBX-…) and the invoice saga with mock payments. Poll GET /v1/invoices. period defaults to the current period. Live keys get 403.

Request body

FieldTypeDescription
periodstring
Example
{}

Responses

StatusMeaningBody
202AcceptedBillingRun
400Error envelopeError
403Error envelopeError
Example response
{
  "tenant_id": "string",
  "period_id": "string",
  "status": "RUN_STATUS_SCHEDULED",
  "cutoff_time": "2026-11-03T10:15:00Z",
  "invoice_count": 1,
  "last_error": "string",
  "generation": 1,
  "start_time": "2026-11-03T10:15:00Z",
  "complete_time": "2026-11-03T10:15:00Z"
}
curl
curl -X POST https://YOUR-API-ADDRESS/v1/sandbox/close-period \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

POST /v1/sandbox/customers/{external_id}/payment-scenario #

Sandbox only — choose the mock payment outcome for a customer

{"scenario": "declined"} sets pm_sandbox_declined. Live keys get 403.

Parameters

NameInTypeDescription
external_id requiredpathstring

Request body

FieldTypeDescription
scenario requiredsuccess | declined | insufficient_funds_once | error_then_success | timeout_committed | timeout_not_committed
Example
{
  "scenario": "success"
}

Responses

StatusMeaningBody
200OKCustomer
403Error envelopeError
Example response
{
  "id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
  "external_id": "string",
  "name": "string",
  "email": "string",
  "payment_method": "string",
  "create_time": "2026-11-03T10:15:00Z",
  "country": "string",
  "billing_currency": "string",
  "address": {
    "line1": "string",
    "line2": "string",
    "city": "string",
    "region": "string",
    "postal_code": "string",
    "country": "string"
  },
  "tax_id": "string",
  "tax_office": "string",
  "e_invoice_registered": false,
  "locale": "string",
  "customer_type": "string",
  "block_reason": "string",
  "block_category": "string",
  "service_suspended": false,
  "phone": "string",
  "tax_id_warning": "string"
}
curl
curl -X POST https://YOUR-API-ADDRESS/v1/sandbox/customers/<external_id>/payment-scenario \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scenario":"success"}'

GET /v1/sandbox/scenarios #

The payment scenarios of a sandbox customer

What each pm_sandbox_* payment method does. Sandbox keys only.

Responses

StatusMeaningBody
200OKSandboxScenariosResponse
403Error envelopeError
Example response
{
  "scenarios": [
    {
      "scenario": "declined",
      "payment_method": "pm_sandbox_declined",
      "outcome": "paid",
      "description": "string"
    }
  ]
}
curl
curl -X GET https://YOUR-API-ADDRESS/v1/sandbox/scenarios \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY"

POST /v1/sandbox/invoices/{id}/simulate #

Run an invoice's payment again under a scenario

Sets the invoice's customer to the scenario (it stays their payment method) and retries the invoice's payment. When the payment cannot run again now (paid, or in progress) the scenario is still set and retried is false with the reason in retry_error. Sandbox keys only.

Parameters

NameInTypeDescription
id requiredpathstring · uuid

Request body

FieldTypeDescription
scenario requiredstringA name from /v1/sandbox/scenarios, with or without the pm_sandbox_ prefix.
Example
{
  "scenario": "string"
}

Responses

StatusMeaningBody
200OKSandboxSimulateInvoiceResponse
400Error envelopeError
403Error envelopeError
404Error envelopeError
Example response
{
  "invoice_id": "string",
  "customer_external_id": "string",
  "scenario": "string",
  "payment_method": "string",
  "retried": false
}
curl
curl -X POST https://YOUR-API-ADDRESS/v1/sandbox/invoices/<id>/simulate \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scenario":"string"}'

Models

Address

FieldTypeDescription
line1 requiredstring
line2 requiredstring
city requiredstring
region requiredstringState, province or county
postal_code requiredstring
country requiredstringISO 3166-1 alpha-2

BillingRun

FieldTypeDescription
tenant_id requiredstring
period_id requiredstring
status requiredRUN_STATUS_SCHEDULED | RUN_STATUS_WAITING_WATERMARK | RUN_STATUS_RATING | RUN_STATUS_INVOICING | RUN_STATUS_COMPLETED | RUN_STATUS_FAILED
cutoff_time requiredstring · date-time
invoice_count requiredinteger
last_error requiredstring
generation requiredinteger
start_time requiredstring · date-time
complete_time requiredstring · date-time

Customer

FieldTypeDescription
id requiredstring · uuid
external_id requiredstring
name requiredstring
email requiredstring
payment_method requiredstring
create_time requiredstring · date-time
country requiredstringISO 3166-1 alpha-2
billing_currency requiredstringISO 4217
address requiredany
tax_id requiredstring
tax_office requiredstring
e_invoice_registered requiredboolean
locale requiredstringThe language of the customer's mails, receipts and payment pages: en, tr, de, fr, es or ar. Empty is the browser's language (pages) and English (mails).
customer_type requiredstringindividual (a person) or business (a taxpayer with a tax id). Empty is unknown.
block_timestring · date-timeSet while the customer is blocked: no new subscription, plan change or purchase (existing subscriptions run on). A block whose blocked_until has passed has ended, whatever this says.
block_reason requiredstringThe seller's own note on the block; never shown to the customer.
block_category requiredstringWhy: fraud, chargeback, abuse, request or other; empty when none was given.
blocked_untilstring · date-timeWhen the block ends by itself; absent: until it is lifted.
service_suspended requiredbooleanThe block also suspends the customer's service: every entitlement check answers allowed false. Read it with block_time and blocked_until, it holds only while the block does.
phone requiredstringThe customer's mobile number as E.164 (+905321234567); empty when none.
tax_id_validated_atstring · date-timeWhen tax_id last passed the local check (a TCKN or VKN checksum, the shape of a European VAT id). Not a registry lookup: no VIES, no GİB query. Absent when the id is empty or not recognised.
tax_id_warning requiredstringOne of tr_individual, tr_business, tr_any, tr_is_tckn, tr_is_vkn, eu_vat, or empty. A hint, never a refusal: the id does not look like the kind of number this customer should have (tr_individual: not a TCKN; tr_business: not a VKN; tr_any: neither; tr_is_tckn: a business was given a TCKN; tr_is_vkn: an individual was given a VKN; eu_vat: a business in the EU has no VAT id of its country's shape). Worked out from the stored id, country and customer_type, so it follows a change of any of them. Empty: nothing to say.

Error

FieldTypeDescription
error requiredobject

SandboxClosePeriodRequest

FieldTypeDescription
periodstring

SandboxScenariosResponse

FieldTypeDescription
scenarios requiredarray of SandboxScenariosScenario

SandboxScenariosScenario

FieldTypeDescription
scenario requiredstring
payment_method requiredstring
outcome requiredpaid | uncollectible | paid_after_retry | paid_after_status_query | paid_after_recharge
defaultboolean
description requiredstring

SandboxSimulateInvoiceRequest

FieldTypeDescription
scenario requiredstringA name from /v1/sandbox/scenarios, with or without the pm_sandbox_ prefix.

SandboxSimulateInvoiceResponse

FieldTypeDescription
invoice_id requiredstring
customer_external_id requiredstring
scenario requiredstring
payment_method requiredstring
retried requiredboolean
retry_errorstring

SetPaymentScenarioRequest

FieldTypeDescription
scenario requiredsuccess | declined | insufficient_funds_once | error_then_success | timeout_committed | timeout_not_committed