Skip to content

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

request
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": "[email protected]" },
  "card": { "fingerprint": "fp_9c1e4b7a2d", "bin": "457173", "last4": "4242" },
  "device": { "id": "dev_7f3a91" },
  "ip": "203.0.113.42",
  "billing_country": "DE"
}
response · full path with the Decision Core
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-Key and 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

response · terminal rule, no provider or Decision Core call
{
  "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
}
response · card number in payload
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.