Start a backtest
const url = 'https://api-staging.asqary.com/v1/backtest';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"policy_version_id":"example","policy_id":"example","version":1,"product":"example","notify_emails":["hello@example.com"],"transactions":[{"transaction":{"id":"example","type":"loan_application","amount":1,"currency":"example","occurred_at":"2026-04-15T12:00:00Z","channel":"example"},"customer":{"id_hash":"example","bvn_hash":"example","phone_hash":"example"},"device":{"id_hash":"example","platform":"example"},"beneficiary":{"account_hash":"example","bank_code":"example"},"location":{"country":"example","region":"example"},"product":"example","policy_version_id":"example","label":"fraud"}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api-staging.asqary.com/v1/backtest \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "policy_version_id": "example", "policy_id": "example", "version": 1, "product": "example", "notify_emails": [ "hello@example.com" ], "transactions": [ { "transaction": { "id": "example", "type": "loan_application", "amount": 1, "currency": "example", "occurred_at": "2026-04-15T12:00:00Z", "channel": "example" }, "customer": { "id_hash": "example", "bvn_hash": "example", "phone_hash": "example" }, "device": { "id_hash": "example", "platform": "example" }, "beneficiary": { "account_hash": "example", "bank_code": "example" }, "location": { "country": "example", "region": "example" }, "product": "example", "policy_version_id": "example", "label": "fraud" } ] }'Evaluates historical transactions against a policy version pinned at
submission. At most 50,000 rows and 25 MB. JSON body, or text/csv with
the target in query parameters. Requires backtest:write.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Makes retries safe. Reusing a key for a different request returns 409 idempotency_key_reused.
Query Parameters
Section titled “Query Parameters”CSV uploads only.
CSV uploads only.
CSV uploads only; with policy_id.
CSV uploads only.
CSV uploads only. Comma-separated; see notify_emails in the JSON body.
Request Bodyrequired
Section titled “Request Bodyrequired”object
With policy_id; default latest.
Emailed when the backtest finishes (status, summary and a dashboard link; no transaction data). Each address must belong to a member of your organisation. Dashboard submissions default to the submitting user; send an empty array to opt out.
A score request plus an optional label; policy_version_id and product are set for the whole backtest.
object
object
Your transaction ID; also the idempotency key.
Minor units (kobo for NGN).
Must match the policy’s market (NGN).
Not more than 5 minutes in the future.
object
HMAC-SHA256 of the identifier under your identifier key, lowercase hex.
HMAC-SHA256 of the identifier under your identifier key, lowercase hex.
HMAC-SHA256 of the identifier under your identifier key, lowercase hex.
object
HMAC-SHA256 of the identifier under your identifier key, lowercase hex.
object
HMAC-SHA256 of the identifier under your identifier key, lowercase hex.
object
Test mode only. Score against this exact version.
Header row with columns from: transaction_id, type, amount, currency, occurred_at, channel, customer_id_hash, device_id_hash, device_platform, beneficiary_account_hash, beneficiary_bank_code, country, region, label. The first six are required.
Responses
Section titled “Responses”Replayed (same Idempotency-Key and request)
object
object
object
object
object
object
object
object
Example
{ "status": "queued", "dataset": { "format": "json" }, "summary": { "labels": { "thresholds": [ { "level": "low" } ] } }, "environment": "live"}Headers
Section titled “Headers”Present (true) when an earlier result was returned.
Queued
object
object
object
object
object
object
object
object
Example
{ "status": "queued", "dataset": { "format": "json" }, "summary": { "labels": { "thresholds": [ { "level": "low" } ] } }, "environment": "live"}Malformed request (invalid_request), including unknown fields.
object
Invalid_request, unauthorized, key_expired, key_revoked, forbidden, ip_not_allowed, quota_exceeded, not_found, method_not_allowed, conflict, policy_in_use, policy_active, policy_archived, idempotency_key_reused, validation_failed, rule_not_available, backtest_invalid_rows, backtest_too_large, rate_limited, internal_error
object
object
Example generated
{ "error_code": "example", "message": "example", "retryable": true, "request_id": "example", "details": {}}Lifecycle conflict (e.g. policy_in_use, policy_active) or idempotency_key_reused.
object
Invalid_request, unauthorized, key_expired, key_revoked, forbidden, ip_not_allowed, quota_exceeded, not_found, method_not_allowed, conflict, policy_in_use, policy_active, policy_archived, idempotency_key_reused, validation_failed, rule_not_available, backtest_invalid_rows, backtest_too_large, rate_limited, internal_error
object
object
Example generated
{ "error_code": "example", "message": "example", "retryable": true, "request_id": "example", "details": {}}More than 50,000 rows or 25 MB (backtest_too_large)
object
Invalid_request, unauthorized, key_expired, key_revoked, forbidden, ip_not_allowed, quota_exceeded, not_found, method_not_allowed, conflict, policy_in_use, policy_active, policy_archived, idempotency_key_reused, validation_failed, rule_not_available, backtest_invalid_rows, backtest_too_large, rate_limited, internal_error
object
object
Example generated
{ "error_code": "example", "message": "example", "retryable": true, "request_id": "example", "details": {}}validation_failed (details: field errors), rule_not_available, or backtest_invalid_rows.
object
Invalid_request, unauthorized, key_expired, key_revoked, forbidden, ip_not_allowed, quota_exceeded, not_found, method_not_allowed, conflict, policy_in_use, policy_active, policy_archived, idempotency_key_reused, validation_failed, rule_not_available, backtest_invalid_rows, backtest_too_large, rate_limited, internal_error
object
object
Example generated
{ "error_code": "example", "message": "example", "retryable": true, "request_id": "example", "details": {}}