{"name":"OceanAlt","tagline":"Ask before you pay: should this payment go to this address?","description":"The compliance layer for agent payments. OceanAlt answers whether a payment should happen — before the money moves — with click-through evidence rather than a black-box score.","homepage":"https://oceanalt.com","updated":"2026-10-22","quickstart":{"one_call":"curl \"https://oceanalt.com/api/decide?to=0x8589427373D6D84E98730D7795D8f6f8731FDA16&network=ethereum\"","what_you_get":"decision (allow|review|decline; do not pay unless allow, or review inside your mandate) · allow · reason_code · retry · signal_keys[] · evidence[] with source URLs · receipt (Ed25519-signed, verifiable offline)","branch_on":"signal_keys — they are language-independent. The prose in `signals`/`advice` is localised (add &lang=zh) and will change; the keys will not.","fail_mode":"Fail closed. Anything not positively cleared should not be paid. A screening call that fails open is theatre.","runnable_example":"https://raw.githubusercontent.com/OceanAlt/mpp-compliance-adapter/main/quickstart.mjs","read_this_first":"https://oceanalt.com/.well-known/agent-quickstart","read_this_first_note":"~1,100 tokens, plain text. One call, three verdicts, one rule. Come back here only if you need the full capability list."},"access":{"signup_required":false,"api_key_required":false,"levels":{"anonymous":{"how":"Send nothing. This is the default and it stays free.","rate_limit_per_minute":60,"free_calls_per_month":2000,"rate_limit_per_minute_over_allowance":20,"metered":true,"metering_note":"Metered per source IP (stored only as a salted hash). Anonymous is free and stays free, but it is not unmetered — an unmetered anonymous tier is an unmetered scanner.","features":["screen_address","screen_endpoint","calldata_check","intent_check","decide","batch","point_in_time","evidence_bundle"],"we_attribute":"nothing — we see the source IP and that is all"},"registered":{"how":"POST /api/access-keys { email }, click the link in the email, then send `Authorization: Bearer <key>` (or `x-api-key`).","rate_limit_per_minute":180,"free_calls_per_month":5000,"rate_limit_per_minute_over_allowance":60,"features":["screen_address","screen_endpoint","calldata_check","intent_check","decide","batch","point_in_time","evidence_bundle"],"we_attribute":"an email address and this key's usage counts (calls per month, last used) — no per-call history is kept per key"},"kya":{"how":"Register an agent (POST /api/registry/agent), then send `x-agent-id` + `x-agent-secret`. No second key to apply for.","rate_limit_per_minute":300,"free_calls_per_month":50000,"rate_limit_per_minute_over_allowance":120,"features":["screen_address","screen_endpoint","calldata_check","intent_check","decide","batch","point_in_time","evidence_bundle"],"we_attribute":"a linkable agent identity: registry record → mandate → this credential → this call. This is not an independent verification of the controlling person or legal entity behind the agent."}},"free_calls_per_month":5000,"legacy_fields_note":"free_calls_per_month and rate_limits.with_key / over_free_allowance describe the registered level and are kept for older integrations. Per-level figures, including each level's own throttled rate, are in levels.","rate_limits":{"anonymous":"60/min","with_key":"180/min","over_free_allowance":"60/min"},"over_allowance_behaviour":"Normal use is throttled, not cut off, when the free allowance runs out. Abuse, anomalous automation, security risk and violations of the acceptable-use policy are excepted.","why_levels":"Trust tier determines capability tier: the more attributable you are, the more scale, automation and sensitive capability you get. This is not a price list — the anonymous level is free and stays free.","no_bypass":"Every credentialed level's throttled rate is at or above the anonymous normal rate, so dropping your credential never gets you more. KYA allowances aggregate per subject, not per agent.","every_response_carries":"an `access` block stating your level, what you have used, and what the next level would add. You do not need to read documentation to find out.","invalid_credentials":"never silently downgraded — the response says `key_rejected` and why, so you are not left debugging your own code.","key_restrictions":{"what":"The holder of a registered key can limit it three ways. A key with none of them set — which includes every key issued before this existed — behaves exactly as before.","scopes":[{"id":"screen_address","endpoints":["GET /api/risk"],"what":"Address screening: one payee address (the ?on= point-in-time lookup does not read keys and is unaffected)"},{"id":"screen_endpoint","endpoints":["GET /api/endpoint"],"what":"Endpoint screening: is this payment URL a known phishing host"},{"id":"decide","endpoints":["GET /api/decide","POST /api/decide","GET /api/monitor","POST /api/mandate/check"],"what":"Pre-payment decision: allow / review / decline (including the optional intent check)"},{"id":"payee_decide","endpoints":["POST /api/payee/decide"],"what":"Payee-side decision: accept this incoming payment or not"},{"id":"batch_screen","endpoints":["POST /api/risk/batch"],"what":"Batch screening: up to 25 addresses in one call (the paid POST /api/x402/batch authenticates by payment and does not read keys)"},{"id":"trace_funds","endpoints":["GET /api/risk/trace","GET /api/risk/flow"],"what":"Fund-flow tracing: multi-hop taint trace and counterparty flow analysis (two views of the same upstream data, kept in one scope)"},{"id":"evidence_bundle","endpoints":["GET /api/evidence/bundle"],"what":"Evidence bundle: one address's Ed25519-signed evidence bundle"},{"id":"intent_check","endpoints":["POST /api/intent/check","POST /api/payment-request"],"what":"Intent check: what this calldata will actually do, against the payment you declared"},{"id":"baseline_lookup","endpoints":["GET /api/baseline/lookup"],"what":"Control-baseline lookup: what controls a counterparty has attested to, before you settle"}],"scope_rule":"Optional. Limit one key to any subset of: screen_address, screen_endpoint, decide, payee_decide, batch_screen, trace_funds, evidence_bundle, intent_check, baseline_lookup. A key with no scopes set — which includes every key issued before this existed — may call all of them, and any scope added later. A call outside a key's scopes is refused with HTTP 403 and reason_code key_scope_denied.","endpoints_that_ignore_keys":"Only the endpoints listed under these scopes, plus the MCP endpoint (see mcp), read an API key at all. What still ignores one, and why: the x402 paid endpoints (POST /api/x402/*), which are paid per call and never needed a key; the point-in-time lookup GET /api/risk?on=; and the remaining utility endpoints (/api/pay, /api/fulfillment, /api/baseline, /api/registry/agent, the RAP endpoints). Those are rate limited per source IP, so scopes, allowlists and expiry do not apply there. Agent credentials (x-agent-id + x-agent-secret) are a separate mechanism and are unaffected by key restrictions.","scope_vs_quota":"Scopes govern what a key may do, not how much. On the six endpoints added on 2026-09-16 — batch, trace, flow, evidence bundles, intent checks, baseline lookups — a key that is sent is checked against its scopes, allowlist and expiry, but the call is still rate limited per source IP and still counts towards nobody's monthly allowance. Sending no key there behaves exactly as it did before: same rate limit, same response, no metering.","ip_allowlist":"Optional. Up to 20 IPv4 or IPv6 addresses or CIDR ranges. A call from any other address is refused with HTTP 403 and reason_code key_ip_denied. The source address is the one our reverse proxy records for the connection; an X-Forwarded-For header sent by the caller is not trusted. IPv4 and IPv6 are matched separately, so ::/0 does not cover IPv4 callers.","expiry":"Optional expires_at. Past it the key is treated exactly like a revoked key: the call is still served, at the anonymous level, and the response says key_rejected: expired. It is never silently downgraded.","reason_codes":["key_scope_denied","key_ip_denied"],"manage":"GET /api/access-keys/settings with the key reads its current settings; POST /api/access-keys/settings with { scopes?, ip_allowlist?, expires_at?, decision_log?, decision_log_days? } changes them. Fields you leave out keep their current value.","settings_endpoint":"GET /api/access-keys/settings","change_rule":"Tightening — fewer scopes, a narrower allowlist, an earlier expiry — takes effect immediately when authenticated with the key itself, because tightening cannot grant anything. Loosening — more scopes, a wider or removed allowlist, a later or removed expiry — only takes effect after the holder opens a confirmation link emailed to the address the key was issued to (valid 24 hours) and confirms it there. A request that loosens anything waits as a whole. A key that has an IP allowlist can only be managed from an allowlisted address."},"cors":"enabled (*)","paid":{"protocol":"x402","settlement":"USDC on Base or Solana (each 402 quote lists the accepted networks in accepts[])","note":"Pay-per-call, no account. Free tools cover the common case; paid endpoints add gateway verdicts, taint tracing and batch."}},"capabilities":[{"id":"decide","what":"Should I pay this payee? One call returns allow / review / decline with reason_code, signal_keys, evidence and evidence_set (RAP v1.1 machine format). Branch on decision and signal_keys.","endpoint":"POST /api/decide { to, network?, payment_intent? }","cost":"free"},{"id":"payee_continuity","what":"Has the payee changed since my last payment to this seller? Send previous_payment_intent with payment_intent; a changed payee, network or asset raises the decision to review (payee_changed_since_previous).","endpoint":"POST /api/decide { payment_intent, previous_payment_intent }","cost":"free"},{"id":"listing_check","what":"Does this payee match the payout wallet the endpoint lists in the public x402 directory (refreshed daily)? A mismatch raises the decision to review (payee_differs_from_listing).","endpoint":"POST /api/decide { payment_intent: { resource_ref, … } }","cost":"free"},{"id":"decision_receipt","what":"Every decision carries a receipt signed with Ed25519 that you can verify offline with the public key at /.well-known/oceanalt-keys.json, without calling OceanAlt. It binds the decision, reason code, signal keys and the payment intent digest, and expires after 15 minutes. It proves origin and integrity, not that the decision is right.","endpoint":"POST /api/decide · POST /api/x402/decision → receipt","cost":"free"},{"id":"payee_authorization","what":"Is this payee authorized by whoever controls the site you are paying? We check x402 signed offers (signer authorized via did:web or DNS _controllers) and a signed /.well-known/x402 manifest. bound: a payee change on the same site is an authorized rotation and does not raise the decision; not_bound: review, or decline if the payee also changed; inconclusive: nothing published, decision unchanged.","endpoint":"POST /api/decide { payment_intent: { resource_ref, … }, signed_offers? }","cost":"free"},{"id":"origin_binding","what":"Does the site you are paying name this payee in its own x402 quote? We ask the origin of resource_ref directly. A different payee, or an origin that cannot be checked, raises the decision to review (payee_not_bound_to_origin / payee_origin_binding_unavailable).","endpoint":"POST /api/decide { payment_intent: { resource_ref, … } }","cost":"free"},{"id":"post_payment_monitor","what":"Keep watching the payee after you pay and get a signed webhook or email if its verdict gets worse. Needs an API key.","endpoint":"POST /api/decide { …, monitor_after_payment: { days, webhook_url } } · GET /api/monitor","cost":"free"},{"id":"payee_activity","what":"Reference only: does a listed x402 payee's incoming USDC come from many independent payers, or mostly from one payer or from wallets it funded itself?","endpoint":"POST /api/decide (field payee_activity)","cost":"free"},{"id":"screen_payee","what":"Is this payee address known-risky?","endpoint":"GET /api/risk?addr=&network=&lang=","cost":"free"},{"id":"screen_endpoint","what":"Is the payment ENDPOINT itself a known phishing host? Address screening cannot answer this — a spoofed endpoint returns a fresh address no list has seen.","endpoint":"GET /api/endpoint?url=&lang=","cost":"free"},{"id":"check_payment_request","what":"Before paying because an email, invoice or message asked you to: is the sender spoofed, are the sender domain and links phishing or lookalikes, is the payee listed or changed since last time, does the text pressure you or carry instructions aimed at an AI? allow / review / decline with findings; text processed in memory, not stored. MCP tool check_payment_request.","endpoint":"POST /api/payment-request","cost":"free"},{"id":"gateway_payment","what":"Compliance gateway for registered agents: run every pre-settlement gate on a payment against the agent's mandate (preview), then pay.","endpoint":"POST /api/pay","cost":"free (preview) / paid (settle)"},{"id":"payee_decide","what":"From the payee's side: accept, decline, or hold and request info","endpoint":"POST /api/payee/decide","cost":"free"},{"id":"verify_payment_requirements","what":"Was this x402 402 response's payTo/amount/asset/network signed by the seller and left untouched in transit? Our own 402s carry extensions.signedRequirements inside the PAYMENT-REQUIRED header payload (mirrored in the body); verify offline against /.well-known/oceanalt-keys.json or via this endpoint.","endpoint":"POST /api/x402/verify-requirements","cost":"free"},{"id":"check_calldata_intent","what":"Anti blind-signing: what will this calldata ACTUALLY do, and does it match the payment I think I am making? Catches approve(attacker, unlimited) dressed up as a payment.","endpoint":"POST /api/intent/check","cost":"free"},{"id":"fulfillment_receipt","what":"After paying, file a receipt: 'I paid this tx (verified on-chain) and did / did not receive'. Payees file 'delivered / disputed'. Both sides shown side by side, nothing adjudicated, no custody; per-payee rates only after 10 verified receipts.","endpoint":"POST /api/fulfillment · GET /api/fulfillment?payee=","cost":"free"},{"id":"paid_decision","what":"The same decision as /api/decide, paid per call over x402 ($0.002) with no key and no signup; adds a signed settlement attestation.","endpoint":"POST /api/x402/decision","cost":"paid (x402)"},{"id":"credit_pack","what":"Prepay 100 decision calls in one x402 payment ($0.10).","endpoint":"POST /api/x402/credits","cost":"paid (x402)"},{"id":"verify_attestation","what":"Anyone can check that a payment carried an OceanAlt decision: verify the attestation token bound to a settlement.","endpoint":"GET /api/attestation/verify?token=<attestation>","cost":"free"},{"id":"batch_screen","what":"Screen many addresses in one call","endpoint":"POST /api/x402/batch","cost":"paid (x402)"},{"id":"appeal","what":"If we flagged your address, appeal it. GET returns our public review scorecard with the overturn rate; POST files an appeal.","endpoint":"GET|POST /api/appeal","cost":"free"},{"id":"observatory","what":"Weekly density of agent-payment terms in public coverage, and the terms that are rising.","endpoint":"GET /api/observatory/bubbles · GET /api/observatory/emerging","cost":"free"},{"id":"payee_check","what":"Check a payee and the paid route before paying: sanctions, how many hosts share the payee in the public x402 directory, and recent payout-address changes","endpoint":"POST /api/x402/payee","cost":"paid (x402)"},{"id":"deep_trace","what":"Multi-hop USDT taint trace on TRON only (the free multi-chain deep trace is GET /api/risk/trace; see coverage.chains)","endpoint":"GET /api/x402/trace?addr=","cost":"paid (x402)"},{"id":"attest_control_baseline","what":"Publish what controls YOUR operator runs, so payers can read it before settling with you. Gaps are allowed if declared with a plan.","endpoint":"POST /api/baseline/attest","cost":"free"},{"id":"conformance_submit","what":"Enter your own gateway on the public conformance scoreboard. You submit a URL, not a score — we run the vectors and publish the result, failures included.","endpoint":"POST /api/rap/conformance/submit","cost":"free"},{"id":"conformance","what":"Run the RAP conformance suite against any implementation, including ours","endpoint":"GET /api/rap/conformance","cost":"free"},{"id":"rap_vectors_version","what":"Current version and count of the RAP conformance vectors, so a runner can tell whether to update","endpoint":"GET /api/rap/vectors-version","cost":"free"},{"id":"reason_code_pack","what":"Machine-readable reason_code, signal_class and retry semantics: decide whether to retry or escalate to a person","endpoint":"GET /api/x402/conformance","cost":"free"},{"id":"contract_profile","what":"Before paying or signing: is the counterparty a contract, is its source verified, who created it, and is the creator on a risk list","endpoint":"GET /api/risk/contract?addr=&network=","cost":"free"},{"id":"multisig_check","what":"Is this payee a multisig wallet type we recognise (Safe, MultiSigWallet)","endpoint":"GET /api/risk/multisig?addr=&network=","cost":"free"},{"id":"tx_check","what":"After paying: check a transaction and its counterparty","endpoint":"GET /api/tx?hash=&network=","cost":"free"}],"interfaces":{"rest":"https://oceanalt.com/api-docs","openapi":"https://oceanalt.com/openapi.json","mcp":{"npm":"oceanalt-aml-mcp","run":"npx oceanalt-aml-mcp","registry":"com.oceanalt/aml","remote":"https://oceanalt.com/api/mcp","remote_rate_limit_per_minute":{"without_key_per_ip":60,"with_key_per_key":240},"paid_tools_local_only":["compliance_decision","deep_trace","batch_screen"],"paid_tools_note":"The paid x402 tools sign with your own wallet key, so they run only in the local npm server (npx oceanalt-aml-mcp), not on the remote endpoint."},"sdk":{"npm":"oceanalt-aml","install":"npm i oceanalt-aml"},"framework_adapters":[{"framework":"Vercel AI SDK","npm":"@oceanalt/vercel-ai","install":"npm i @oceanalt/vercel-ai ai zod","guide":"https://oceanalt.com/en/developers/vercel-ai-sdk"},{"framework":"LangChain.js","npm":"@oceanalt/langchain","install":"npm i @oceanalt/langchain @langchain/core zod","guide":"https://oceanalt.com/en/developers/langchain"}],"telegram_bot":"@OceanAltTrust_Bot","discord_bot":"/check <address or URL> — same verdicts, interactions endpoint at /api/discord/interactions","mcp_free_tools":["screen_address","screen_endpoint","payee_decide","payment_decision","counterparty_control_baseline","baseline_controls","attest_control_baseline","resolve_agent_identity","recent_flagged","verify_payment_requirements","check_calldata_intent","evidence_bundle","check_payment_request"],"embed":"https://oceanalt.com/embed.js"},"coverage":{"networks":["ethereum","base","bsc","polygon","arbitrum","optimism","avalanche","arc","tron","solana","bitcoin","xrpl"],"endpoint_layer":{"what":"Malicious-domain screening, chain-agnostic. Covers the step that happens before any address exists: the URL the agent is about to call.","sources":["phishing-domain intelligence"],"endpoint":"GET /api/endpoint?url="},"declaration":"https://oceanalt.com/en/coverage","status":"https://oceanalt.com/en/status","malicious_domains":998431,"counted_at":"2026-10-22T15:18:42.566Z","depth_note":"List matching (sanctions / mixer / scam / hack / OceanAlt-reviewed) runs on every chain. Full depth — issuer freeze lists, address age and activity, and one-hop taint in the verdict, with fund flow and multi-hop deep trace on request — on Ethereum, Polygon, Arbitrum, Base, Optimism and TRON. BSC and Avalanche are partial depth: see `chains` for exactly which steps run there. Bitcoin and Solana verdicts use list matching only, with multi-hop deep trace on request. Per-chain detail in `chains`.","batch_note":"Batch screening skips the EVM issuer-freeze lookup and TRON one-hop taint for speed; screen addresses one at a time when you need those steps.","chains":[{"chain":"ethereum","name":"Ethereum","depth":"full","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USDT","USDC","USDP","PYUSD","BUSD","PAXG","EURC","FDUSD","cbBTC","USD1","XAUT","EURT"],"on_request":["fund_flow","deep_trace"],"note":"List matching, issuer freeze lists (twelve tokens: USDT, USDC, USDP, PYUSD, BUSD, PAXG, EURC, FDUSD, cbBTC, USD1, XAUT, EURT; PAXG and XAUT are tokenized gold and cbBTC is wrapped bitcoin, not stablecoins), address age and activity, one-hop taint; fund flow and deep trace on request. USDT on Ethereum is checked against Tether's on-chain blacklisting record, with token contracts that Tether blacklisted to prevent mis-sends removed as non-risk entries; the other tokens are read directly from their on-chain freeze-list contracts. The FDUSD, USD1, XAUT and EURT freeze lists are verified as live only."},{"chain":"polygon","name":"Polygon","depth":"full","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USDC","USDT"],"on_request":["fund_flow","deep_trace"],"note":"List matching, issuer freeze lists (USDC, USDT), address age and activity, one-hop taint; fund flow and deep trace on request. The USDT freeze list here is verified as live only."},{"chain":"arbitrum","name":"Arbitrum","depth":"full","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USDC","USDT"],"on_request":["fund_flow","deep_trace"],"note":"List matching, issuer freeze lists (USDC, USDT), address age and activity, one-hop taint; fund flow and deep trace on request. The USDT freeze list here is verified as live only."},{"chain":"base","name":"Base","depth":"full","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USDC","EURC","cbBTC"],"on_request":["fund_flow","deep_trace"],"note":"List matching, issuer freeze lists (USDC, EURC and cbBTC, read directly from on-chain freeze-list contracts), address age and activity, one-hop taint; fund flow and deep trace on request."},{"chain":"optimism","name":"Optimism","depth":"full","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USDC"],"on_request":["fund_flow","deep_trace"],"note":"List matching, issuer freeze list (USDC), address age and activity, one-hop taint; fund flow and deep trace on request."},{"chain":"tron","name":"TRON","depth":"full","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USDT"],"on_request":["fund_flow","deep_trace","deep_trace_paid"],"note":"List matching, the Tether freeze list (USDT-TRC20), one-hop taint (USDT received from Tether-frozen addresses), address age, activity and public explorer labels; fund flow and deep trace on request (also available as a paid per-call endpoint)."},{"chain":"bsc","name":"BNB Chain","depth":"partial","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USD1","FDUSD"],"on_request":["fund_flow"],"note":"List matching, issuer freeze lists (USD1 and FDUSD), address age and activity, one-hop taint; fund flow on request. Deep trace is not offered on this chain yet. **USDT and USDC here are Binance-Peg tokens with no issuer freeze list to query**; the USD1 and FDUSD freeze lists are verified as live only."},{"chain":"avalanche","name":"Avalanche","depth":"partial","verdict_steps":["lists","issuer_freeze","address_activity"],"issuer_freeze_tokens":["USDC","USDT","EURC"],"on_request":[],"note":"List matching, issuer freeze lists (USDC, USDT, EURC) and address activity (on-chain transaction count and balance). One-hop taint, fund flow and deep trace are not offered on this chain yet. The USDT freeze list is verified as live only."},{"chain":"arc","name":"Arc","depth":"full","verdict_steps":["lists","issuer_freeze","address_activity","address_age","onehop_taint"],"issuer_freeze_tokens":["USDC"],"on_request":[],"note":"List matching, issuer freeze list (USDC, read directly from Circle's freeze-list contract on this chain), address age and activity, and one-hop taint. Verdicts go as deep here as on Ethereum. Fund flow and deep trace are not offered on this chain yet. USDC is the native gas token here, so the balance is a USDC balance."},{"chain":"solana","name":"Solana","depth":"list","verdict_steps":["lists"],"issuer_freeze_tokens":[],"on_request":["deep_trace"],"note":"Verdicts use list matching, without on-chain behavioural analysis; deep trace on request (follows USDC/USDT inflows upstream, up to 3 hops)."},{"chain":"bitcoin","name":"Bitcoin","depth":"list","verdict_steps":["lists"],"issuer_freeze_tokens":[],"on_request":["deep_trace"],"note":"Verdicts use list matching, without on-chain behavioural analysis; deep trace on request (follows inflows upstream, up to 3 hops)."},{"chain":"xrpl","name":"XRP Ledger","depth":"list","verdict_steps":["lists"],"issuer_freeze_tokens":[],"on_request":[],"note":"Verdicts use list matching, without on-chain behavioural analysis. Deep trace is not offered on this chain."}],"step_definitions":{"lists":"Sanctions, mixer, scam/phishing, hack and OceanAlt-reviewed address lists (chain-agnostic).","issuer_freeze":"Stablecoin issuer freeze list, read on-chain (see issuer_freeze_tokens).","address_activity":"Transaction count and balance.","address_age":"First-seen date and new-address signals.","onehop_taint":"Funds received directly from a listed address (EVM) or USDT received from a Tether-frozen address (TRON). This is not a full-history scan.","fund_flow":"GET /api/risk/flow — upstream and downstream counterparties. TRON: USDT. EVM: native coin and token transfers with USD estimates; zero-value and junk-token transfers are excluded. Returned separately; does not change the verdict.","deep_trace":"GET /api/risk/trace — free, 8 requests/min per IP, up to 3 hops, largest 3 sources per hop, main path only. Returned separately; does not change the verdict.","deep_trace_paid":"GET /api/x402/trace — paid per call over x402, TRON USDT, up to 3 hops. Returned separately; does not change the verdict."}},"gateway":{"gates_total":11,"gates_always_on":9,"order":[{"key":"kya","name":"Attribution (KYA)","optional":false},{"key":"revoked","name":"Revocation check","optional":false},{"key":"proof","name":"Identity proof (anti-impersonation)","optional":false},{"key":"kyc","name":"KYC gate (optional)","optional":true},{"key":"limit","name":"Per-payment limit","optional":false},{"key":"velocity","name":"Daily cumulative limit","optional":false},{"key":"allowlist","name":"Payee allowlist","optional":false},{"key":"mandate","name":"Mandate-intent match (anti prompt-injection)","optional":false},{"key":"aml","name":"AML sanctions & risk screening","optional":false},{"key":"anomaly","name":"Behavioral anomaly detection (optional)","optional":true},{"key":"replay","name":"Replay & double-spend prevention","optional":false}],"note":"These run before settlement, in this order. Two are off by default and opt-in per tenant.","idempotency":{"header":"Idempotency-Key","applies_to":"the payment call and action rotate on the gateway endpoint; other actions ignore the header","window_hours":24,"replay":"Same x-agent-secret + same key + same JSON body → the original status code and body, with response header Idempotent-Replayed: true. Nothing runs twice, and the retry is not recorded as a replay attack or alerted to the key owner.","retry_rule":"Keep the same key AND the same nonce when retrying. A new payment needs a new key and a new nonce.","errors":{"idempotency_key_reused":"422: same key, different body. Nothing was executed.","idempotency_request_in_progress":"409: the original request is still running. Resend unchanged after retry-after.","idempotency_key_invalid":"400: the key must be 1-255 printable ASCII characters."},"without_header":"Behaviour unchanged.","spec":"https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/"}},"webhooks":{"what":"When one of your agents is blocked or flagged, OceanAlt POSTs JSON to the webhook URL you set in the console.","configure":"https://oceanalt.com/en/keys","signature":{"spec":"https://www.standardwebhooks.com/","headers":["webhook-id","webhook-timestamp","webhook-signature"],"scheme":"v1,<base64 HMAC-SHA256 over webhook-id.webhook-timestamp.raw-body>, keyed with the base64-decoded bytes after whsec_","timestamp_tolerance_seconds":300,"rotation":"For 24 hours after a rotation both the new and the previous secret sign (space-separated); accept if any matches.","secret":"Shown once in the console; rotate if lost."},"delivery":{"success":"any 2xx within about 5 seconds; redirects are not followed","retry_after_seconds":[60,300,1800,7200],"max_attempts":5,"same_webhook_id_on_retry":true,"log":"every attempt (status code, duration, error summary) is visible in the console for 30 days"},"verify_example":"https://oceanalt.com/en/api-docs#webhooks"},"standard":{"name":"RAP — Responsible Agentic Payments Framework v1.0","url":"https://oceanalt.com/en/rap","pillars":["attribution (KYA)","mandate & limits","controls / firewall","screening (AML)","auditability","privacy","interoperability"],"conformance_vectors":15,"conformance_runner":"https://raw.githubusercontent.com/OceanAlt/mpp-compliance-adapter/main/rap-conformance.mjs","conformant_means":"every critical vector passes; failing important vectors are disclosed but do not negate conformance","scoreboard":"https://oceanalt.com/en/rap/conformance"},"limitations":["\"clear\" means we found nothing in the data we hold. It is not a statement that an address is safe. Absence of evidence is not evidence of safety.","We do not custody funds and we do not move money. We answer whether a payment should happen; settlement is someone else's layer.","We do not verify the identity of a payee. We screen an address against lists and on-chain behaviour.","A partnership, a directory listing or an integration badge is not an endorsement, a security guarantee, or a compliance certification.","Ratings and research stay independent of any commercial relationship; partners are held to the same standard as non-partners.","Cross-chain tracing stops at a bridge. We say so rather than guessing what happened on the other side.","Pre-payment screening applies to part of three incident classes: frontend/domain hijacks, social engineering and rugpulls. Key compromise, contract bugs, oracle manipulation and bridge flaws happen outside this layer and screening does not stop them. Our incident archive classifies real crypto incidents by whether pre-payment screening applies: GET /api/incidents/stats (human page https://oceanalt.com/en/incidents).","Our address list is not complete, and no match does not mean an address is safe. We publish a per-chain coverage declaration instead of claiming completeness: https://oceanalt.com/en/coverage (machine-readable: coverage.chains above).","A decision protects only payments whose caller asks before paying and acts on the verdict. Transfers that skip the check, or go ahead after a decline, are not covered. /watch alerts report a risk change or an outgoing transfer after the fact and never block it. The one mechanism that enforces limits without our servers is the on-chain spending policy at /en/lab/onchain — testnet only, not yet third-party audited.","Verdicts use one-hop relations only: on EVM chains where one-hop taint runs, funds received directly from a listed address (not a full-history scan); on TRON, USDT received from a Tether-frozen address; and on EVM, having received funds directly from a listed address according to our precomputed relation table, which can raise a verdict to caution but never to risky. Multi-hop tracing runs only on request — GET /api/risk/trace (free, 8 requests/min per IP, up to 3 hops, largest 3 sources per hop, main path only; Ethereum, Base, Polygon, Arbitrum, Optimism, TRON, Bitcoin, Solana) and GET /api/x402/trace (paid per call, TRON USDT, up to 3 hops). A trace result is returned on its own and does not change the screening verdict."],"machine_contract":{"language":"English by default; add lang=zh for Chinese prose.","stable_keys":"signal_keys, reason_code, verdict, retry — branch on these, not on prose.","contract":"https://oceanalt.com/api/contract","contract_guarantee":"Additive-only. Identifiers are never renamed or removed without a 90-day deprecation cycle, and a build gate enforces it — a promise without a lock on it is not a promise.","verdicts":["clear","caution","risky","uncertain"],"uncertain_note":"uncertain means screening could not complete. It must never be treated as clear."},"contact":{"business":"business@oceanalt.com","issues":"https://github.com/OceanAlt666/oceanalt-aml-mcp/issues"},"license":"https://oceanalt.com/en/legal"}