# invoices.org — Full API Documentation > Document mailing gateway. Send physical mail via a single API call with x402 payment. ## Overview invoices.org accepts a PDF document, a recipient address, and a return address. It prints the document and mails it via USPS. Payment is handled via the x402 protocol — no accounts, no API keys, no signup required. Base URL: https://invoices.org ## Authentication No traditional authentication. Payment via x402 protocol (USDC on Base network). The x402 payment flow is built into the API: - Requests without payment receive HTTP 402 with payment requirements - Requests with valid x402 payment headers are processed immediately If you use the @x402/fetch library, payment is handled automatically. ## Endpoint ### POST /api/mail Mail a PDF document to a physical address. #### Two-Round Flow **Round 1 — Upload and Get Quote (no payment):** Request: ``` POST /api/mail Content-Type: application/json { "pdf": "", "to": { "name": "Jane Smith", "address_line1": "123 Main St", "address_line2": "Apt 4B", "city": "Portland", "state": "OR", "postcode": "97201", "country": "US" }, "from": { "name": "Acme Corp", "address_line1": "456 Oak Ave", "city": "San Francisco", "state": "CA", "postcode": "94107", "country": "US" }, "use_type": "operational" } ``` Response (HTTP 402): ```json { "transaction_id": "INV-20260222-001", "amount": "3.00", "currency": "USDC", "policy": "https://invoices.org/policy/no-refunds", "policy_summary": "No refunds. Payment confirms acceptance of terms.", "accepts": { "scheme": "exact", "network": "eip155:8453", "maxAmountRequired": "3.00", "resource": "/api/mail", "description": "Physical document mailing via invoices.org", "mimeType": "application/json", "payTo": "0x...", "maxTimeoutSeconds": 300, "outputSchema": null } } ``` The PDF is stored server-side for 30 minutes, keyed by the transaction ID. **Round 2 — Pay and Fulfill:** Request: ``` POST /api/mail X-PAYMENT: X-Transaction-ID: INV-20260222-001 ``` No body required — the PDF was stored in Round 1. Response (HTTP 200): ```json { "job_id": "INV-20260222-001", "status": "queued", "provider_ref": "ltr_abc123", "estimated_delivery": "2026-03-01" } ``` #### Request Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | pdf | string | Yes | Base64-encoded PDF document (max 5 pages) | | to.name | string | Yes | Recipient full name | | to.address_line1 | string | Yes | Street address | | to.address_line2 | string | No | Apartment, suite, etc. | | to.city | string | Yes | City | | to.state | string | Yes | State/province | | to.postcode | string | Yes | ZIP/postal code | | to.country | string | Yes | ISO country code (e.g., "US") | | from.name | string | Yes | Sender name (printed as return address) | | from.address_line1 | string | Yes | Sender street address | | from.address_line2 | string | No | Apartment, suite, etc. | | from.city | string | Yes | Sender city | | from.state | string | Yes | Sender state/province | | from.postcode | string | Yes | Sender ZIP/postal code | | from.country | string | Yes | Sender ISO country code | | use_type | string | No | "operational" (default) or "marketing" | #### Response Fields | Field | Type | Description | |-------|------|-------------| | job_id | string | Unique job identifier (same as transaction_id) | | status | string | "queued", "sent", "delivered", or "failed" | | provider_ref | string | Fulfillment provider reference ID | | estimated_delivery | string | ISO date of estimated delivery | #### Idempotency The transaction ID ensures idempotency. Re-sending Round 2 with the same transaction ID returns the same result without re-charging or re-mailing. ## Constraints - **Maximum 5 pages** per document. Documents over 5 pages are rejected. - PDF must be valid and base64-encoded. - Both `to` and `from` addresses are required. - US domestic mail only (international support planned). ## Error Codes | HTTP | Code | Description | |------|------|-------------| | 400 | INVALID_BODY | Request body is not valid JSON | | 400 | MISSING_FIELDS | Required fields (pdf, to, from) missing | | 400 | INCOMPLETE_ADDRESS | Address missing required fields | | 400 | INVALID_PDF | PDF is not valid base64 | | 400 | EMPTY_PDF | PDF decodes to zero bytes | | 400 | US_ONLY | International mail not supported — both addresses must be US | | 400 | INVALID_POSTCODE | Postcode is not a valid US ZIP (5 digits or ZIP+4) | | 402 | PAYMENT_REQUIRED | No x402 payment — includes quote and payment requirements | | 403 | MODERATION_REJECTED | Document failed content review | | 404 | TX_NOT_FOUND | Transaction ID not found or expired | | 410 | TX_EXPIRED | Transaction expired (30-minute window) | | 502 | FULFILLMENT_ERROR | Print-and-mail provider error | ## Content Moderation All documents are automatically screened before a quote is issued. **Approved content:** - Invoices, bills, statements, receipts - Business letters, formal correspondence - Marketing and promotional material (product offers, sales, coupons, catalogs) - Personal letters and correspondence - Legal notices, contracts, agreements - Operational notices, account updates **Rejected content:** - Threats of violence, extortion, blackmail - Harassment or stalking - Hate speech targeting race, religion, ethnicity, gender, sexuality - Fraud, scams, impersonation of government officials or agencies - Social engineering (fake password resets, fake account notices) - Political campaign material, voter targeting, political advocacy - Disinformation, fake news, fabricated claims presented as fact Documents that fail moderation receive HTTP 403 with no payment option. ## Pricing $3.00 USD per letter, paid in USDC on Base network via x402. Price covers: printing (B&W, single-sided), enveloping, USPS standard postage, content screening, and service margin. ## Policies - **No Refunds.** All payments are final once a document is submitted for mailing. Our obligation is fulfilled when the document is submitted to our print-and-mail provider. Postal delivery is handled by USPS and is outside our control. - Full policy: https://invoices.org/policy/no-refunds ## Agent Credentials (Optional) invoices.org accepts **BBS+ zero-knowledge proof credentials** issued by QueryZero. Credentials are optional — anonymous payments always work. But credentials enable: - Transaction attribution to your verified agent identity - Payment history tied to your DID (reputation building) - Wallet match verification (disclosed wallet matches payment wallet) ### How It Works 1. The 402 response includes discovery headers telling you what credentials are accepted: - `X-Accept-Credentials: QueryZeroAgentIdentity` - `X-Credential-Request: {"required":["walletAddress"],"desired":["agentName"],"schema":"..."}` 2. If you have a QueryZero agent credential, derive a ZK proof disclosing at minimum `walletAddress` (index 1) 3. Add the proof as a header on your payment request: ``` X-Agent-Credential: ``` 4. On successful payment, the response includes `identity_attributed: true` if your credential wallet matched your payment wallet ### Proof Payload Format The `X-Agent-Credential` header value is a base64-encoded JSON object: ```json { "proof": "", "header": "", "disclosedMessages": ["walletAddress=0x..."], "disclosedMessageIndexes": [1], "publicKey": "", "schema": "https://queryzero.net/api/v1/schemas/agent-identity-v1", "ciphersuite": "BLS12-381-SHA-256" } ``` ### Getting a Credential Get a QueryZero agent credential first: https://queryzero.net/llms.txt (see "Agent Credentials" section) ## x402 Protocol Learn more about x402 payment: https://www.x402.org Client libraries: - @x402/fetch (npm) — wraps fetch() with automatic x402 payment - @x402/evm (npm) — EVM payment signing ## Provider Built by eSoup (https://esoup.net).