Developers
One call to score an event.
Send a payment, sign-up, login, account update or payout to POST /v1/score and get a decision back synchronously. Examples are illustrative; the OpenAPI contract is authoritative.
Request
Score a payment
POST /v1/score HTTP/1.1
Host: api.frape.io
Authorization: Bearer frp_test_<prefix>_<secret>
Content-Type: application/json
Idempotency-Key: checkout-81723-attempt-1
{
"type": "payment",
"external_id": "order_81723",
"occurred_at": "2026-10-01T12:04:31Z",
"amount": 12999,
"currency": "EUR",
"account": { "id": "acct_4821", "email": "jane@example.com" },
"card": { "fingerprint": "fp_9c1e4b7a2d", "bin": "457173", "last4": "4242" },
"device": { "id": "dev_7f3a91" },
"ip": "203.0.113.42",
"billing_country": "DE"
}HTTP/1.1 200 OK
Content-Type: application/json
{
"event_id": "0199a1f2-7c3b-7d41-9a2e-5f0c8b1d3e47",
"decision": "CHALLENGE",
"score": 58,
"risk_level": "medium",
"reasons": ["new_device_for_account", "ip_country_mismatch"],
"matched_rules": ["sig_new_device", "sig_geo_mismatch"],
"model_called": true,
"model_skip_reason": null,
"policy_version": "pol_2026_09_28_3",
"latency_ms": 212
}- Amounts are integer minor units with an ISO-4217 currency.
- Cards are sent as fingerprint, BIN and last four only. Card numbers and CVVs are rejected.
- Retrying with the same
Idempotency-Keyand body within 24 hours replays the original response.
Response
What comes back
- event_id
- UUIDv7 of the stored event; use it with GET /v1/events/{id} and POST /v1/feedback.
- decision
- APPROVE, CHALLENGE, REVIEW or DECLINE — always produced by the deterministic policy.
- score
- 0–100 risk score.
- risk_level
- Banded risk level for display.
- reasons[]
- Stable reason codes you can show to analysts or map to customer messaging.
- matched_rules[]
- Rule identifiers that fired, for audit and tuning.
- model_called
- Whether the Decision Core was consulted for this event.
- model_skip_reason
- Why the Decision Core was not consulted (for example terminal_rule or confident_without_model), otherwise null.
- policy_version
- Version of the policy that made the decision.
- latency_ms
- Server-side processing time.
Examples
Short-circuits and errors
{
"event_id": "0199a1f2-80d4-7e19-b6a0-2c7d9e5f1a08",
"decision": "DECLINE",
"score": 100,
"risk_level": "critical",
"reasons": ["blocklisted_card_fingerprint"],
"matched_rules": ["hard_blocklist_card"],
"model_called": false,
"model_skip_reason": "terminal_rule",
"policy_version": "pol_2026_09_28_3",
"latency_ms": 9
}HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://docs.frape.io/errors/forbidden_field",
"title": "Forbidden field",
"status": 400,
"code": "forbidden_field",
"errors": [{ "field": "card.number", "message": "card numbers are never accepted" }]
}Design partners
Help shape what FRAPE decides next.
We are working with a small number of teams who score payments, sign-ups, logins or payouts and want decisions they can explain line by line. Bring your rules and your edge cases.