curl --request POST \
--url https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"card_id": "1NFHrqBHb3cTfLVkFSGmHZqdDPi",
"amount": "2.00",
"merchant": {
"descriptor": "COFFEE ROASTERS",
"mcc": "5814",
"city": "BROOKLYN",
"state": "NY",
"country": "USA"
},
"type": "authorization"
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
card_id: '1NFHrqBHb3cTfLVkFSGmHZqdDPi',
amount: '2.00',
merchant: {
descriptor: 'COFFEE ROASTERS',
mcc: '5814',
city: 'BROOKLYN',
state: 'NY',
country: 'USA'
},
type: 'authorization'
})
};
fetch('https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction"
payload = {
"card_id": "1NFHrqBHb3cTfLVkFSGmHZqdDPi",
"amount": "2.00",
"merchant": {
"descriptor": "COFFEE ROASTERS",
"mcc": "5814",
"city": "BROOKLYN",
"state": "NY",
"country": "USA"
},
"type": "authorization"
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction"
payload := strings.NewReader("{\n \"card_id\": \"1NFHrqBHb3cTfLVkFSGmHZqdDPi\",\n \"amount\": \"2.00\",\n \"merchant\": {\n \"descriptor\": \"COFFEE ROASTERS\",\n \"mcc\": \"5814\",\n \"city\": \"BROOKLYN\",\n \"state\": \"NY\",\n \"country\": \"USA\"\n },\n \"type\": \"authorization\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"simulation_id": "sim_card_01J8ZQ4T7K2M9X",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"status": "completed"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "amount must be a positive decimal with at most two decimal places",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Endpoint only available in sandbox mode",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Card not found",
"status": 404,
"detail": "Card not found",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#card-not-active",
"title": "Card Not Active",
"status": 409,
"detail": "The card must be active to present a simulated transaction.",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#sandbox-amount-cap-exceeded",
"title": "Sandbox Amount Cap Exceeded",
"status": 422,
"detail": "amount 25 exceeds sandbox cap of 2; reduce the amount and retry",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#sandbox-card-simulation-daily-limit",
"title": "Sandbox Card Simulation Daily Limit",
"status": 429,
"detail": "This client has used its card-simulation allowance for the day. Retry within 24 hours.",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#internal-error",
"title": "Internal Error",
"status": 500,
"detail": "An internal error occurred",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-implemented",
"title": "Not Implemented",
"status": 501,
"detail": "card simulation is not available in this deployment yet",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#provider-error",
"title": "Provider Error",
"status": 502,
"detail": "provider sandbox service returned an error",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}Simulate a card authorization
Presents a card authorization to Dakota as if a merchant had swiped the
card. The authorization runs the production path: the authorization
service decides it, the hold lands on the wallet, and the
card_transaction.created webhook fires. Only the trigger is synthetic.
A decline is a normal outcome, not an HTTP error. The authorization
service declines the authorization as it would in production, for
example for a card with too little spendable balance. A declined
authorization creates a card transaction with status: declined and
a decline_reason, and fires card_transaction.created, the same as
an approval. The simulation completes and names the
card_transaction_id once the card transaction is visible
(status: pending until then); inspect the card transaction for the
reason. Repeating this call with the same X-Idempotency-Key returns
the same completed simulation.
A decline that could not be recorded as a card transaction (rare)
fails the simulation: poll GET /sandbox/simulations/{simulation_id}
and it reads state: rejected (state_position: failed), with
metadata.failure_reason carrying the network result, for example
declined:INSUFFICIENT_FUNDS.
Some merchant categories reserve more than the authorization amount, within the tolerances card networks allow. The excess is released when the transaction clears, or when the merchant updates the authorized amount.
- Fuel pumps (MCC 5542): an authorization below 175 USD reserves 175 USD, so the wallet needs at least 175 USD available.
- Restaurants and fast food (MCC 5812, 5814): 30% above the authorization. A 2 USD authorization at MCC 5814 holds 2.60 USD.
- Bars, taxis, beauty and barber shops and spas (MCC 5813, 4121, 7230, 7298): 20% above the authorization.
- Lodging (MCC 7011 and hotel chain codes 3501-3999): 15% above.
- Cruise lines (MCC 4411): 15% above.
- Car, truck and RV rental (MCC 7512, 7513, 7519 and chain codes 3351-3500): 15% or 75 USD above, whichever is greater.
Other categories hold the authorization amount. The wallet needs the
hold available, not just the purchase, and a per_transaction spend
limit is checked against the hold too. Partial approvals are not
returned yet, so a purchase whose hold exceeds the available balance
is declined.
In a default sandbox the simulated amount and the faucet are both capped at 2 USD per call, and the faucet at 5 calls per wallet per day, so fuel and vehicle rental need more than the faucet can provide and decline. Fund the wallet with two faucet calls before a 2 USD purchase at a restaurant (MCC 5812 or 5814), or in a category with no extra hold.
The card must belong to a customer of the authenticated client. Available in sandbox mode only.
curl --request POST \
--url https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"card_id": "1NFHrqBHb3cTfLVkFSGmHZqdDPi",
"amount": "2.00",
"merchant": {
"descriptor": "COFFEE ROASTERS",
"mcc": "5814",
"city": "BROOKLYN",
"state": "NY",
"country": "USA"
},
"type": "authorization"
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
card_id: '1NFHrqBHb3cTfLVkFSGmHZqdDPi',
amount: '2.00',
merchant: {
descriptor: 'COFFEE ROASTERS',
mcc: '5814',
city: 'BROOKLYN',
state: 'NY',
country: 'USA'
},
type: 'authorization'
})
};
fetch('https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction"
payload = {
"card_id": "1NFHrqBHb3cTfLVkFSGmHZqdDPi",
"amount": "2.00",
"merchant": {
"descriptor": "COFFEE ROASTERS",
"mcc": "5814",
"city": "BROOKLYN",
"state": "NY",
"country": "USA"
},
"type": "authorization"
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction"
payload := strings.NewReader("{\n \"card_id\": \"1NFHrqBHb3cTfLVkFSGmHZqdDPi\",\n \"amount\": \"2.00\",\n \"merchant\": {\n \"descriptor\": \"COFFEE ROASTERS\",\n \"mcc\": \"5814\",\n \"city\": \"BROOKLYN\",\n \"state\": \"NY\",\n \"country\": \"USA\"\n },\n \"type\": \"authorization\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"simulation_id": "sim_card_01J8ZQ4T7K2M9X",
"card_transaction_id": "2ZFHrqBHb3cTfLVkFSGmHZqdDPi",
"status": "completed"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#invalid-request",
"title": "Invalid request",
"status": 400,
"detail": "amount must be a positive decimal with at most two decimal places",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Endpoint only available in sandbox mode",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Card not found",
"status": 404,
"detail": "Card not found",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#card-not-active",
"title": "Card Not Active",
"status": 409,
"detail": "The card must be active to present a simulated transaction.",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#sandbox-amount-cap-exceeded",
"title": "Sandbox Amount Cap Exceeded",
"status": 422,
"detail": "amount 25 exceeds sandbox cap of 2; reduce the amount and retry",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#sandbox-card-simulation-daily-limit",
"title": "Sandbox Card Simulation Daily Limit",
"status": 429,
"detail": "This client has used its card-simulation allowance for the day. Retry within 24 hours.",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#internal-error",
"title": "Internal Error",
"status": 500,
"detail": "An internal error occurred",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-implemented",
"title": "Not Implemented",
"status": 501,
"detail": "card simulation is not available in this deployment yet",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#provider-error",
"title": "Provider Error",
"status": 502,
"detail": "provider sandbox service returned an error",
"instance": "https://api.platform.dakota.xyz/sandbox/cards/simulate/transaction",
"request_id": "req_01hzy6y7v8w9x0y1z2a3b4c5d6"
}Authorizations
Headers
Unique key (UUID) to ensure request idempotency on POST, PUT and PATCH requests.
A key is scoped to your client, the HTTP method and the path, and is remembered for 24 hours after a
successful (below 400) response. Repeating the same request (same JSON body, whatever the key order or
whitespace) with the same key within that window returns the original response with
X-Idempotent-Replayed: true instead of executing the request again. Using the same key on the same
endpoint with a different body returns 422 with problem type idempotency-key-reused; the request is
not executed. Error responses (4xx and 5xx) are not remembered, so a request refused for a fixable reason
can be corrected and retried under the same key. Request bodies that are not JSON (for example file
uploads) are not compared.
Body
A request to present a simulated authorization on a card.
KSUID is a 27-character globally unique ID that combines a timestamp with a random component. Used for all entity identifiers in the Dakota platform.
27^[0-9A-Za-z]{27}$"1NFHrqBHb3cTfLVkFSGmHZqdDPi"
Amount in decimal USD, at most two decimal places. Capped by the sandbox per-transaction limit.
Required for every type except balance_inquiry, which moves no
funds and so takes no amount: omit it, or send "0". A
balance_inquiry naming a non-zero amount is refused.
"2.00"
The merchant presenting a simulated card transaction.
Show child attributes
Show child attributes
Which network message the simulation opens. authorization is a
standard purchase; financial_authorization clears immediately;
balance_inquiry checks the spendable balance and moves no funds,
so it is the one type that takes no amount, and it creates no card
transaction: no card_transaction.* webhook fires, and the
simulation completes with no card_transaction_id. A declined one
answers pending and fails the simulation (state: rejected).
authorization, credit_authorization, financial_authorization, balance_inquiry "authorization"
Whether the merchant accepts a partial approval. Partial approvals are not returned yet: a purchase whose hold exceeds the available balance is declined either way.
Response
Card simulation accepted
An accepted card simulation.
Simulation identifier. Resolve it with
GET /sandbox/simulations/{simulation_id}.
"sim_card_01J8ZQ4T7K2M9X"
Where a card simulation stands. completed means the card transaction
exists and this response names it, or, for a balance_inquiry, that the
network approved the inquiry: an inquiry moves no funds and creates no
card transaction, so it completes with no card_transaction_id.
pending means the simulation was accepted and its outcome is not on
this response: the transaction has not been materialized yet, the
inquiry has not been answered yet, or the simulation was declined with
no card transaction to name. Poll
GET /sandbox/simulations/{simulation_id} for the identifier, for
state_position: completed, or for state: rejected. A declined card
authorization creates a card transaction with status: declined, so it
completes here and names it the same as an approval. A decline with no
card transaction answers pending here and fails the simulation, which
then reads state: rejected with the reason in
metadata.failure_reason: a declined balance_inquiry, or a decline
that could not be recorded as a card transaction (rare). failed means
the simulation was not accepted: a refusal the endpoint could classify
comes back as a problem response instead, so failed is what an
unclassified one looks like. It can still name a card transaction,
because the response reports whichever transaction the call resolved.
pending, completed, failed KSUID is a 27-character globally unique ID that combines a timestamp with a random component. Used for all entity identifiers in the Dakota platform.
27^[0-9A-Za-z]{27}$"1NFHrqBHb3cTfLVkFSGmHZqdDPi"
Was this page helpful?

