Simulation Endpoints
The emulation engine runs autonomously and produces realistic, non-deterministic outcomes by default. When a test scenario requires a specific, controlled outcome — a KYC approval, an exact deposit amount, a precise card spend — the staging-only simulation endpoints under /staging/* let you force that state on demand.
Staging only. All endpoints on this page are prefixed
/staging/and exist only athttps://staging.api.axyscards.com/v2. Calling them against the production base URL (https://production.api.axyscards.com/v2) will return404. They are not part of the published production API and have no effect on production data.
Amount format differs from the main API. Where the main API uses decimal-implied integers for monetary amounts (
1000= $10.00), the simulation endpoints use decimal strings with up to 2 decimal places — e.g.,"10.00"rather than1000. See each endpoint below for the exact field description.
Force a KYC outcome
POST /staging/kyc/validate
Forces a KYC result for a cardholder in status = 3 (Under Review). Use this to deterministically reach either the Approved or Compliance Decline state without waiting for the emulation engine's natural review timing.
| Field | Required | Type | Description |
|---|---|---|---|
cardholderId | Yes | integer | The cardholder to apply the result to. Must be status = 3 (Under Review). |
result | Yes | string enum | pass → cardholder moves to status = 1 (Approved) · fail → cardholder moves to status = 2 (Compliance Decline) |
Example — force an approval
curl --cert staging-cert.pem --key staging-key.pem \
-H "X-API-Key: YOUR_STAGING_API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://staging.api.axyscards.com/v2/staging/kyc/validate" \
-d '{ "cardholderId": 10532, "result": "pass" }'{
"status": "success",
"result": {}
}Example — force a decline
{ "cardholderId": 10532, "result": "fail" }{
"status": "success",
"result": {}
}After calling this endpoint, verify the outcome with GET /cardholders/{cardholderId} — status should have updated to 1 (pass) or 2 (fail).
What this replaces
In production, this state transition is triggered by a real cardholder completing the Didit/SumSub KYC flow and the compliance provider returning a result. In staging, you can use this endpoint to skip the manual KYC step entirely for automated test sequences — or to force a specific outcome (e.g., fail) that the emulation engine might not produce on a given run.
Simulate a crypto deposit
POST /staging/simulate-crypto-deposit
Triggers the full STP pipeline for a given deposit address — simulating an on-chain deposit, the confirmation accumulation, finality, and off-ramp conversion into the card's base currency. The balance updates (ledgerBalance → availableBalance) occur through the normal pipeline with realistic (emulated) timing.
| Field | Required | Type | Description |
|---|---|---|---|
address | Yes | string | A deposit address from the card's cryptoAddresses array |
tokenId | Yes | string | The token/asset identifier — e.g., a chain-specific USDT token ID, or a canonical identifier for the asset being simulated |
amount | Yes | string | Amount to simulate as a decimal string (e.g., "100.00") — not a decimal-implied integer |
Example
curl --cert staging-cert.pem --key staging-key.pem \
-H "X-API-Key: YOUR_STAGING_API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://staging.api.axyscards.com/v2/staging/simulate-crypto-deposit" \
-d '{
"address": "0x742d35Cc6634C0532925a3b8D4C9B7e...",
"tokenId": "usdt-eth",
"amount": "100.00"
}'{
"status": "success",
"message": "Deposit simulation initiated",
"txId": "sim_tx_8f3a92c1d"
}The txId is a simulated transaction identifier. After calling this endpoint:
- Poll
GET /cards/{cardId}/balance—ledgerBalancewill update first (simulating ≥10 confirmations), thenavailableBalancewill update after simulated finality and off-ramp. - The timing between steps is emulated (not instant) — your polling logic is being tested.
What this replaces
In production, a depositor sends digital assets on-chain and the platform detects them automatically. In staging, this endpoint simulates that on-chain event, allowing you to test your deposit-monitoring and balance-polling logic without needing to send real cryptocurrency.
Simulate a card spend
POST /staging/simulate-spend
Simulates an immediate card spend, reducing the card's balance and triggering the normal transaction recording and reconciliation flow. The resulting transaction will appear in GET /cards/transactions.
| Field | Required | Type | Description |
|---|---|---|---|
cardId | Yes | integer | The card to debit. Must be issuerCardStatus = 1 (Active). |
amount | Yes | string | Amount to debit as a decimal string, max 2 decimal places (e.g., "25.00") |
Example
curl --cert staging-cert.pem --key staging-key.pem \
-H "X-API-Key: YOUR_STAGING_API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://staging.api.axyscards.com/v2/staging/simulate-spend" \
-d '{ "cardId": 8821, "amount": "25.00" }'{
"status": "success",
"message": "Spend simulated"
}After calling this endpoint, verify with GET /cards/{cardId}/balance (balance reduced) and GET /cards/transactions?cardId={cardId} (transaction record created).
What this replaces
In production, a card spend is initiated by the cardholder at a merchant terminal or online checkout, routed through the card network, and authorized by the platform. In staging, this endpoint simulates that full authorization and settlement flow, allowing you to test your transaction-monitoring, reconciliation, and balance-check logic without needing a real merchant transaction.
Prepare a 3-DS OTP
POST /staging/prepare-spend-otp
Creates and stores a simulated OTP for a card that has an active OTP listener subscription. Returns the OTP code so you can test the full 3DS delivery-and-verification flow programmatically, including your webhook handler, GET /otp/{token} retrieval, and code delivery logic.
| Field | Required | Type | Description |
|---|---|---|---|
cardId | Yes | integer | The card whose active OTP listener will receive the simulated OTP. The card must have issuerCardStatus = 1 (Active) and an active subscription (via POST /otp/listeners). |
Example
curl --cert staging-cert.pem --key staging-key.pem \
-H "X-API-Key: YOUR_STAGING_API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://staging.api.axyscards.com/v2/staging/prepare-spend-otp" \
-d '{ "cardId": 8821 }'{
"status": "success",
"pin": "471928"
}The pin in the response is the OTP code that has been stored for this card's active listener. After calling this endpoint:
- Your webhook endpoint receives a callback with
{ "cardId": 8821 }(ifwebhookUrlwas configured on the subscription). - Call
GET /otp/{token}with the subscription token — the response will havestatus: "received"andcode: "471928". - Verify your code delivery logic handles the
codecorrectly before it expires.
What this replaces
In production, a 3DS OTP is generated when a cardholder initiates a card-not-present transaction and the card network triggers an authentication challenge. In staging, this endpoint simulates that trigger, allowing you to test the complete OTP subscription → callback → retrieval → delivery flow end-to-end without needing a real CNP transaction at a real merchant.
The full staged test sequence
Used together, these four endpoints let you run a complete integration test from zero to a fully exercised card — without any real KYC documents, cryptocurrency, merchants, or cardholders:
sequenceDiagram
participant You
participant API as Staging API
participant Sim as Emulation Engine
You->>API: POST /cardholders
API->>You: cardholderId = 10532
You->>API: PUT /cardholders/10532/kyc-submit
API->>You: applicationLink, status = 3
You->>API: POST /staging/kyc/validate (result=pass)
Sim->>Sim: Force cardholder → status=1
API->>You: status: success
You->>API: POST /cards/virtual/10532
API->>You: cardId = 8821, cryptoAddresses
You->>API: POST /staging/simulate-crypto-deposit
Sim->>Sim: Run STP pipeline with emulated timing
Note over You,Sim: Poll GET /cards/8821/balance<br/>until availableBalance > 0
You->>API: POST /otp/listeners (cardId=8821)
API->>You: subscription token
You->>API: POST /staging/prepare-spend-otp (cardId=8821)
Sim->>You: Webhook callback → cardId
You->>API: GET /otp/{token}
API->>You: code: "471928"
You->>API: POST /staging/simulate-spend (cardId=8821)
API->>You: status: success
You->>API: GET /cards/transactions?cardId=8821
API->>You: Transaction record present
See Testing Your Integration for the full test matrix and resilience scenarios that go beyond this happy-path sequence.
