# Faithful YAML serialization of https://legit.gonna.bond/openapi.json as fetched 2026-09-19 (HTTP 200, application/json, 59,922 bytes). # Content is unchanged from the provider's document; the verbatim JSON is at openapi/_original/gonna-bond-legit-openapi-original.json. # The provider publishes no servers[] block; the base URL https://legit.gonna.bond is recorded in apis.yml from the provider's own llms.txt examples. openapi: 3.1.0 info: title: LEGIT description: 'Trust-check any x402 merchant or agent address on Algorand, Base, Solana, or 17 other chains before routing a payment. Returns a real-time grade (A+ to F) and score (0-100) built from live uptime, response latency, and payment coherence measurements, not self-reported data. Run as a pre-payment trust check: call GET /v1/check/{address} before any x402 payment to an address you have not paid before. Free: check a single address, pull a full trust report, batch-check multiple addresses, get a routing recommendation between two counterparties, resolve a merchant''s on-chain identity, query the ranked merchant leaderboard, see trending active merchants, and read live network pulse. Paid ($0.004 Algorand / $0.005 Base, via x402): compare two addresses side-by-side, get arena verdicts, pull 30-day score history for trend analysis, set a webhook-armed watch sentinel (7-day diagnostic tier or 30-day standard, same rail price) that fires on grade transitions, and run deep-check due diligence. Use before sending an x402 payment to an unknown merchant, before accepting a counterparty in agent-to-agent settlement, or to monitor a critical upstream service for trust degradation. Created by GONNA.' version: 0.1.0 contact: name: GONNA url: https://gonna.bond/gonnaverse/ email: legit@gonna.bond x-logo: url: https://legit.gonna.bond/favicon.png x-guidance: 'LEGIT is the trust and routing layer for the x402 agentic economy. Trust-check any x402 merchant address on Algorand, Base, Solana or 17 other chains before routing a payment: grades (A+ to F) and scores (0-100) come from live uptime, latency and payment-coherence probes, never self-reported data. Run as a pre-payment trust check: call GET /v1/check/{address} before any x402 payment to an address you have not paid before. Start FREE: GET /v1/check/{address} (full trust report), /v1/leaderboard (ranked shortlist), /v1/trending, /v1/pulse, /v1/arena/preview. Paid per call in USDC over x402: GET /v1/compare (2-5 merchants head-to-head), /v1/arena (24h cross-chain settlement benchmark, ?network= filter), /v1/history?address=... (30-day trust trend), POST /v1/watch (7- or 30-day change sentinel, webhook-armed), POST /v1/deep-check (due diligence, up to 10 addresses). How to pay: call a paid endpoint without paying and it answers 402 with a PaymentRequired document listing every active rail; pay one rail and retry with the PAYMENT-SIGNATURE header. Rails cheapest first: algorand-mainnet $0.004, base-mainnet and solana-mainnet $0.005 per call. Watch companions GET /v1/watches/{watch_id} and /v1/watches/{watch_id}/events are FREE: the watch id is the bearer capability for status and the event feed. Webhook payload anatomy: /docs; agent manifest: /llms.txt. Use LEGIT before sending an x402 payment to an unknown merchant, before accepting a counterparty in agent-to-agent settlement, or to monitor a critical upstream for trust degradation.' paths: /health: get: summary: Liveness probe description: 'Liveness probe: ``{"status": "ok"}`` when the service is up (FREE).' operationId: health_health_get responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Health Health Get security: [] /v1/leaderboard: get: summary: Query the ranked merchant leaderboard to shortlist counterparties description: 'Leaderboard with optional ?network= filter (SPEC_V2, Module A). ``networks`` always lists the distinct networks present BEFORE filtering so clients can build filter chips; backwards compatible with Wave 1. Wave 16 (Instant Speed): cacheable for 30s. ``view=trimmed`` is the dashboard''s diet variant: null optional fields are omitted entirely (the dashboard treats absent and null identically), which removes hundreds of ``"field":null`` pairs from a large board. The default view is byte-for-byte the public contract it always was. Wave 18 (The Instant Doctrine): opt-in server pagination via ``page``/``size`` (25/50/100) plus a ``q`` name/address substring filter, sliced AFTER the existing filter+sort+rank logic so ranks stay global; the paged payload also carries ``counts`` (cheap per-network tallies for the dashboard chips). A 30s in-process TTL cache (keyed by the full query string) fronts every variant; the rate limiter still sees every request. Wave 40 (La Voce): testnet networks and dormant merchants (no measurement inside LEGIT_ACTIVE_WINDOW_DAYS, default 7 days) are out of the default view; ``?include_testnet=true`` and ``?include_dormant=true`` restore them, dormant entries flagged ``dormant: true``. Wave 41 (La Bellezza, W0): ``rank`` is the consecutive position in the returned view (post testnet/dormant policy): 1,2,3 with no holes. The additive ``rank_global`` preserves the absolute pre-filter rank; with both opt-ins active, rank == rank_global.' operationId: leaderboard_v1_leaderboard_get parameters: - name: network in: query required: false schema: anyOf: - type: string minLength: 1 maxLength: 32 pattern: ^[a-z0-9-]+$ - type: 'null' description: Optional exact-match network filter (e.g. base-mainnet) title: Network description: Optional exact-match network filter (e.g. base-mainnet) - name: view in: query required: false schema: anyOf: - type: string pattern: ^(full|trimmed)$ - type: 'null' description: 'Optional payload diet. ''trimmed'' omits null-valued optional fields (additive contract: absent instead of null); the default keeps the full Wave 1 shape.' title: View description: 'Optional payload diet. ''trimmed'' omits null-valued optional fields (additive contract: absent instead of null); the default keeps the full Wave 1 shape.' - name: page in: query required: false schema: anyOf: - type: integer minimum: 1 - type: 'null' description: 'Wave 18: optional 1-based server page. When page and/or size are given the response becomes the paged shape {generated_at, total, page, size, entries} sliced AFTER the global rank/filter logic, so ranks stay global.' title: Page description: 'Wave 18: optional 1-based server page. When page and/or size are given the response becomes the paged shape {generated_at, total, page, size, entries} sliced AFTER the global rank/filter logic, so ranks stay global.' - name: size in: query required: false schema: anyOf: - type: integer - type: 'null' description: 'Wave 18: page size, one of 25, 50, 100 (default 50 when paging).' title: Size description: 'Wave 18: page size, one of 25, 50, 100 (default 50 when paging).' - name: q in: query required: false schema: anyOf: - type: string minLength: 1 maxLength: 100 - type: 'null' description: 'Wave 18: optional name/address substring filter.' title: Q description: 'Wave 18: optional name/address substring filter.' - name: include_testnet in: query required: false schema: type: boolean description: 'Wave 40: testnet/devnet/amoy/sepolia networks are excluded by default; pass ?include_testnet=true to restore them (same entry shape).' default: false title: Include Testnet description: 'Wave 40: testnet/devnet/amoy/sepolia networks are excluded by default; pass ?include_testnet=true to restore them (same entry shape).' - name: include_dormant in: query required: false schema: type: boolean description: 'Wave 40: the default view shows only merchants with a measurement inside the active window (LEGIT_ACTIVE_WINDOW_DAYS, default 7 days); pass ?include_dormant=true for the full view, with dormant entries flagged dormant=true.' default: false title: Include Dormant description: 'Wave 40: the default view shows only merchants with a measurement inside the active window (LEGIT_ACTIVE_WINDOW_DAYS, default 7 days); pass ?include_dormant=true for the full view, with dormant entries flagged dormant=true.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Leaderboard' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/stats: get: summary: Read headline service stats and storage facts description: 'Headline service stats: merchant and measurement counts, average trust score and verifiable storage facts (FREE, cached 30s).' operationId: stats_v1_stats_get responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Stats' security: [] /v1/compare: get: summary: Compare 2-5 addresses side-by-side before picking one to pay description: 'Compare 2-5 merchant addresses head-to-head (FREE, rate limited). Returns a TrustReport-like summary per address plus ``winner`` (best trust score; Wave 7 ties broken by more real payments settled, then lower median latency, then higher sample size) and a plain-English ``rationale``. Untracked addresses are included with ``score=null`` and ``tracked=false``; they cannot win. Wave 41c (Il Cliente Cieco): ``addresses`` is optional. A blind client (one that paid and calls with no parameters) gets the top merchants of the current default ranking compared, with the additive ``defaults_applied`` field disclosing the choice; when the ranking holds too few real merchants no sensible default exists and the parameter stays honestly required (self-documenting 422). Paid: $0.004 on Algorand / $0.005 on Base, via x402 (per call in USDC on algorand-mainnet or base-mainnet; the 402 response lists every active rail). The POST /v1/watch 7-day diagnostic tier pays the same per-call rail price as the 30-day watch.' operationId: compare_v1_compare_get parameters: - name: addresses in: query required: false schema: anyOf: - type: string minLength: 1 maxLength: 2000 - type: 'null' description: 'Comma-separated merchant addresses (2-5). Optional: when omitted, the top merchants of the current default ranking are compared and the choice is disclosed in defaults_applied.' title: Addresses description: 'Comma-separated merchant addresses (2-5). Optional: when omitted, the top merchants of the current default ranking are compared and the choice is disclosed in defaults_applied.' examples: two_addresses: summary: Compare two Algorand merchant addresses value: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A,ZQFL2SVFDQDKFAUCCE2WVXH6EF3LRUUJZLKJMDIED56LODOKW23JSKB7NT three_addresses: summary: Compare three Algorand merchant addresses value: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A,ZQFL2SVFDQDKFAUCCE2WVXH6EF3LRUUJZLKJMDIED56LODOKW23JSKB7NT,TARTD3TCZERKBTXQQEQED76TGSCBU6SL2QE3Z5K74GKTRCIHFMSIDAOLJP responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CompareResponse' example: generated_at: '2026-01-01T00:00:00+00:00' entries: - address: ADDRESS_A name: Merchant A score: 82.5 grade: B provisional: false uptime_pct: 99.5 latency_p50_ms: 210.0 sample_size: 12 settle_count: 340 network: algorand-mainnet explorer_url: https://allo.info/account/ADDRESS_A tracked: true - address: ADDRESS_B name: null score: null grade: null provisional: false uptime_pct: null latency_p50_ms: null sample_size: 0 settle_count: 0 network: null explorer_url: null tracked: false winner: ADDRESS_A rationale: 'Merchant A wins: highest trust score (82.5 vs 71.0).' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' '402': description: 'Payment required: the body is an x402 PaymentRequired document (x402Version, error, resource, accepts) listing the USDC payment offers for every active rail; retry with a payment payload.' content: application/json: schema: type: object properties: x402Version: type: integer error: type: string resource: type: object accepts: type: array items: type: object x-payment-info: price: mode: fixed currency: USD amount: '0.004' protocols: - x402: {} /v1/check/{address}: get: summary: Trust-check a merchant address before paying it description: Full trust report for one merchant (Algorand address or base URL). operationId: check_v1_check__address__get parameters: - name: address in: path required: true schema: type: string title: Address responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/TrustReport' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/receipts: get: summary: Receipts description: 'Verified on-chain payment receipts for one tracked merchant. The 30-day ledger of real settlements observed by LEGIT''s own keyless chain scan (Algorand first): who paid, how much, when, with the on-chain transaction id as independently verifiable evidence. ``receipts`` is newest-first and capped at 100 entries while ``total_receipts`` and ``volume_usd`` cover the full window. An empty window is an honest empty answer (total_receipts 0, receipts []), never invented rows; untracked addresses get an honest 404. Wave 47b: the address is a mandatory query parameter (the /v1/history convention), so the registered path is exactly "/v1/receipts" and an operator-declared X402_PREMIUM_PATHS entry matches it byte-for-byte. This endpoint is FREE by construction: it ships outside X402_PREMIUM_PATHS and stays free until the operator adds the path to that env var (per-path payment via the app.payments middleware, which this wave does not touch).' operationId: receipts_v1_receipts_get parameters: - name: address in: query required: true schema: type: string minLength: 1 maxLength: 300 description: Merchant address (or base URL) exactly as tracked by LEGIT, e.g. ?address=ADDR. title: Address description: Merchant address (or base URL) exactly as tracked by LEGIT, e.g. ?address=ADDR. examples: algorand_address: summary: 30-day receipts of one Algorand merchant value: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ReceiptsResponse' '404': description: 'The address is not tracked by LEGIT: an honest 404, never an invented ledger.' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/route: get: summary: Get a routing recommendation between two counterparties description: 'Phase 0 routing: keyword match on merchant name/address, best score wins.' operationId: route_v1_route_get parameters: - name: need in: query required: true schema: type: string minLength: 1 maxLength: 200 title: Need responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/RouteResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/report/{address}: get: summary: Pull the full trust report of one merchant before integrating description: 'Deep report: full breakdown, 30-row score history, rank and percentile. FREE (rate limited). Unknown addresses get an honest unrated report. The fabricated demo report requires the explicit ``?demo=true`` opt-in.' operationId: report_v1_report__address__get parameters: - name: address in: path required: true schema: type: string title: Address - name: demo in: query required: false schema: type: boolean description: 'Opt-in demo mode: for the five hardcoded demo addresses, return the fabricated illustration report flagged demo=true. Off by default: fabricated data is never served unmarked.' default: false title: Demo description: 'Opt-in demo mode: for the five hardcoded demo addresses, return the fabricated illustration report flagged demo=true. Off by default: fabricated data is never served unmarked.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DeepReport' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/batch-check: post: summary: Batch-check multiple addresses in one call description: 'Trust-report-lite for 1..20 validated addresses in one call. FREE (rate limited). Fabricated demo entries require the explicit ``?demo=true`` opt-in; when any are included the response is flagged ``demo: true`` at the top level and per entry.' operationId: batch_check_v1_batch_check_post parameters: - name: demo in: query required: false schema: type: boolean description: 'Opt-in demo mode: demo addresses resolve to the fabricated illustration entries flagged demo=true. Off by default.' default: false title: Demo description: 'Opt-in demo mode: demo addresses resolve to the fabricated illustration entries flagged demo=true. Off by default.' requestBody: required: true content: application/json: schema: type: object properties: addresses: type: array items: type: string maxLength: 300 minItems: 1 maxItems: 20 description: 1 to 20 merchant addresses or base URLs, each validated like /v1/check. Untracked addresses get an honest unrated report, never an invented score. example: - G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A required: - addresses example: addresses: - G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BatchReport' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/trending: get: summary: See trending active merchants description: 'FREE. Top 5 by 24h score delta; falls back to top 5 by score. Wave 8.9 (the honesty gate): the demo-merchant fallback renders ONLY while the DB holds zero real merchants. When real merchants exist but no score signal has landed yet (cold start after a redeploy), the strip gets an honest empty list and the dashboard says it is gathering 24h signals, instead of inventing names. Wave 18 (The Instant Doctrine): served from the cycle-computed snapshot; on a cold boot it computes ONCE, stores and serves. The path and shape are identical to what they always were. Wave 40 (La Voce): testnet networks and dormant merchants are out of the default strip; ?include_testnet=true and ?include_dormant=true restore them, dormant entries flagged ``dormant: true``. The opt-in variants are computed fresh per request (bounded grouped queries, rate limited); the snapshot serves the default view.' operationId: trending_v1_trending_get parameters: - name: include_testnet in: query required: false schema: type: boolean description: 'Wave 40: testnet/devnet/amoy/sepolia networks are excluded by default; pass ?include_testnet=true to restore them (same entry shape).' default: false title: Include Testnet description: 'Wave 40: testnet/devnet/amoy/sepolia networks are excluded by default; pass ?include_testnet=true to restore them (same entry shape).' - name: include_dormant in: query required: false schema: type: boolean description: 'Wave 40: the default strip shows only merchants with a measurement inside the active window (LEGIT_ACTIVE_WINDOW_DAYS, default 7 days); pass ?include_dormant=true for the full field, dormant entries flagged dormant=true.' default: false title: Include Dormant description: 'Wave 40: the default strip shows only merchants with a measurement inside the active window (LEGIT_ACTIVE_WINDOW_DAYS, default 7 days); pass ?include_dormant=true for the full field, dormant entries flagged dormant=true.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/Trending' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/pulse: get: summary: Read the live x402 network pulse description: 'Real network pulse: the facilitator''s masked live transaction stream, merged with recent on-chain USDC payments from the Wave 8.5 ledger. Wave 18 (The Instant Doctrine): served from the cycle-computed snapshot (refreshed every indexer cycle), so a page load never waits on the facilitator round-trip. Cold boot computes ONCE, stores and serves. Graceful empty list when the facilitator is unreachable. Each transaction carries ``tx_url`` (Wave 3.2): an explorer link when the stream exposes a real on-chain hash, else None. On-chain rows are honestly labeled ``event="onchain_payment"`` and never presented as facilitator settles.' operationId: pulse_v1_pulse_get responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Pulse V1 Pulse Get security: [] /v1/chain-logos: get: summary: Resolve official chain brand tiles description: 'Wave 14 (The Chain Heraldry): network slug -> official tile URL. Static payload (the mapping only changes with a deploy), cacheable for 10 minutes. Unmapped chains (skale-base-mainnet, aws-base, unknown slugs) are simply absent: clients keep their monogram/glyph fallback.' operationId: chain_logos_v1_chain_logos_get responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Chain Logos V1 Chain Logos Get security: [] /v1/networks: get: summary: Check per-chain payment health before routing description: 'Per-chain payment network health from the facilitator, plus honest coverage counts from our own DB. Cached 60s. Graceful empty ``networks`` list when the facilitator is unreachable. Wave 8.6: ``settlement_rails`` counts the facilitator rails (the 6 gasless chains) while ``chains_indexed``/``indexed_chains`` report how many chains the oracle actually indexes merchants on, so the two scopes are never conflated.' operationId: networks_v1_networks_get responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Networks V1 Networks Get security: [] /v1/merchant/{address}/identity: get: summary: Resolve a merchant's on-chain identity across chains description: 'Cross-chain identity for a merchant, from our DB. Graceful 404-shape: ``{"found": false}`` (HTTP 200) when the address is unknown. Categories are best-effort filled from the facilitator''s live identity record ([] when unavailable).' operationId: merchant_identity_v1_merchant__address__identity_get parameters: - name: address in: path required: true schema: type: string title: Address responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Merchant Identity V1 Merchant Address Identity Get '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/arena: get: summary: 'Get arena verdicts: the 24h cross-chain settlement benchmark' description: 'Wave 6 (The Arena): the public cross-chain x402 settlement benchmark. Ranks every chain with any signal (pulse transactions in the last 24h, tracked merchants, or facilitator network health) by real settle count (Wave 8.9: micropayments are a count economy; volume only breaks ties). Cached 60s. Honest by construction: with zero pulse data in the window the narrative says the arena is still gathering its first data and no leader is named. Wave 39 (Il Biglietto da Visita): the optional ?network= slug narrows the benchmark to one chain (cached separately per slug); an unknown slug is an honest 400 listing the valid slugs. Paid: $0.004 on Algorand / $0.005 on Base, via x402 (per call in USDC on algorand-mainnet or base-mainnet; the 402 response lists every active rail). The POST /v1/watch 7-day diagnostic tier pays the same per-call rail price as the 30-day watch.' operationId: arena_v1_arena_get parameters: - name: network in: query required: false schema: anyOf: - type: string maxLength: 64 - type: 'null' description: 'Optional chain slug filter, e.g. ?network=base-mainnet: the benchmark is narrowed to that one network. Omit it for the full cross-chain arena. An unknown slug is an honest 400 listing the slugs currently benchmarked.' title: Network description: 'Optional chain slug filter, e.g. ?network=base-mainnet: the benchmark is narrowed to that one network. Omit it for the full cross-chain arena. An unknown slug is an honest 400 listing the slugs currently benchmarked.' examples: single_network: summary: Benchmark one chain (Base) value: base-mainnet algorand_only: summary: Benchmark Algorand only value: algorand-mainnet responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Arena V1 Arena Get example: generated_at: '2026-01-01T00:00:00+00:00' window_hours: 24 chains: - network: base-mainnet network_name: Base chain_family: evm tx_count_24h: 150 settles_24h: 120 settles_facilitator_24h: 118 settles_onchain_24h: 2 large_inflows_24h: 0 verifies_24h: 30 volume_usdc_24h: 61.25 avg_ticket_usdc_24h: 0.51 merchants_tracked: 8 avg_trust_score: 76.4 latency_p50_ms: 240.0 avg_settlement_time: 2s rank: 1 large_inflows_24h: 0 leader: base-mainnet narrative: 'Base leads x402 settlement: 120 settles totaling 61.25 USDC in 24h.' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' '402': description: 'Payment required: the body is an x402 PaymentRequired document (x402Version, error, resource, accepts) listing the USDC payment offers for every active rail; retry with a payment payload.' content: application/json: schema: type: object properties: x402Version: type: integer error: type: string resource: type: object accepts: type: array items: type: object x-payment-info: price: mode: fixed currency: USD amount: '0.004' protocols: - x402: {} /v1/arena/preview: get: summary: Preview the settlement arena for free description: 'Wave 16: the FREE trimmed arena snapshot for the public homepage. Same groups/structure the dashboard needs to render the arena doors, every indexed chain included and stripped to the rendered fields. Explicitly free tier (never in DEFAULT_PREMIUM_PATHS), cached 60s both in-process and via Cache-Control. Built from the same assembly as the premium /v1/arena so the two views can never disagree about the facts.' operationId: arena_preview_v1_arena_preview_get responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Arena Preview V1 Arena Preview Get security: [] /.well-known/legit: get: summary: Discover LEGIT's endpoints, pricing and rails description: 'Machine-readable service document: endpoints, pricing, rails. Wave 37 (The Aligned Docs): this document must say what production does. The free tier below is served without payment today; the premium tier (compare, arena, history, watch, deep-check) answers 402 with x402 offers at the real prices when the operator lists it in X402_PREMIUM_PATHS. Only rails that exist in the 402 documents are listed (never promise a rail that does not exist).' operationId: wellknown__well_known_legit_get responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Wellknown Well Known Legit Get security: [] /v1/history: get: summary: Pull 30-day score history of one merchant for trend analysis description: 'Thirty days of trust history for one x402 merchant. The daily series combines the surviving daily probe rollups and the raw probes still inside the retention window (sample counts, uptime, latency avg/min/max) with the daily average/min/max trust score and modal grade from LEGIT''s score history. Every day carries a lean "meta" block (coverage, provenance, and gap_kind only when a measured day has no score row) so an agent can tell a rollup-backed day from a raw-only day and a compaction hole from a scoring gap. coverage describes measurement completeness, not score completeness. A day can be coverage: complete with score: absent when probes ran but scoring did not. The current snapshot adds the latest score, grade, probe tier, 7d and 30d uptime and the median latency. One call answers the question every buyer asks before integrating: is this merchant getting better or worse? Untracked addresses get an honest 404; a tracked merchant stale for its probe tier queues an on-demand re-probe, disclosed in the response. Wave 41c (Il Cliente Cieco): ``address`` is optional. A blind client (one that paid and calls with no parameters) gets the history of the rank-1 merchant of the current default ranking, with the additive ``defaults_applied`` field disclosing the choice; when the ranking holds no real merchant no sensible default exists and the parameter stays honestly required (self-documenting 422). Paid: $0.004 on Algorand / $0.005 on Base, via x402 (per call in USDC on algorand-mainnet or base-mainnet; the 402 response lists every active rail). The POST /v1/watch 7-day diagnostic tier pays the same per-call rail price as the 30-day watch.' operationId: history_v1_history_get parameters: - name: address in: query required: false schema: anyOf: - type: string minLength: 1 maxLength: 300 - type: 'null' description: 'Merchant address (or base URL) exactly as tracked by LEGIT, e.g. ?address=ADDR. Optional: when omitted, the rank-1 merchant of the current default ranking is used and the choice is disclosed in defaults_applied.' title: Address description: 'Merchant address (or base URL) exactly as tracked by LEGIT, e.g. ?address=ADDR. Optional: when omitted, the rank-1 merchant of the current default ranking is used and the choice is disclosed in defaults_applied.' examples: algorand_address: summary: 30-day history of one Algorand merchant value: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A responses: '200': description: The merchant's 30-day trust history and current snapshot. content: application/json: schema: type: object title: Response History V1 History Get example: generated_at: '2026-08-10T00:00:00' address: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A name: AlgoPay Gateway network: algorand-mainnet explorer_url: https://allo.info/account/G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A tracked: true window_days: 30 current: score: 97.4 grade: A+ provisional: false tier: settling uptime_pct_7d: 99.8 uptime_pct_30d: 99.5 latency_p50_ms: 118.0 sample_size: 512 last_probe_at: '2026-08-09T23:45:00' series: - day: '2026-08-09' sample_count: 24 ok_count: 24 uptime_pct: 100.0 latency_avg_ms: 121.4 latency_min_ms: 98.0 latency_max_ms: 210.0 score_avg: 97.4 score_min: 97.1 score_max: 97.8 grade: A+ meta: coverage: partial provenance: measurements: raw score: score_table backstop: queued: false note: merchant is fresh for its probe tier '404': description: 'The address is not tracked by LEGIT: an honest 404, never an invented series.' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' '402': description: 'Payment required: the body is an x402 PaymentRequired document (x402Version, error, resource, accepts) listing the USDC payment offers for every active rail; retry with a payment payload.' content: application/json: schema: type: object properties: x402Version: type: integer error: type: string resource: type: object accepts: type: array items: type: object x-payment-info: price: mode: fixed currency: USD amount: '0.004' protocols: - x402: {} /v1/watch: post: summary: Set a webhook-armed 7- or 30-day watch sentinel that fires on grade transitions description: 'Put a sentinel on one x402 merchant for 7 or 30 days. The optional ``days`` field selects the duration tier: 7 (the diagnostic tier) or 30 (the standard, also the default when days is omitted, overridable operator-side via LEGIT_WATCH_TTL_DAYS). The tier is a duration only: the 7-day diagnostic tier pays the same rail price as the 30-day watch; differentiated pricing requires a payments.py change (sealed). After every indexing cycle LEGIT compares the merchant''s freshest trust score and probe outcome against the watch''s recorded state and records the real transitions: grade changes, score drops beyond the LEGIT_WATCH_SCORE_DROP threshold (default 10 points), outages (3 or more probes attempted with zero successes) and recoveries. The returned watch id is the bearer capability: whoever holds it reads status and the newest-first event feed FREE at /v1/watches/{watch_id} and /v1/watches/{watch_id}/events. Pass an https webhook_url to have every event POSTed to your agent the moment it fires (best effort, never retried). Untracked addresses get an honest 404 with a pointer to /v1/check; when the active-watch cap is reached the answer is an honest 409, never a silently dropped watch. Paid: $0.004 on Algorand / $0.005 on Base, via x402 (per call in USDC on algorand-mainnet or base-mainnet; the 402 response lists every active rail). The POST /v1/watch 7-day diagnostic tier pays the same per-call rail price as the 30-day watch.' operationId: create_watch_v1_watch_post requestBody: content: application/json: schema: type: object properties: address: type: string minLength: 1 maxLength: 300 description: Merchant address to put a sentinel on. Untracked addresses are an honest 404 with a /v1/check pointer. example: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A days: type: integer enum: - 7 - 30 description: 'Optional duration tier: 7 (diagnostic) or 30 (standard, the default when omitted). Both tiers pay the same per-call rail price; the tier only sets the watch expiry.' example: 30 webhook_url: type: string maxLength: 2000 description: 'Optional https:// URL: every watch event is POSTed to it the moment it fires (best effort, never retried).' example: https://agent.example/hooks/legit required: - address examples: plain_watch: summary: Watch one merchant, poll the free event feed value: address: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A webhook_watch: summary: Watch one merchant with an https webhook value: address: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A webhook_url: https://agent.example/hooks/legit diagnostic_watch: summary: Watch one merchant for the 7-day diagnostic tier value: address: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A days: 7 required: true responses: '201': description: Successful Response content: application/json: schema: type: object title: Response Create Watch V1 Watch Post example: watch_id: 9f1c2a4b6d8e4f0a1b3c5d7e9f0a1b2c address: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A network: algorand-mainnet created_at: '2026-08-10T00:00:00' expires_at: '2026-09-09T00:00:00' ttl_days: 30 webhook_configured: true initial: score: 97.4 grade: A+ capability: 'The watch id is the bearer capability: read status and events FREE at GET /v1/watches/{watch_id} and GET /v1/watches/{watch_id}/events.' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' '402': description: 'Payment required: the body is an x402 PaymentRequired document (x402Version, error, resource, accepts) listing the USDC payment offers for every active rail; retry with a payment payload.' content: application/json: schema: type: object properties: x402Version: type: integer error: type: string resource: type: object accepts: type: array items: type: object x-payment-info: price: mode: fixed currency: USD amount: '0.004' protocols: - x402: {} /v1/watches/{watch_id}: get: summary: Read watch status free with the bearer watch id description: 'Watch status, expiry and last known state (FREE). Honest 404 for an unknown id, including watches the garbage collector already deleted (LEGIT_WATCH_GC_DAYS past expiry).' operationId: watch_status_v1_watches__watch_id__get parameters: - name: watch_id in: path required: true schema: type: string title: Watch Id responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Watch Status V1 Watches Watch Id Get '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/watches/{watch_id}/events: get: summary: Read the watch event feed, the source of truth description: 'Newest-first transition events of a watch, capped at 200 (FREE). Events stay readable after the watch expires, until the garbage collector deletes the watch and its events LEGIT_WATCH_GC_DAYS past expiry (the read then 404s with the watch).' operationId: watch_events_v1_watches__watch_id__events_get parameters: - name: watch_id in: path required: true schema: type: string title: Watch Id responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Watch Events V1 Watches Watch Id Events Get '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' security: [] /v1/deep-check: post: summary: Run deep-check due diligence on up to 10 addresses description: 'Bulk due diligence for up to 10 x402 merchants in one call. Every tracked address returns the full trust snapshot with the complete parsed score breakdown, a compact 30-day history (daily uptime, average score and modal grade), its rank percentile within its own network, first/last seen timestamps and its probe tier. Untracked addresses are listed honestly under "untracked"; nothing is silently dropped and nothing is invented. Tracked merchants stale for their probe tier queue an on-demand re-probe each. Wave 40 (La Voce, W5): Base merchants with at least one real USDC settle found by LEGIT''s independent eth_getLogs chain scan over the last 7 days carry an additive "evidence" block ({"base_usdc_settles_7d": n, "evidence_source": "independent_chain_scan"}). It is omitted for everyone else: absence of proof is not proof of absence. Metadata only, never a scoring input; a scan failure omits the field, never an error. Paid: $0.004 on Algorand / $0.005 on Base, via x402 (per call in USDC on algorand-mainnet or base-mainnet; the 402 response lists every active rail). The POST /v1/watch 7-day diagnostic tier pays the same per-call rail price as the 30-day watch.' operationId: deep_check_v1_deep_check_post requestBody: content: application/json: schema: type: object properties: addresses: type: array items: type: string maxLength: 300 minItems: 1 maxItems: 10 description: 1 to 10 merchant addresses (LEGIT_DEEP_MAX) for bulk due diligence in one call. Untracked addresses are listed honestly under untracked. example: - G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A - ZQFL2SVFDQDKFAUCCE2WVXH6EF3LRUUJZLKJMDIED56LODOKW23JSKB7NT required: - addresses examples: two_addresses: summary: Deep-check two merchants before routing value: addresses: - G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A - ZQFL2SVFDQDKFAUCCE2WVXH6EF3LRUUJZLKJMDIED56LODOKW23JSKB7NT required: true responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Deep Check V1 Deep Check Post example: generated_at: '2026-08-10T00:00:00' max_addresses: 10 entries: - address: G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A name: AlgoPay Gateway network: algorand-mainnet explorer_url: https://allo.info/account/G7V7U7H6IYRP7BIZO2KV6ODGQPESMMRDCWBYT3GIMNHTNK3VCKWSSKD55A tracked: true score: 97.4 grade: A+ provisional: false breakdown: uptime_pct: 99.8 latency_p50_ms: 118.0 sample_size: 512 provisional: false tier: settling rank_percentile: 92.3 network_size: 14 first_seen: '2026-06-01T12:00:00' last_seen: '2026-08-09T23:45:00' last_probe_at: '2026-08-09T23:45:00' series: - day: '2026-08-09' sample_count: 24 uptime_pct: 100.0 score_avg: 97.4 grade: A+ untracked: - UNKNOWN_ADDRESS '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' '402': description: 'Payment required: the body is an x402 PaymentRequired document (x402Version, error, resource, accepts) listing the USDC payment offers for every active rail; retry with a payment payload.' content: application/json: schema: type: object properties: x402Version: type: integer error: type: string resource: type: object accepts: type: array items: type: object x-payment-info: price: mode: fixed currency: USD amount: '0.004' protocols: - x402: {} /v1/referee/reproduce.py: get: summary: Referee Reproduce Script description: 'The standalone referee reproduction script (stdlib + httpx) as a downloadable artifact: the exact code that re-derives every published flag from the public chain indexer independently. An honest 404 when the deployment ships without the script.' operationId: referee_reproduce_script_v1_referee_reproduce_py_get responses: '200': description: Successful Response content: application/json: schema: {} security: [] /v1/referee: get: summary: Referee Report description: 'The referee audit as JSON: methodology, thresholds, limitations, per-merchant verdicts with their real chain evidence. The top-level ``reproduce_script`` points at the standalone script that re-derives every flag independently.' operationId: referee_report_v1_referee_get responses: '200': description: Successful Response content: application/json: schema: type: object title: Response Referee Report V1 Referee Get security: [] components: schemas: BatchCheckRequest: properties: addresses: items: type: string type: array maxItems: 20 minItems: 1 title: Addresses type: object required: - addresses title: BatchCheckRequest description: 'POST /v1/batch-check body: 1..20 addresses, each validated like /v1/check.' BatchReport: properties: generated_at: type: string title: Generated At results: items: $ref: '#/components/schemas/TrustReportLite' type: array title: Results demo: type: boolean title: Demo default: false type: object required: - generated_at - results title: BatchReport CompareEntry: properties: address: type: string title: Address name: anyOf: - type: string - type: 'null' title: Name score: anyOf: - type: number - type: 'null' title: Score grade: anyOf: - type: string - type: 'null' title: Grade provisional: type: boolean title: Provisional default: false uptime_pct: anyOf: - type: number - type: 'null' title: Uptime Pct latency_p50_ms: anyOf: - type: number - type: 'null' title: Latency P50 Ms sample_size: type: integer title: Sample Size default: 0 settle_count: type: integer title: Settle Count default: 0 network: anyOf: - type: string - type: 'null' title: Network explorer_url: anyOf: - type: string - type: 'null' title: Explorer Url tracked: type: boolean title: Tracked default: true type: object required: - address title: CompareEntry description: TrustReport-like summary of one address in a comparison. CompareResponse: properties: generated_at: type: string title: Generated At entries: items: $ref: '#/components/schemas/CompareEntry' type: array title: Entries winner: anyOf: - type: string - type: 'null' title: Winner rationale: type: string title: Rationale type: object required: - generated_at - entries - rationale title: CompareResponse DeepCheckRequest: properties: addresses: items: type: string type: array title: Addresses type: object required: - addresses title: DeepCheckRequest description: 'POST /v1/deep-check body: up to LEGIT_DEEP_MAX addresses.' DeepReport: properties: address: type: string title: Address name: anyOf: - type: string - type: 'null' title: Name score: type: number title: Score grade: type: string title: Grade breakdown: $ref: '#/components/schemas/ScoreBreakdown' history: items: $ref: '#/components/schemas/ScorePoint' type: array title: History rank: anyOf: - type: integer - type: 'null' title: Rank percentile: type: number title: Percentile default: 0.0 networks_served: items: type: string type: array title: Networks Served generated_at: type: string title: Generated At measurement_window_days: type: integer title: Measurement Window Days default: 30 demo: type: boolean title: Demo default: false type: object required: - address - score - grade - breakdown - generated_at title: DeepReport description: Deep trust report for one merchant (SPEC_V2 contract). HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError Leaderboard: properties: generated_at: type: string title: Generated At entries: items: $ref: '#/components/schemas/LeaderboardEntry' type: array title: Entries networks: items: type: string type: array title: Networks demo: type: boolean title: Demo default: false type: object required: - generated_at - entries title: Leaderboard LeaderboardEntry: properties: rank: type: integer title: Rank rank_global: anyOf: - type: integer - type: 'null' title: Rank Global address: type: string title: Address name: anyOf: - type: string - type: 'null' title: Name display_name: anyOf: - type: string - type: 'null' title: Display Name score: type: number title: Score grade: type: string title: Grade latency_p50_ms: type: number title: Latency P50 Ms uptime_pct: type: number title: Uptime Pct sample_size: type: integer title: Sample Size network: type: string title: Network source: type: string title: Source default: goplausible settle_count: type: integer title: Settle Count default: 0 verify_count: type: integer title: Verify Count default: 0 adoption: type: number title: Adoption default: 0.0 payments_observed: type: boolean title: Payments Observed default: false provisional: type: boolean title: Provisional default: false explorer_url: anyOf: - type: string - type: 'null' title: Explorer Url external_calls_30d: anyOf: - type: integer - type: 'null' title: External Calls 30D external_payers_30d: anyOf: - type: integer - type: 'null' title: External Payers 30D external_demand_source: anyOf: - type: string - type: 'null' title: External Demand Source intel_avg_ticket: anyOf: - type: number - type: 'null' title: Intel Avg Ticket intel_verifies: anyOf: - type: integer - type: 'null' title: Intel Verifies intel_first_seen: anyOf: - type: integer - type: 'null' title: Intel First Seen intel_last_seen: anyOf: - type: integer - type: 'null' title: Intel Last Seen intel_source: anyOf: - type: string - type: 'null' title: Intel Source domain: anyOf: - type: string - type: 'null' title: Domain logo_url: anyOf: - type: string - type: 'null' title: Logo Url settles_7d: anyOf: - type: integer - type: 'null' title: Settles 7D volume_7d: anyOf: - type: number - type: 'null' title: Volume 7D demo: type: boolean title: Demo default: false dormant: type: boolean title: Dormant default: false type: object required: - rank - address - score - grade - latency_p50_ms - uptime_pct - sample_size - network title: LeaderboardEntry ReceiptEntry: properties: txid: type: string title: Txid payer: type: string title: Payer amount_usd: type: number title: Amount Usd ts: type: string title: Ts network: type: string title: Network type: object required: - txid - payer - amount_usd - ts - network title: ReceiptEntry description: 'Wave 46 (L''Arbitro Verificato): one on-chain payment receipt. A real settlement observed on a public chain indexer: the payer, the amount in USD (amount_micro / 1e6), the naive-UTC timestamp, the network slug and the on-chain transaction id as evidence. Never fabricated: only rows the indexer worker''s chain-receipts pass wrote.' ReceiptsResponse: properties: address: type: string title: Address network: type: string title: Network window_days: type: integer title: Window Days default: 30 generated_at: type: string title: Generated At provenance: type: string title: Provenance default: algorand_indexer verified_payers_30d: anyOf: - type: integer - type: 'null' title: Verified Payers 30D top_payer_share_30d: anyOf: - type: number - type: 'null' title: Top Payer Share 30D total_receipts: type: integer title: Total Receipts volume_usd: type: number title: Volume Usd receipts: items: $ref: '#/components/schemas/ReceiptEntry' type: array title: Receipts type: object required: - address - network - generated_at - total_receipts - volume_usd title: ReceiptsResponse description: 'Wave 46 (L''Arbitro Verificato): the 30-day receipt ledger of one tracked merchant (GET /v1/receipts?address=ADDR). ``verified_payers_30d`` is omitted entirely (never null) when no chain scan has covered the merchant yet; ``receipts`` is newest-first and capped at 100 entries while ``total_receipts`` and ``volume_usd`` always cover the full 30-day window. An empty window is an honest empty answer (total_receipts 0, receipts []), never invented rows.' RouteResponse: properties: query: type: string title: Query chosen: anyOf: - $ref: '#/components/schemas/LeaderboardEntry' - type: 'null' alternatives: items: $ref: '#/components/schemas/LeaderboardEntry' type: array title: Alternatives payment_hint: type: object title: Payment Hint demo: type: boolean title: Demo default: false type: object required: - query - payment_hint title: RouteResponse ScoreBreakdown: properties: uptime_pct: type: number title: Uptime Pct latency_p50_ms: type: number title: Latency P50 Ms success_rate: type: number title: Success Rate coherence: type: number title: Coherence sample_size: type: integer title: Sample Size score: type: number title: Score grade: type: string title: Grade explanation: items: type: string type: array title: Explanation adoption: type: number title: Adoption default: 0.0 provisional: type: boolean title: Provisional default: false type: object required: - uptime_pct - latency_p50_ms - success_rate - coherence - sample_size - score - grade title: ScoreBreakdown ScorePoint: properties: ts: type: string title: Ts score: type: number title: Score type: object required: - ts - score title: ScorePoint description: One historical score snapshot. Stats: properties: merchants: type: integer title: Merchants merchants_testnet: type: integer title: Merchants Testnet default: 0 merchants_mainnet: type: integer title: Merchants Mainnet default: 0 merchants_active: type: integer title: Merchants Active default: 0 measurements: type: integer title: Measurements avg_score: type: number title: Avg Score storage: $ref: '#/components/schemas/StorageInfo' type: object required: - merchants - measurements - avg_score - storage title: Stats StorageInfo: properties: path: type: string title: Path persistent: type: boolean title: Persistent db_bytes: anyOf: - type: integer - type: 'null' title: Db Bytes retention_days: anyOf: - type: integer - type: 'null' title: Retention Days tables: anyOf: - type: object - type: 'null' title: Tables tables_bytes: anyOf: - type: string - type: 'null' title: Tables Bytes type: object required: - path - persistent title: StorageInfo description: 'Wave 8.6: verifiable storage facts (resolved SQLite path + whether it lives on the persistent volume). Wave 40 (The Diet): disk observability -- ``db_bytes`` is the on-disk size of the DB file (null when unreadable) and ``retention_days`` the raw-measurement retention window actually in force (older history survives as daily rollups, not raw rows). Wave 41 (La Bellezza, W6): growth introspection -- ``tables`` maps each main table to its real row count (plus ``bytes`` when SQLite''s dbstat virtual table is compiled in). ``tables_bytes`` names the bytes source ("dbstat") or is null, in which case entries honestly carry row counts only. Wave 43 (La Grande Dieta, D5): table entries additionally carry ``index_bytes`` (that table''s index pages via dbstat, additive) when dbstat is available -- ``bytes`` alone under-reported the real on-disk cost per table by 1.4x-2.9x.' Trending: properties: generated_at: type: string title: Generated At trending: items: $ref: '#/components/schemas/LeaderboardEntry' type: array title: Trending demo: type: boolean title: Demo default: false type: object required: - generated_at - trending title: Trending TrustReport: properties: address: type: string title: Address name: anyOf: - type: string - type: 'null' title: Name display_name: anyOf: - type: string - type: 'null' title: Display Name score: type: number title: Score grade: type: string title: Grade breakdown: $ref: '#/components/schemas/ScoreBreakdown' generated_at: type: string title: Generated At anchored_tx: anyOf: - type: string - type: 'null' title: Anchored Tx provisional: type: boolean title: Provisional default: false explorer_url: anyOf: - type: string - type: 'null' title: Explorer Url external_calls_30d: anyOf: - type: integer - type: 'null' title: External Calls 30D external_payers_30d: anyOf: - type: integer - type: 'null' title: External Payers 30D external_demand_source: anyOf: - type: string - type: 'null' title: External Demand Source intel_avg_ticket: anyOf: - type: number - type: 'null' title: Intel Avg Ticket intel_verifies: anyOf: - type: integer - type: 'null' title: Intel Verifies intel_first_seen: anyOf: - type: integer - type: 'null' title: Intel First Seen intel_last_seen: anyOf: - type: integer - type: 'null' title: Intel Last Seen intel_source: anyOf: - type: string - type: 'null' title: Intel Source probe_queue: anyOf: - type: object - type: 'null' title: Probe Queue evidence: anyOf: - type: object - type: 'null' title: Evidence tier: anyOf: - type: string - type: 'null' title: Tier routing_confidence: anyOf: - type: string - type: 'null' title: Routing Confidence verified_payers_30d: anyOf: - type: integer - type: 'null' title: Verified Payers 30D receipts_provenance: anyOf: - type: string - type: 'null' title: Receipts Provenance top_payer_share_30d: anyOf: - type: number - type: 'null' title: Top Payer Share 30D referee_flag: anyOf: - type: boolean - type: 'null' title: Referee Flag referee_verdict: anyOf: - type: string - type: 'null' title: Referee Verdict type: object required: - address - score - grade - breakdown - generated_at title: TrustReport TrustReportLite: properties: address: type: string title: Address score: type: number title: Score grade: type: string title: Grade latency_p50_ms: type: number title: Latency P50 Ms uptime_pct: type: number title: Uptime Pct demo: type: boolean title: Demo default: false type: object required: - address - score - grade - latency_p50_ms - uptime_pct title: TrustReportLite description: Compact per-address result inside a BatchReport. ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type type: object required: - loc - msg - type title: ValidationError WatchCreateRequest: properties: address: type: string maxLength: 300 minLength: 1 title: Address days: anyOf: - type: integer - type: 'null' title: Days webhook_url: anyOf: - type: string maxLength: 2000 - type: 'null' title: Webhook Url type: object required: - address title: WatchCreateRequest description: 'POST /v1/watch body: one tracked address, an optional duration tier and an optional https webhook. ``days`` selects the duration tier (7-day diagnostic or 30-day standard; omitted means the LEGIT_WATCH_TTL_DAYS default of 30). The tier only sets expires_at: the 7-day diagnostic tier pays the same rail price as the 30-day watch; differentiated pricing requires a payments.py change (sealed).'