The Verdikt API
A single REST endpoint returns a complete fraud decision in under 50ms. Send what you know about an order; get back a verdict, a calibrated risk score and the reasons behind it. Production base URL: https://verdiktt.com/api/v1
Introduction
The Verdikt API is organised around REST. It has predictable, resource-oriented URLs, accepts JSON request bodies, returns JSON responses, and uses standard HTTP verbs and status codes. Every request is scored in real time by our AI decisioning engine: a transaction foundation model, a graph network and risk models running in parallel.
/api/v1. Jump to the playground to send a real request and inspect the response.Authentication
Authenticate with your secret API key in the Authorization header as a bearer token. Keys are environment-scoped: test keys are prefixed vk_test_ and live keys vk_live_. Live keys are billable and eligible for the chargeback guarantee; test keys always run in sandbox. Never expose a live secret key in client-side code.
| Environment | Key prefix | Behaviour |
|---|---|---|
| Sandbox | vk_test_ | Deterministic scoring, no billing, no guarantee. |
| Production | vk_live_ | Full model, billed per decision, guarantee-eligible. |
Sandbox scoring is deterministic. Use the reserved emails [email protected], [email protected] and [email protected] to force each verdict while integrating.
Making requests
All requests must be made over HTTPS and send a JSON body with Content-Type: application/json. The API recognises these headers:
| Header | Purpose |
|---|---|
Authorization required | Bearer token with your secret API key. |
Content-Type required | Must be application/json for write calls. |
Idempotency-Key | Safely retry a decision without scoring it twice. |
Every response includes X-Request-Id, X-RateLimit-Limit and X-RateLimit-Remaining headers.
Idempotency
To safely retry requests without accidentally scoring the same order twice, pass a unique Idempotency-Key header (your order_id is a good choice). The first request is processed and the result stored against the key; subsequent requests with the same key return the original decision without re-scoring. Keys are retained for 24 hours.
The Decision object
A decision represents a single risk evaluation. These are the fields it returns:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier, prefixed dec_. |
verdict | string | One of approve, review, decline. |
score | number | Calibrated fraud probability from 0.00 to 1.00. |
guaranteed | boolean | Whether the order is covered by the chargeback guarantee. |
reasons | array | Human-readable signal codes driving the verdict. |
latency_ms | number | Server-side decisioning time in milliseconds. |
livemode | boolean | true for live keys, false in sandbox. |
created | number | Unix timestamp of creation. |
Create a decision
Submit a transaction and receive a real-time verdict. Request body fields:
| Field | Type | Description |
|---|---|---|
order_id required | string | Your unique identifier for the order. |
amount required | number | Order total in major units (e.g. 249.00). |
currency required | string | ISO 4217 currency code, e.g. USD. |
customer required | object | email, ip, device_id, phone. |
product_type | string | digital_goods, marketplace, physical, subscription. |
payment | object | Tokenised instrument: bin, last4, method. |
session | object | Behavioural signals from the Verdikt.js browser SDK. |
metadata | object | Any key-value pairs echoed back on webhooks. |
Request
curl https://verdiktt.com/api/v1/decisions \
-H "Authorization: Bearer vk_live_4f9c20a1d8e3" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ord_8842" \
-d '{
"order_id": "ord_8842",
"amount": 249.00,
"currency": "USD",
"product_type": "physical",
"customer": {
"email": "[email protected]",
"ip": "81.2.69.142",
"device_id": "dvc_a91f"
}
}'Response
{
"id": "dec_9f3a21c7c4e0",
"object": "decision",
"created": 1781827200,
"livemode": true,
"order_id": "ord_8842",
"amount": 249.0,
"currency": "USD",
"product_type": "physical",
"verdict": "approve",
"score": 0.07,
"guaranteed": true,
"reasons": [
"email_reputation_ok",
"established_device",
"shipping_billing_match",
"graph_no_fraud_link"
],
"latency_ms": 43
}Retrieve a decision
Fetch a previously created decision by its id.
curl https://verdiktt.com/api/v1/decisions/dec_9f3a21c7c4e0 \ -H "Authorization: Bearer vk_live_4f9c20a1d8e3"
List decisions
Returns a list of decisions, most recent first. Accepts an optional limit query parameter (default 10, max 100).
curl "https://verdiktt.com/api/v1/decisions?limit=10" \ -H "Authorization: Bearer vk_live_4f9c20a1d8e3"
Response
{
"object": "list",
"url": "/v1/decisions",
"has_more": false,
"data": [
{ "id": "dec_9f3a21c7c4e0", "verdict": "approve", "score": 0.07, "...": "..." },
{ "id": "dec_61b0a4e2f199", "verdict": "review", "score": 0.54, "...": "..." }
]
}Live playground
Send a real request to the sandbox engine running in this environment. Edit the body or pick a preset, then send. Try the reserved test emails to force each verdict, or a disposable-email domain to watch the score climb.
// Click “Send request” to score this transaction // against the live sandbox engine.
Verdicts & scores
The score is a calibrated fraud probability. The verdict applies your configured thresholds (defaults shown):
| Verdict | Default range | Suggested action |
|---|---|---|
approve | score < 0.35 | Fulfil immediately. Guarantee-eligible. |
review | 0.35 to 0.70 | Hold for manual review or step-up auth. |
decline | score ≥ 0.70 | Block the order. |
Errors
Verdikt uses conventional HTTP status codes and returns a machine-readable error object.
| Status | Meaning |
|---|---|
200 | Decision returned successfully. |
400 | Invalid or missing request parameters. |
401 | Missing or invalid API key. |
404 | Resource not found. |
429 | Rate limit exceeded; back off and retry. |
503 | Decisioning temporarily unavailable. |
{
"error": {
"type": "invalid_request_error",
"message": "customer.email is required.",
"fields": ["customer.email is required."]
}
}Rate limits
Production accounts are limited to 1,000 req/s by default, burstable on request. When you exceed the limit the API returns 429. Inspect X-RateLimit-Remaining and implement exponential backoff. Decisioning calls are designed to fail fast, so a safe default is to fail open (approve) or closed (review) per your risk appetite if a call times out.
Webhooks
Verdikt sends signed webhook events when an asynchronous outcome occurs: a held order resolves, a guarantee is confirmed, or a chargeback is reported by the network. Verify the Verdikt-Signature header against your endpoint secret.
| Event | Fires when |
|---|---|
decision.updated | A review order is resolved. |
guarantee.confirmed | An approved order is covered by the guarantee. |
chargeback.received | The network reports a chargeback. |
chargeback.reimbursed | A guaranteed loss is reimbursed to you. |
{
"id": "evt_2c8f10a4",
"type": "chargeback.received",
"created": 1781913600,
"data": {
"decision_id": "dec_9f3a21c7c4e0",
"order_id": "ord_8842",
"amount": 249.0,
"currency": "USD",
"reason_code": "10.4",
"guaranteed": true
}
}Libraries
Official, typed SDKs wrap the REST API for every major stack:
| Language | Install |
|---|---|
| Node / TypeScript | npm install @verdikt/node |
| Python | pip install verdikt |
| Ruby | gem install verdikt |
| Go | go get github.com/verdikt/verdikt-go |
| PHP | composer require verdikt/verdikt-php |