---
title: "Get OZAV's verdict on a risk question"
method: POST
path: "/decisions"
tags: ["Decisions"]
---

# Get OZAV's verdict on a risk question

`POST /decisions`

## Request

- Base URL: `https://developers.ozav.io/v2`
- URL: `https://developers.ozav.io/v2/decisions`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Runs OZAV's own engines on the input and returns the verdict with its reasons and checks.
The verdict is recorded (your input is not) so you can read it back and report its outcome.

Missing or stale data is `REVIEW`, never `ALLOW`. If an engine cannot answer at all, the
call returns `503 DECISION_UNAVAILABLE`, nothing is recorded and nothing is charged.

Send an `Idempotency-Key` to retry safely: the same key and body return the same decision
and are not charged again; the same key with a different body answers `409`.

Requires the `decisions:write` scope. API keys created before this scope existed do not
gain it: create a new key with the scopes you need.

## Headers

- `PAYMENT-SIGNATURE` string
- `X-Ozav-Simulate-Payment` 'required'
- `Idempotency-Key` string

## Request body

- union: What to decide. `type` selects the shape of `input`.
  - object
    - `type` 'name.match', required: Is this name on a sanctions list?
    - `input` object, required
      - `name` string, required: Full name of the person or business.
      - `date_of_birth` string, date: YYYY-MM-DD. Without it a full-name match is `REVIEW`, never `DENY`.
  - object
    - `type` 'destination.ownership', required: Is this destination the customer's own?
    - `input` object, required
      - `rail` string, required: The payout rail, e.g. `pix`. The same-owner rule applies to Pix only.
      - `destination_tax_id` string, required: CPF/CNPJ of the destination account holder.
      - `customer_tax_id` string, required: CPF/CNPJ of your customer.
  - object
    - `type` 'wallet.risk', required: Is this address on a sanctions list?
    - `input` object, required
      - `address` string, required: The wallet address.
      - `chain` string: Optional network label, recorded as given.
  - object
    - `type` 'transaction.outbound', required: One outgoing payment: the other party, wallet and ownership together.
    - `input` object, required
      - `amount_usd` number: Optional. Recorded for context; the verdict does not depend on it.
      - `counterparty` object
        - `name` string, required: Full name of the other party to the payment.
        - `date_of_birth` string, date: YYYY-MM-DD.
      - `destination` object, required
        - `wallet_address` string: Destination wallet address.
        - `rail` string: Payout rail. `rail`, `destination_tax_id` and `customer_tax_id` go together: with them, ownership is checked.
        - `destination_tax_id` string: CPF/CNPJ of the destination account holder.
        - `customer_tax_id` string: CPF/CNPJ of your customer.

## Response `201`

The verdict.

- Decision
  - `id` string, required: The decision id (`ozav_dec_...`).
  - `object` 'decision', required: Always the literal `decision`.
  - `type` 'name.match' | 'destination.ownership' | 'wallet.risk' | 'transaction.outbound', required: The decision type requested.
  - `effect` 'ALLOW' | 'REVIEW' | 'DENY', required: `ALLOW`, `REVIEW` (a person should look) or `DENY` (OZAV holds the proof of the risk).
  - `reasons` object[], required: Why. When `effect` is not `ALLOW`, only the reasons that caused it.
    - `code` string, required: Stable machine code, e.g. `NAME_MATCHES_SANCTIONS_LIST`.
    - `message` string, required: A human-readable sentence.
  - `checks` object[], required: Each check that ran and what it found.
    - `check` string, required: `sanctions_list`, `designated_addresses` or `destination_ownership`.
    - `result` string, required: What the check found.
  - `policy_version` string, required: The version of OZAV's rules that produced the verdict.
  - `outcome` 'confirmed_risk' | 'false_positive' | 'completed' | 'reversed' | 'chargeback' | 'null', nullable, required: The outcome you reported, or `null`.
  - `outcome_at` string, date-time, nullable, required: When the outcome was reported.
  - `created_at` string, date-time, required: When the decision was made.

## Other responses

