{"openapi":"3.1.0","info":{"title":"Agent Preflight APIs","version":"1.0.0","description":"Pre-action x402 payment checks, purchase shortlisting, and deterministic email HTML validation for AI agents.","contact":{"name":"Email Preflight API","email":"dillonbordeleau@gmail.com","url":"https://email-preflight-api.vercel.app"},"x-guidance":"Use POST /api/x402-shortlist to search the official Coinbase Bazaar endpoint, preserve Bazaar search rank, probe at most three candidates through the hardened unpaid probe, and return only offers that pass live resource, amount, network, payee, and invocation checks. Use GET /api/x402-preflight/sample before POST /api/x402-preflight, or POST /api/preflight before sending marketing email HTML."},"externalDocs":{"description":"Agent installation and usage guide","url":"https://email-preflight-api.vercel.app/SKILL.md"},"servers":[{"url":"https://email-preflight-api.vercel.app"}],"paths":{"/api/preflight":{"post":{"operationId":"preflightEmailHtml","summary":"Preflight email HTML before sending","description":"Returns deterministic source checks without storing the submitted HTML or calling an LLM.","tags":["newsletter","email-marketing","pre-send","email-validation","gmail-clipping","marketing-agent","accessibility"],"security":[{"x402Payment":[]}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.010000"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"html":{"type":"string","minLength":1,"maxLength":512000,"description":"One complete email HTML source document, up to 512,000 UTF-8 bytes. Do not include subscriber data."}},"required":["html"],"additionalProperties":false},"example":{"html":"<html><body><a href=\"https://news.example.org/unsubscribe\">Unsubscribe</a></body></html>"}}}},"responses":{"200":{"description":"Deterministic preflight report","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"service":{"type":"string","const":"email-preflight"},"version":{"type":"string"},"clipping":{"type":"object","properties":{"risk":{"type":"string","enum":["low","warning","high"]},"htmlBytes":{"type":"integer","minimum":0},"thresholdBytes":{"type":"integer","minimum":0},"headroomBytes":{"type":"integer"},"percentOfThreshold":{"type":"number","minimum":0}},"required":["risk","htmlBytes","thresholdBytes","headroomBytes","percentOfThreshold"],"additionalProperties":false},"metrics":{"type":"object","properties":{"links":{"type":"integer","minimum":0},"images":{"type":"integer","minimum":0},"imagesWithoutAlt":{"type":"integer","minimum":0},"commentBytes":{"type":"integer","minimum":0},"styleBlockBytes":{"type":"integer","minimum":0},"scriptBlockBytes":{"type":"integer","minimum":0},"inlineStyleBytes":{"type":"integer","minimum":0},"embeddedBase64ImageBytes":{"type":"integer","minimum":0}},"required":["links","images","imagesWithoutAlt","commentBytes","styleBlockBytes","scriptBlockBytes","inlineStyleBytes","embeddedBase64ImageBytes"],"additionalProperties":false},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["high","medium","low"]},"code":{"type":"string","enum":["gmail_clipping_likely","gmail_clipping_headroom_low","image_alt_missing","unsafe_link_scheme","placeholder_link","script_block_present","unsubscribe_reference_not_found","embedded_base64_image"]},"message":{"type":"string"},"count":{"type":"integer","minimum":1}},"required":["severity","code","message","count"],"additionalProperties":false}},"limitations":{"type":"array","items":{"type":"string"}}},"required":["ok","service","version","clipping","metrics","issues","limitations"],"additionalProperties":false},"example":{"ok":true,"service":"email-preflight","version":"2026-07-31","clipping":{"risk":"low","htmlBytes":88,"thresholdBytes":102400,"headroomBytes":102312,"percentOfThreshold":0.1},"metrics":{"links":1,"images":0,"imagesWithoutAlt":0,"commentBytes":0,"styleBlockBytes":0,"scriptBlockBytes":0,"inlineStyleBytes":0,"embeddedBase64ImageBytes":0},"issues":[],"limitations":["This is deterministic source analysis, not inbox-placement or rendering testing.","Merge tags and platform-added footer content can change final message size.","A missing issue does not guarantee compatibility with every email client."]}}}},"400":{"description":"Invalid JSON or HTML input"},"402":{"description":"Payment Required"},"413":{"description":"HTML input exceeds the size limit"}}}},"/api/x402-preflight":{"post":{"operationId":"preflightX402Endpoint","summary":"Inspect an unpaid x402 v2 challenge before paying","description":"Pre-action check for AI agents: inspect an unfamiliar live x402 v2 challenge immediately before purchase. Verify price, network, payee, resource binding, timeout, and Bazaar metadata without paying the target or forwarding credentials. POST probes send only a fixed empty JSON object; callers cannot supply target request content.","tags":["x402","payment-preflight","pre-action-check","agent-procurement","agent-safety","endpoint-validation","ssrf-protection"],"security":[{"x402Payment":[]}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.003000"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"description":"Public HTTPS x402 endpoint. Credentials, fragments, nonstandard ports, and local/private/reserved destinations are rejected."},"method":{"type":"string","enum":["GET","HEAD","POST"],"default":"POST"},"expected":{"type":"object","properties":{"network":{"type":"string","minLength":1},"payTo":{"type":"string","minLength":1},"maxAmountUsd":{"type":"number","minimum":0,"maximum":1000000}},"additionalProperties":false}},"required":["url"],"additionalProperties":false},"example":{"url":"https://merchant.example/api/paid-resource","method":"POST","expected":{"network":"eip155:8453","maxAmountUsd":0.01}}}}},"responses":{"200":{"description":"Sanitized unpaid-probe report","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"service":{"type":"string","const":"x402-endpoint-preflight"},"version":{"type":"string"},"target":{"type":"object"},"probe":{"type":"object"},"summary":{"type":"object"},"challenge":{"oneOf":[{"type":"object"},{"type":"null"}]},"findings":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["severity","code","path","message"],"additionalProperties":false}},"privacy":{"type":"object"},"limitations":{"type":"array","items":{"type":"string"}}},"required":["ok","service","version","target","probe","summary","challenge","findings","privacy","limitations"],"additionalProperties":false},"example":{"ok":true,"service":"x402-endpoint-preflight","version":"2026-07-31","target":{"url":"https://merchant.example/api/paid-resource","method":"POST"},"probe":{"status":"completed","httpStatus":402,"redirectsFollowed":0,"responseBodyRead":false},"summary":{"compatible":true,"findingCounts":{"error":0,"warning":0,"info":0},"acceptsCount":1},"challenge":{"x402Version":2,"resourceUrl":"https://merchant.example/api/paid-resource","accepts":[{"scheme":"exact","network":"eip155:8453","amountAtomic":"3000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x1111111111111111111111111111111111111111","maxTimeoutSeconds":60,"amountUsd":"0.003","amountUsdBasis":"USDC (6 decimals)"}],"bazaar":{"present":true,"inputMetadataPresent":true,"outputMetadataPresent":true}},"findings":[],"privacy":{"retained":false,"rawResponseReturned":false,"credentialsForwarded":false},"limitations":["This unpaid probe does not verify settlement, merchant identity, or endpoint quality."]}}}},"400":{"description":"Invalid preflight request"},"402":{"description":"Payment Required"},"413":{"description":"Request body exceeds the size limit"}}}},"/api/x402-preflight/sample":{"get":{"operationId":"getX402EndpointPreflightSample","summary":"Preview a complete x402 preflight response for free","description":"Returns a static request and response example. It contacts no target and requires no payment.","tags":["x402","payment-preflight","pre-action-check","agent-procurement","agent-safety","endpoint-validation","ssrf-protection"],"security":[],"responses":{"200":{"description":"Static sample with paid endpoint and price","content":{"application/json":{"example":{"sample":true,"paidEndpoint":"https://email-preflight-api.vercel.app/api/x402-preflight","priceUsd":"0.003","request":{"url":"https://merchant.example/api/paid-resource","method":"POST","expected":{"network":"eip155:8453","maxAmountUsd":0.01}},"response":{"ok":true,"service":"x402-endpoint-preflight","version":"2026-07-31","target":{"url":"https://merchant.example/api/paid-resource","method":"POST"},"probe":{"status":"completed","httpStatus":402,"redirectsFollowed":0,"responseBodyRead":false},"summary":{"compatible":true,"findingCounts":{"error":0,"warning":0,"info":0},"acceptsCount":1},"challenge":{"x402Version":2,"resourceUrl":"https://merchant.example/api/paid-resource","accepts":[{"scheme":"exact","network":"eip155:8453","amountAtomic":"3000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x1111111111111111111111111111111111111111","maxTimeoutSeconds":60,"amountUsd":"0.003","amountUsdBasis":"USDC (6 decimals)"}],"bazaar":{"present":true,"inputMetadataPresent":true,"outputMetadataPresent":true}},"findings":[],"privacy":{"retained":false,"rawResponseReturned":false,"credentialsForwarded":false},"limitations":["This unpaid probe does not verify settlement, merchant identity, or endpoint quality."]}}}}}}}},"/api/x402-shortlist":{"post":{"operationId":"shortlistX402Purchase","summary":"Create a live-checked x402 purchase shortlist","description":"Find a small Coinbase Bazaar candidate set for one needed capability, live-probe at most three unpaid x402 challenges through the hardened SSRF-resistant preflight, reject unsafe, inconsistent, stale, filtered, or uninvocable offers, and return one purchase-ready recommendation plus alternates and exact request skeletons. No target payment is made.","tags":["x402","purchase-shortlist","agent-procurement","coinbase-bazaar","live-challenge-check","agent-tools"],"security":[{"x402Payment":[]}],"x-live":true,"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.005000"},"network":"eip155:8453","asset":"USDC","payTo":"0x8331051Bb822536d5e228433e7A5486f7169064D","protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"need":{"type":"string","minLength":1,"maxLength":200,"description":"Short natural-language description of the capability the agent needs. Whitespace-only values are rejected."},"maxPriceUsd":{"type":"number","minimum":0.000001,"maximum":100,"multipleOf":0.000001,"description":"Optional maximum recognized USDC price in USD, with at most six decimal places."},"network":{"type":"string","pattern":"^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$","description":"Optional CAIP-2 payment network filter."},"method":{"type":"string","enum":["GET","HEAD","POST"],"description":"Optional HTTP method filter. The service supports only methods handled by the hardened unpaid probe."}},"required":["need"],"additionalProperties":false},"example":{"need":"current weather for a city","maxPriceUsd":0.01,"network":"eip155:8453","method":"GET"}}}},"responses":{"200":{"description":"Purchase-ready recommendation, alternates, disqualifications, or an honest partial/unavailable result","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"service":{"type":"string","const":"x402-purchase-shortlist"},"version":{"type":"string"},"live":{"type":"boolean","const":true},"status":{"type":"string","enum":["ready","partial","no_match","partial_no_match","search_unavailable"]},"request":{"type":"object","properties":{"need":{"type":"string","minLength":1,"maxLength":200,"description":"Short natural-language description of the capability the agent needs. Whitespace-only values are rejected."},"maxPriceUsd":{"type":"number","minimum":0.000001,"maximum":100,"multipleOf":0.000001,"description":"Optional maximum recognized USDC price in USD, with at most six decimal places."},"network":{"type":"string","pattern":"^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$","description":"Optional CAIP-2 payment network filter."},"method":{"type":"string","enum":["GET","HEAD","POST"],"description":"Optional HTTP method filter. The service supports only methods handled by the hardened unpaid probe."}},"required":["need"],"additionalProperties":false},"search":{"type":"object","properties":{"provider":{"type":"string","const":"Coinbase CDP Bazaar"},"endpoint":{"type":"string","pattern":"^https://"},"status":{"type":"string"},"resultCount":{"type":"integer","minimum":0},"consideredCount":{"type":"integer","minimum":0,"maximum":6},"partialResults":{"type":"boolean"},"searchMethod":{"oneOf":[{"type":"string"},{"type":"null"}]},"rankingNotice":{"type":"string"}},"required":["provider","endpoint","status","resultCount","consideredCount","partialResults","searchMethod","rankingNotice"],"additionalProperties":false},"checks":{"type":"object","properties":{"candidateLimit":{"type":"integer","const":6},"probeLimit":{"type":"integer","const":3},"probeDeadlineMs":{"type":"integer","minimum":1},"probedCount":{"type":"integer","minimum":0,"maximum":3},"selectionPolicy":{"type":"string"}},"required":["candidateLimit","probeLimit","probeDeadlineMs","probedCount","selectionPolicy"],"additionalProperties":false},"recommendation":{"oneOf":[{"type":"object","properties":{"rank":{"type":"integer","minimum":1,"maximum":3},"searchRank":{"type":"integer","minimum":1,"maximum":6},"resource":{"type":"string","pattern":"^https://"},"description":{"oneOf":[{"type":"string"},{"type":"null"}]},"declaredServiceName":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Unverified service name declared in Bazaar metadata; not merchant identity."},"bazaarLastUpdated":{"oneOf":[{"type":"string"},{"type":"null"}]},"method":{"type":"string","enum":["GET","HEAD","POST"]},"price":{"type":"object","properties":{"scheme":{"type":"string","const":"exact"},"network":{"type":"string"},"amountAtomic":{"type":"string","pattern":"^[1-9][0-9]*$"},"amountUsd":{"type":"string","pattern":"^[0-9]+(?:\\.[0-9]+)?$"},"amountUsdBasis":{"type":"string"},"asset":{"type":"string"},"payTo":{"type":"string"}},"required":["scheme","network","amountAtomic","amountUsd","amountUsdBasis","asset","payTo"],"additionalProperties":false},"request":{"type":"object","properties":{"method":{"type":"string","enum":["GET","HEAD","POST"]},"url":{"type":"string","pattern":"^https://"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"query":{"type":"object"},"body":{"type":"object"}},"required":["method","url","headers"],"additionalProperties":false},"liveCheck":{"type":"object","properties":{"status":{"type":"string","const":"passed"},"httpStatus":{"type":"integer","const":402},"resourceMatched":{"type":"boolean","const":true},"paymentMatched":{"type":"boolean","const":true},"bazaarInvocationMetadataPresent":{"type":"boolean","const":true}},"required":["status","httpStatus","resourceMatched","paymentMatched","bazaarInvocationMetadataPresent"],"additionalProperties":false}},"required":["rank","searchRank","resource","description","declaredServiceName","bazaarLastUpdated","method","price","request","liveCheck"],"additionalProperties":false},{"type":"null"}]},"alternates":{"type":"array","maxItems":2,"items":{"type":"object","properties":{"rank":{"type":"integer","minimum":1,"maximum":3},"searchRank":{"type":"integer","minimum":1,"maximum":6},"resource":{"type":"string","pattern":"^https://"},"description":{"oneOf":[{"type":"string"},{"type":"null"}]},"declaredServiceName":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Unverified service name declared in Bazaar metadata; not merchant identity."},"bazaarLastUpdated":{"oneOf":[{"type":"string"},{"type":"null"}]},"method":{"type":"string","enum":["GET","HEAD","POST"]},"price":{"type":"object","properties":{"scheme":{"type":"string","const":"exact"},"network":{"type":"string"},"amountAtomic":{"type":"string","pattern":"^[1-9][0-9]*$"},"amountUsd":{"type":"string","pattern":"^[0-9]+(?:\\.[0-9]+)?$"},"amountUsdBasis":{"type":"string"},"asset":{"type":"string"},"payTo":{"type":"string"}},"required":["scheme","network","amountAtomic","amountUsd","amountUsdBasis","asset","payTo"],"additionalProperties":false},"request":{"type":"object","properties":{"method":{"type":"string","enum":["GET","HEAD","POST"]},"url":{"type":"string","pattern":"^https://"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"query":{"type":"object"},"body":{"type":"object"}},"required":["method","url","headers"],"additionalProperties":false},"liveCheck":{"type":"object","properties":{"status":{"type":"string","const":"passed"},"httpStatus":{"type":"integer","const":402},"resourceMatched":{"type":"boolean","const":true},"paymentMatched":{"type":"boolean","const":true},"bazaarInvocationMetadataPresent":{"type":"boolean","const":true}},"required":["status","httpStatus","resourceMatched","paymentMatched","bazaarInvocationMetadataPresent"],"additionalProperties":false}},"required":["rank","searchRank","resource","description","declaredServiceName","bazaarLastUpdated","method","price","request","liveCheck"],"additionalProperties":false}},"disqualifications":{"type":"array","maxItems":7,"items":{"type":"object","properties":{"searchRank":{"oneOf":[{"type":"integer","minimum":1},{"type":"null"}]},"resource":{"oneOf":[{"type":"string","pattern":"^https://"},{"type":"null"}]},"stage":{"type":"string","enum":["search","catalog","probe"]},"code":{"type":"string"},"message":{"type":"string"}},"required":["searchRank","resource","stage","code","message"],"additionalProperties":false}},"privacy":{"type":"object"},"limitations":{"type":"array","items":{"type":"string"}}},"required":["ok","service","version","live","status","request","search","checks","recommendation","alternates","disqualifications","privacy","limitations"],"additionalProperties":false},"example":{"ok":true,"service":"x402-purchase-shortlist","version":"2026-07-31","live":true,"status":"partial","request":{"need":"current weather for a city","maxPriceUsd":0.01,"network":"eip155:8453","method":"GET"},"search":{"provider":"Coinbase CDP Bazaar","endpoint":"https://api.cdp.coinbase.com/platform/v2/x402/discovery/search","status":"completed","resultCount":4,"consideredCount":4,"partialResults":true,"searchMethod":"vector","rankingNotice":"Search rank is supplied by Coinbase Bazaar from retrieval relevance and service-quality signals; those signals are not independently verified here."},"checks":{"candidateLimit":6,"probeLimit":3,"probeDeadlineMs":3500,"probedCount":3,"selectionPolicy":"Preserve Coinbase Bazaar search rank; recommend the first candidate that passes every local deterministic live check."},"recommendation":{"rank":1,"searchRank":2,"resource":"https://weather.example/api/current?city=Toronto","description":"Current weather observations for a requested city.","declaredServiceName":"Example Weather API","bazaarLastUpdated":"2026-07-31T12:00:00Z","method":"GET","price":{"scheme":"exact","network":"eip155:8453","amountAtomic":"5000","amountUsd":"0.005","amountUsdBasis":"USDC (6 decimals)","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x1111111111111111111111111111111111111111"},"request":{"method":"GET","url":"https://weather.example/api/current?city=Toronto","headers":{"Accept":"application/json"},"query":{"city":"Toronto"}},"liveCheck":{"status":"passed","httpStatus":402,"resourceMatched":true,"paymentMatched":true,"bazaarInvocationMetadataPresent":true}},"alternates":[],"disqualifications":[{"searchRank":1,"resource":"https://stale.example/api/weather","stage":"probe","code":"bazaar_payment_live_mismatch","message":"Bazaar amount, network, asset, or payee metadata is stale or inconsistent with the live challenge."}],"privacy":{"retained":false,"rawUpstreamBodiesReturned":false,"credentialsForwarded":false,"callerHeadersForwarded":false,"callerBodyForwarded":false,"targetPaymentsMade":false},"limitations":["Coinbase Bazaar supplies search rank; this service adds deterministic live checks, not an independent quality score.","A recommendation does not establish merchant identity, settlement success, endpoint quality, safety, endorsement, or future behavior."]}}}},"400":{"description":"Invalid shortlist request"},"402":{"description":"Payment Required after valid input"},"413":{"description":"Request body exceeds the 8 KB limit"}}}},"/api/x402-shortlist/sample":{"get":{"operationId":"getX402PurchaseShortlistSample","summary":"View a static x402 shortlist response for free","description":"Returns a static example. It performs no Bazaar search, target probe, or payment.","tags":["x402","purchase-shortlist","agent-procurement","coinbase-bazaar","live-challenge-check","agent-tools"],"security":[],"x-live":true,"responses":{"200":{"description":"Static shortlist sample","content":{"application/json":{"example":{"sample":true,"live":true,"paidEndpoint":"https://email-preflight-api.vercel.app/api/x402-shortlist","priceUsd":"0.005","network":"eip155:8453","request":{"need":"current weather for a city","maxPriceUsd":0.01,"network":"eip155:8453","method":"GET"},"response":{"ok":true,"service":"x402-purchase-shortlist","version":"2026-07-31","live":true,"status":"partial","request":{"need":"current weather for a city","maxPriceUsd":0.01,"network":"eip155:8453","method":"GET"},"search":{"provider":"Coinbase CDP Bazaar","endpoint":"https://api.cdp.coinbase.com/platform/v2/x402/discovery/search","status":"completed","resultCount":4,"consideredCount":4,"partialResults":true,"searchMethod":"vector","rankingNotice":"Search rank is supplied by Coinbase Bazaar from retrieval relevance and service-quality signals; those signals are not independently verified here."},"checks":{"candidateLimit":6,"probeLimit":3,"probeDeadlineMs":3500,"probedCount":3,"selectionPolicy":"Preserve Coinbase Bazaar search rank; recommend the first candidate that passes every local deterministic live check."},"recommendation":{"rank":1,"searchRank":2,"resource":"https://weather.example/api/current?city=Toronto","description":"Current weather observations for a requested city.","declaredServiceName":"Example Weather API","bazaarLastUpdated":"2026-07-31T12:00:00Z","method":"GET","price":{"scheme":"exact","network":"eip155:8453","amountAtomic":"5000","amountUsd":"0.005","amountUsdBasis":"USDC (6 decimals)","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x1111111111111111111111111111111111111111"},"request":{"method":"GET","url":"https://weather.example/api/current?city=Toronto","headers":{"Accept":"application/json"},"query":{"city":"Toronto"}},"liveCheck":{"status":"passed","httpStatus":402,"resourceMatched":true,"paymentMatched":true,"bazaarInvocationMetadataPresent":true}},"alternates":[],"disqualifications":[{"searchRank":1,"resource":"https://stale.example/api/weather","stage":"probe","code":"bazaar_payment_live_mismatch","message":"Bazaar amount, network, asset, or payee metadata is stale or inconsistent with the live challenge."}],"privacy":{"retained":false,"rawUpstreamBodiesReturned":false,"credentialsForwarded":false,"callerHeadersForwarded":false,"callerBodyForwarded":false,"targetPaymentsMade":false},"limitations":["Coinbase Bazaar supplies search rank; this service adds deterministic live checks, not an independent quality score.","A recommendation does not establish merchant identity, settlement success, endpoint quality, safety, endorsement, or future behavior."]}}}}}}}}},"components":{"securitySchemes":{"x402Payment":{"type":"apiKey","in":"header","name":"PAYMENT-SIGNATURE","description":"x402 v2 payment authorization. Price is declared per operation in x-payment-info."}}}}