Integrate PayeeProof in 5–10 minutes.
One endpoint. One API key. One clear answer before funds move. This page is intentionally small: one quickstart request, two working code examples, and three sample responses. The primary operator outcomes are SAFE, BLOCK, REVERIFY, and TEST FIRST; UNAVAILABLE is a retry or manual-review state, not a green light.
POST /api/preflight-check Request: - expected.network - expected.asset - expected.address - provided.network - provided.asset - provided.address Response: - SAFE - BLOCK - TEST FIRST - REVERIFY - UNAVAILABLE
Use the approved route as expected and the submitted route as provided.
Required fields
Fast mental model
Start with cURL.
curl -X POST "https://payeeproof-api.onrender.com/api/preflight-check" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"expected": {
"network": "ethereum",
"asset": "USDC",
"address": "0x59d779BED4dB1E734D3fDa3172d45bc3063eCD69",
"memo": null
},
"provided": {
"network": "ethereum",
"asset": "USDC",
"address": "0x59d779BED4dB1E734D3fDa3172d45bc3063eCD69",
"memo": null
},
"context": {
"reference_id": "payout_102948",
"flow_type": "payout_approval",
"policy_profile": "payout_strict"
}
}'
trace_id, record_id, and checked_at change on every call.Use a ready file, not guesswork.
No dependency version for Node 18+
Uses built-in fetch, reads PAYEEPROOF_API_KEY from env, prints verdict + reason + next step.
Simple requests example
Reads PAYEEPROOF_API_KEY from env, sends one request, prints a compact summary, and exits with error details if the call fails.
These three shapes are enough for a practical first integration.
Route may be valid, but it behaves like infrastructure or an app rather than a plain wallet.
SAFE response
{
"ok": true,
"service": "preflight-check",
"version": "2.x",
"trace_id": "req_example_safe_01",
"checked_at": "2026-03-31T10:12:08Z",
"chain": "ethereum",
"policy_profile": "payout_strict",
"status": "verified",
"verdict": "SAFE",
"reason_code": "OK",
"next_action": "SAFE_TO_PROCEED",
"next_action_label": "Proceed with the payment",
"confidence": "High",
"summary": "Core details match and the destination looks like a personal wallet.",
"why_this_verdict": "Network, asset, address, and memo or tag checks matched cleanly, and the destination looks like a normal wallet rather than infrastructure.",
"risk_flags": [],
"checks": {
"network_match": true,
"asset_match": true,
"address_match": true,
"memo_match": true,
"expected_address_valid": true,
"provided_address_valid": true,
"expected_network_supported": true,
"provided_network_supported": true,
"expected_asset_supported": true,
"provided_asset_supported": true
},
"proof": {
"checked_at": "2026-03-31T10:12:08Z",
"chain": "ethereum",
"trace_id": "req_example_safe_01",
"verdict": "SAFE",
"confidence": "High",
"reason_code": "OK",
"next_action": "SAFE_TO_PROCEED",
"next_action_label": "Proceed with the payment",
"policy_profile": "payout_strict"
},
"record_id": "ppf_demo_safe_01",
"history_url": "/api/verification-records/ppf_demo_safe_01"
}
BLOCK response
{
"ok": true,
"service": "preflight-check",
"version": "2.x",
"trace_id": "req_example_block_01",
"checked_at": "2026-03-31T10:14:08Z",
"chain": "polygon",
"policy_profile": "payout_strict",
"status": "blocked",
"verdict": "BLOCK",
"reason_code": "NETWORK_MISMATCH",
"next_action": "BLOCK_AND_REVERIFY",
"next_action_label": "Block and re-verify the destination",
"confidence": "High",
"summary": "The submitted payout details do not match the approved instructions.",
"why_this_verdict": "The submitted destination is on a different chain than the approved request. This is the classic wrong-network mistake.",
"risk_flags": ["NETWORK_MISMATCH"],
"checks": {
"network_match": false,
"asset_match": true,
"address_match": true,
"memo_match": true,
"expected_address_valid": true,
"provided_address_valid": true,
"expected_network_supported": true,
"provided_network_supported": true,
"expected_asset_supported": true,
"provided_asset_supported": true
},
"proof": {
"checked_at": "2026-03-31T10:14:08Z",
"chain": "polygon",
"trace_id": "req_example_block_01",
"verdict": "BLOCK",
"confidence": "High",
"reason_code": "NETWORK_MISMATCH",
"next_action": "BLOCK_AND_REVERIFY",
"next_action_label": "Block and re-verify the destination",
"policy_profile": "payout_strict"
},
"record_id": "ppf_demo_block_01",
"history_url": "/api/verification-records/ppf_demo_block_01"
}
TEST FIRST response
{
"ok": true,
"service": "preflight-check",
"version": "2.x",
"trace_id": "req_example_test_01",
"checked_at": "2026-03-31T10:16:08Z",
"chain": "ethereum",
"policy_profile": "payout_strict",
"status": "review_required",
"verdict": "TEST FIRST",
"reason_code": "DESTINATION_IS_CONTRACT_OR_APP",
"next_action": "TEST_FIRST",
"next_action_label": "Send a small test first",
"confidence": "Medium",
"summary": "The details match, but the destination looks like a contract or app.",
"why_this_verdict": "Contract destinations can accept funds differently from a personal wallet. A small test first reduces irreversible mistakes.",
"risk_flags": ["DESTINATION_IS_CONTRACT_OR_APP"],
"checks": {
"network_match": true,
"asset_match": true,
"address_match": true,
"memo_match": true,
"expected_address_valid": true,
"provided_address_valid": true,
"expected_network_supported": true,
"provided_network_supported": true,
"expected_asset_supported": true,
"provided_asset_supported": true
},
"proof": {
"checked_at": "2026-03-31T10:16:08Z",
"chain": "ethereum",
"trace_id": "req_example_test_01",
"verdict": "TEST FIRST",
"confidence": "Medium",
"reason_code": "DESTINATION_IS_CONTRACT_OR_APP",
"next_action": "TEST_FIRST",
"next_action_label": "Send a small test first",
"policy_profile": "payout_strict"
},
"record_id": "ppf_demo_test_01",
"history_url": "/api/verification-records/ppf_demo_test_01"
}
Handle the three that matter first.
401 — missing or invalid API key
{
"ok": false,
"error": "API key required for direct API access."
}
400 — missing required fields
{
"ok": false,
"error": "Both expected.network and provided.network are required."
}
429 — rate limited
{
"ok": false,
"error": "RATE_LIMITED",
"message": "Too many requests. Retry later."
}
Keep the docs light. Get to the first real call fast.
This page is intentionally enough, not endless. Review the public OpenAPI contract if you need the schema, then move straight to a real call or a pilot conversation.