- `202`: Accepted - a concurrent request with the same `Idempotency-Key` is still executing; the body is `{"status": "processing"}`. Retry with the same key once the original completes: a completed request replays its stored response verbatim with the original status code and the `Idempotent-Replayed: true` header. This is not the resource - check the status code before deserializing. If this `202` repeats instead of resolving, the original request's outcome is unknown and no stored result will arrive - the key stays claimed when a request fails after the resource may already have been written. Stop retrying, reconcile with a `GET` to see whether the resource exists, and use a new key if it does not.
- `400`: The request is invalid.
- `401`: Missing or invalid API key.
- `402`: OZAV Services only (prepaid): your prepaid credit does not cover this call (code INSUFFICIENT_CREDIT). The call did not run and nothing was charged. `details` carries `balance_usd` and `price_usd`; top up in the portal (Billing) and retry. Organizations on the OZAV platform are invoiced monthly and never receive this. On `POST /decisions` and `POST /screenings`, where OZAV accepts x402 payment, the response also carries an x402 v2 challenge: the `PAYMENT-REQUIRED` header (base64 `PaymentRequired`) and the same object in `details.x402` - the price of this one call in native USDC, paid to OZAV. `accepts` lists one entry per network OZAV receives on, Polygon (`eip155:137`) first; where enabled, a second entry offers Base (`eip155:8453`). Pay on any one of them, signing for that network's USDC (the entry's `asset`); a payment whose `accepted.asset` is not the USDC of its `network` is refused with `network_or_asset_not_accepted`. Retry with the `PAYMENT-SIGNATURE` header to pay it. A payment OZAV does not accept answers `402 X402_PAYMENT_REJECTED` with `details.reason` (`amount_below_price`, `wrong_pay_to`, `network_or_asset_not_accepted`, `authorization_not_yet_valid`, `authorization_expires_too_soon`, `authorization_window_too_long`, `signature_invalid`, `authorization_already_used`, `insufficient_balance`, `settlement_refused`, `payment_malformed` or `payment_not_accepted`) and a new challenge; nothing was charged. If OZAV could not confirm the settlement, `503 X402_PAYMENT_UNAVAILABLE`: retry with the same header, it is never charged twice. A retried payment is credited only once OZAV reads, on-chain, the transaction that used the authorization moving the USDC to OZAV; when that cannot be established automatically, the `503` says the payment needs a manual check (contact support with the request id). Where OZAV also accepts MPP, the response carries an MPP challenge in `WWW-Authenticate: Payment` (method `evm`, intent `charge`, credential type `authorization`, valid for five minutes) and in `details.mpp.www_authenticate`. A credential OZAV does not accept answers `402 MPP_PAYMENT_REJECTED` with `details.reason` (the reasons above, plus `challenge_not_issued_by_ozav`, `challenge_expired` and `nonce_not_bound_to_challenge`); `503 MPP_PAYMENT_UNAVAILABLE` means retry with the same credential.
- `403`: The organization lacks the entitlement (code ENTITLEMENT_REQUIRED) or the key lacks the scope (code INSUFFICIENT_SCOPE). On money-moving requests (POST /transfers, POST /wallets/{wallet_id}/transfers) a compliance hold on the customer answers with code COMPLIANCE_HOLD: the hold is reviewed and lifted on OZAV's side; retrying does not clear it. When the only hold is a pause until pending onboarding documents are received, a withdrawal answers CUSTOMER_DOCUMENTS_PENDING instead: send what `requirements` on GET /customers/{id} lists; OZAV lifts the pause after reviewing it. On OZAV Services (live without the platform's KYB), any API outside decisions, screenings, lists and self-custody wallets answers with code PRODUCTION_NOT_ACTIVATED.
- `409`: Conflict (e.g. IDEMPOTENCY_KEY_REUSED).
- `503`: A dependency OZAV needs (storage, a resource lookup) could not be reached, so OZAV fails closed rather than guess. Safe to retry with the same `Idempotency-Key` where the operation accepts one.

---

[API](https://skmtc.dev/ozav/apis/ozav-api.md) - [All operations](https://skmtc.dev/ozav/apis/ozav-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ozav/apis/ozav-api/revisions/4133dc2109d7?raw)
