---
title: "Verify before pay (protocol payload)"
method: POST
path: "/v1/verify/before-pay"
tags: ["Verify"]
---

# Verify before pay (protocol payload)

`POST /v1/verify/before-pay`

## Request

- Base URL: `https://api.farofinance.app`
- URL: `https://api.farofinance.app/v1/verify/before-pay`
- Auth: HTTP bearer

Verify-before-pay for agent-payment protocols, taking the **raw protocol payload**: an x402 `402 Payment Required` challenge body, an AP2 CartMandate/PaymentMandate, or an ACP merchant + checkout context. Faro extracts the counterparty (merchant → payee check, endpoint/site → URL check, receiving address → payee + on-chain screening), verifies each in parallel, and returns the riskiest verdict. A payload Faro cannot parse degrades to 🟡/`review` — never an error, never a false 🟢. Advisory only: Faro does not settle, authorize, or move funds.

## Request body

- VerifyBeforePayIn: Body for `POST /v1/verify/before-pay` — the raw protocol payload path. Send the protocol payload as-is (an x402 402 challenge body, an AP2 Cart/Payment mandate, or an ACP checkout context); Faro's adapter extracts the counterparty artifacts. Prefer this over `/v1/verify/payment-intent` when you hold the actual protocol object — no field-mapping on your side.
  - `protocol` 'ap2' | 'x402' | 'acp', required
  - `payload` object, required: The protocol object itself: the 402 challenge JSON (x402), the CartMandate/PaymentMandate (AP2), or the merchant + checkout context (ACP).
  - `region` string, nullable: Optional ISO 3166-1 alpha-2 region hint (e.g. `IN`, `US`) used only to interpret a *bare* phone number that has no country code. Labelling context only — it never changes the reputation node, sanctions, or the verdict. A number written in full `+<country code>` form is identified regardless.

## Response `200`

The verdict for the artifact.

- VerdictResult: The single verdict object returned by every verify endpoint and SDK method.
  - `verdict` 'green' | 'yellow' | 'red', required
  - `confidence` number, required: Calibrated confidence in the verdict (honest about data completeness).
  - `artifact` Artifact, required
    - `type` 'url' | 'payee' | 'message' | 'document', required
    - `value` string, required: The normalized artifact string that was checked.
  - `reason` string, required: One plain-language line explaining the verdict — always present.
  - `recommended_action` 'allow' | 'warn' | 'block' | 'review', required
  - `signals` Signal[]: Evidence behind the verdict — deterministic checks, enrichment, reputation.
    - `name` string, required: Machine-readable signal id, e.g. `domain_age_days`.
    - `severity` 'info' | 'low' | 'medium' | 'high' | 'critical', required
    - `detail` string, required: Human-readable explanation of what was found.
    - `source` string, required: Integration that produced the signal, e.g. `safe_browsing`.
  - `explanation` string, nullable: Optional longer context (e.g. session repeat-check notes).
  - `request_id` string, required: Unique id for this request (also in the `X-Request-ID` response header).
  - `cached` boolean: True when served from the verdict cache (`X-Faro-Cache: hit`).
  - `first_seen` string, date-time, nullable: When Faro first saw this normalized node in the reputation graph.
  - `checked_at` string, date-time, nullable: When this verdict was computed.

## Other responses

- `401`: Missing or invalid API key.
- `422`: Request body failed validation.
- `429`: Rate limit exceeded — slow down.

---

[API](https://skmtc.dev/farofinance/apis/faro.md) · [All operations](https://skmtc.dev/farofinance/apis/faro/llms.txt) · [OpenAPI document](https://skmtc.dev/farofinance/apis/faro/revisions/205cdf54420b?raw)
