Skip to content

Start a backtest

POST
/v1/backtest
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.

Idempotency-Key
string
/^[A-Za-z0-9._:\-]{1,128}$/

Makes retries safe. Reusing a key for a different request returns 409 idempotency_key_reused.

policy_version_id
string
/^plv_[0-9a-f]{32}$/

CSV uploads only.

policy_id
string
/^pol_[0-9a-f]{32}$/

CSV uploads only.

version
integer
>= 1

CSV uploads only; with policy_id.

product
string
/^[a-z0-9_]{1,40}$/

CSV uploads only.

notify_emails
string

CSV uploads only. Comma-separated; see notify_emails in the JSON body.

object
policy_version_id
string
/^plv_[0-9a-f]{32}$/
policy_id
string
/^pol_[0-9a-f]{32}$/
version

With policy_id; default latest.

integer
>= 1
product
string
/^[a-z0-9_]{1,40}$/
notify_emails

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.

Array<string>
<= 10 items
transactions
required
Array
>= 1 items <= 50000 items

A score request plus an optional label; policy_version_id and product are set for the whole backtest.

object
transaction
required
object
id
required

Your transaction ID; also the idempotency key.

string
/^[A-Za-z0-9._:\-]{1,128}$/
type
required
string
Allowed values: loan_application loan_disbursement repayment transfer withdrawal deposit card_payment bill_payment other
amount
required

Minor units (kobo for NGN).

integer
currency
required

Must match the policy’s market (NGN).

string
/^[A-Z]{3}$/
occurred_at
required

Not more than 5 minutes in the future.

string format: date-time
channel
string
/^[A-Za-z0-9 ._\-]{1,64}$/
customer
required
object
id_hash
required

HMAC-SHA256 of the identifier under your identifier key, lowercase hex.

string
/^[0-9a-f]{64}$/
bvn_hash

HMAC-SHA256 of the identifier under your identifier key, lowercase hex.

string
/^[0-9a-f]{64}$/
phone_hash

HMAC-SHA256 of the identifier under your identifier key, lowercase hex.

string
/^[0-9a-f]{64}$/
device
object
id_hash
required

HMAC-SHA256 of the identifier under your identifier key, lowercase hex.

string
/^[0-9a-f]{64}$/
platform
string
/^[A-Za-z0-9 ._\-]{1,64}$/
beneficiary
object
account_hash
required

HMAC-SHA256 of the identifier under your identifier key, lowercase hex.

string
/^[0-9a-f]{64}$/
bank_code
string
/^[A-Za-z0-9 ._\-]{1,64}$/
location
object
country
string
/^[A-Z]{2}$/
region
string
/^[A-Za-z0-9 ._\-]{1,64}$/
product
string
/^[a-z0-9_]{1,40}$/
policy_version_id

Test mode only. Score against this exact version.

string
/^plv_[0-9a-f]{32}$/
label
string
Allowed values: fraud legitimate suspected

Replayed (same Idempotency-Key and request)

Media typeapplication/json
object
backtest_id
required
string
/^bt_[0-9a-f]{32}$/
status
required
string
Allowed values: queued running completed failed cancelled
policy
required
object
id
required
string
/^pol_[0-9a-f]{32}$/
version
required
integer
version_id
required
string
/^plv_[0-9a-f]{32}$/
config_sha256
string
engine_version
string
dataset
required
object
format
string
Allowed values: json csv
sha256
string
row_count
integer
invalid_row_count
integer
summary
required
One of:
object
scored
integer
by_risk_level
object
key
additional properties
integer
by_action
object
key
additional properties
integer
score_histogram
Array<object>
object
from
integer
to
integer
count
integer
mean_score
number
mean_confidence
number
rule_hits
object
key
additional properties
integer
labels
One of:
null
error
required
string | null
environment
required
string
Allowed values: live test
notify_emails
Array<string>
notified_at
string | null format: date-time
created_at
required
string format: date-time
started_at
string | null format: date-time
completed_at
string | null format: date-time

Example

{
"status": "queued",
"dataset": {
"format": "json"
},
"summary": {
"labels": {
"thresholds": [
{
"level": "low"
}
]
}
},
"environment": "live"
}
Idempotent-Replayed
string
Allowed values: true

Present (true) when an earlier result was returned.

Queued

Media typeapplication/json
object
backtest_id
required
string
/^bt_[0-9a-f]{32}$/
status
required
string
Allowed values: queued running completed failed cancelled
policy
required
object
id
required
string
/^pol_[0-9a-f]{32}$/
version
required
integer
version_id
required
string
/^plv_[0-9a-f]{32}$/
config_sha256
string
engine_version
string
dataset
required
object
format
string
Allowed values: json csv
sha256
string
row_count
integer
invalid_row_count
integer
summary
required
One of:
object
scored
integer
by_risk_level
object
key
additional properties
integer
by_action
object
key
additional properties
integer
score_histogram
Array<object>
object
from
integer
to
integer
count
integer
mean_score
number
mean_confidence
number
rule_hits
object
key
additional properties
integer
labels
One of:
null
error
required
string | null
environment
required
string
Allowed values: live test
notify_emails
Array<string>
notified_at
string | null format: date-time
created_at
required
string format: date-time
started_at
string | null format: date-time
completed_at
string | null format: date-time

Example

{
"status": "queued",
"dataset": {
"format": "json"
},
"summary": {
"labels": {
"thresholds": [
{
"level": "low"
}
]
}
},
"environment": "live"
}

Malformed request (invalid_request), including unknown fields.

Media typeapplication/json
object
error_code
required

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

string
message
required
string
retryable
required
boolean
request_id
string
details
One of:
Array<object>
object
field
required
string
message
required
string
code
string

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.

Media typeapplication/json
object
error_code
required

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

string
message
required
string
retryable
required
boolean
request_id
string
details
One of:
Array<object>
object
field
required
string
message
required
string
code
string

Example generated

{
"error_code": "example",
"message": "example",
"retryable": true,
"request_id": "example",
"details": {}
}

More than 50,000 rows or 25 MB (backtest_too_large)

Media typeapplication/json
object
error_code
required

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

string
message
required
string
retryable
required
boolean
request_id
string
details
One of:
Array<object>
object
field
required
string
message
required
string
code
string

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.

Media typeapplication/json
object
error_code
required

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

string
message
required
string
retryable
required
boolean
request_id
string
details
One of:
Array<object>
object
field
required
string
message
required
string
code
string

Example generated

{
"error_code": "example",
"message": "example",
"retryable": true,
"request_id": "example",
"details": {}
}