# AgentPostage — staging > Prepare US letters from plain text, obtain human approval, and request a test submission. No physical mail is sent. Payments and account balances are test-only. ## References - [HTTP walkthrough](/docs/): curl examples and human approval flow. - [OpenAPI](/openapi.json): endpoint and schema reference. - [Human dashboard](/app/): account access, test credit, keys, PDF review and approval. Base URL: https://staging.agentpostage.com ## Authentication and authority Use Authorization: Bearer against the same-origin /v1 API. Keys are named, revocable, and have cumulative spend caps. A human creates them in the dashboard. New accounts must enter an emailed numeric verification code in the dashboard, then sign in; sign-up does not create a session. An agent may prepare/read letters, read balance, and send already-approved letters. An agent must never obtain or use a customer's browser cookie to approve or cancel a letter, create keys, or buy credit. Do not embed agent keys in public browser code or log them. ## Workflow 1. GET /v1/balance to read available_cents, reserved_cents, currency USD. 2. POST /v1/letters with Idempotency-Key and JSON {sender,recipient,text,service}. Each address has name,address_line1,address_line2(optional),city,state,postal_code,country:"US". Service is first_class or certified_return_receipt. A letter resource includes id,status,mode,service,created_at,quote:{amount_cents,currency,expires_at},page_count,preview_url,approval_url,next_action. The server selects mode simulation or letterstream_test; the agent cannot override it. 3. Present the returned approval_url on the staging origin to the human. Stop while awaiting_approval. The human signs in, reviews the immutable PDF and quote, then approves that exact letter. In letterstream_test mode, the synthetic PDF and addresses are submitted to LetterStream, which adds an address coversheet not included in the preview (coversheet=Y). Tell the human this before approval: the preview shows letter content, not the complete provider print package. POST /v1/letters/{id}/approve is browser-session-only and does not send. 4. GET /v1/letters/{id} to check approval. Once approved, POST /v1/letters/{id}/send with a separate Idempotency-Key. This reserves funds and queues once. 5. GET /v1/letters/{id} to follow events and status. Local simulation ends in simulated. LetterStream Test Mode ends in provider_test_held: a real test job held for authorization. Neither is proof of mailing, receipt, delivery, or legal effectiveness. Existing simulated rows remain valid. 6. A human can cancel in the dashboard before submission is claimed. POST /v1/letters/{id}/cancel requires a customer session and releases any queued reservation once. Agent keys cannot cancel letters. ## Constraints and recovery - Save idempotency keys before requests. Reuse the same key and identical body after a timeout; do not create a new key to retry the same logical request. Different content with the same prepare key yields 409. - Idempotency keys: 8–128 ASCII letters, digits, dots, colons, underscores or hyphens. - Content is immutable. Changed text, service, or addresses require a new preparation and new human approval. - USD amounts are integer cents. The returned unexpired quote is provisional test credit, separate from provider-reported cost. Test-credit examples (349/1699 cents plus 25 per additional preview page) are not live or universal provider prices. - LetterStream submissions require verified provider Test Mode and zero provider funds, always use preauth=1, and never authorize dispatch. AgentPostage test credit is separate from provider funds. - LetterStream evidence fields: provider:"letterstream", provider_cost_cents, provider_job_id, provider_document_id, provider_batch_id, test_mode:true, held:true, physical_mail_sent:false. Show only returned values; never invent IDs, costs, or real delivery evidence. - In submission_unknown, evidence may retain only provider, provider_batch_id and provider_document_id. Those are request identifiers for manual review, not proof of acceptance or a held job. Do not infer verified Test Mode, a cost, a hold, or a physical-mail flag from missing fields. - In submission_unknown, funds stay reserved. Do not blindly retry or create replacement sends. - Errors: {error:{code,message,next_action?}}. Surface errors; do not invent success. - PDF: GET /v1/letters/{id}/pdf; account authorization required, private/no-store. - LetterStream limits single-file submissions to 50 batches per day; each provider-mode letter uses one batch. - US addresses only. Printable ASCII text and line breaks; up to 24,000 characters and 10 pages. No attachments or URL imports. - Use fictitious sample data in staging. Never promise delivery or legal effectiveness. - Test credit uses fixed top-ups via human-only POST /v1/billing/checkout. A return from checkout does not prove payment; verified server processing credits the balance. If checkout is unavailable, it returns billing_unavailable and starts no payment. - HTTP documentation is authoritative. POST /mcp tools: prepare_letter, get_letter, get_balance, send_letter. Use an MCP client for the protocol handshake; approval remains human-only.