Docs
REST and MCP use the same letter service. Connect an MCP assistant below, or use the REST API for a platform such as Muse.ai that calls HTTP endpoints.
REST integrations
Using Muse.ai? Start with the Muse.ai setup guide for a copyable connection prompt and Google sign-in instructions.
Base URL: https://paperagent.dev/v1. Use an existing OAuth access token or a PaperAgent API key in Authorization: Bearer …. When self-service is enabled, connect automatically with the device flow below. Integrations requiring a manual key can use an optional key from your account page. Read and write permissions are shared with MCP.
OpenAPI request and response schemas · Agent instructions
Automatic connection — no support email
Read OAuth discovery first. If device_authorization_endpoint is absent, new-customer sign-in, device connections and key creation are unavailable; stop onboarding without offering an API-key fallback. When advertised, register a public client at /oauth/register with explicit urn:ietf:params:oauth:grant-type:device_code and refresh_token grants, no redirect URI, and letter scopes. POST your client ID, scopes and resource https://paperagent.dev/mcp to /oauth/device_authorization.
Show the returned connection link and code directly to the customer. A host's manual API-key connector is a separate flow and should not replace that link. They sign in with Google, validate and confirm their return address, and approve the agent. Poll /oauth/token with the device grant, client ID and device code every five seconds. Continue on authorization_pending; add five seconds to the interval on slow_down. Stop on denial or ten-minute expiry. Store the resulting tokens securely and rotate the refresh token at /oauth/token when the one-hour access token expires. Disconnect an agent from your account to revoke all its tokens.
A customer with a confirmed return address can create an unpaid order. Confirmed live Stripe payment completes payment verification before live fulfillment. Test keys and test payments never enable live mailing. Browser account management requires Google sign-in and CSRF protection; agents cannot mint extra credentials. The complete JSON examples are in llms.txt.
- Create a draft with
POST /v1/drafts. Include the recipient and a text or Markdown body; standard is the default tier. - Review
GET /v1/drafts/{id}/preview. Show the PDF, mailing requirements and total. Obtain approval before sending. Re-preview after edits. - Call
POST /v1/letterswith the draft ID, approvedconfirm_total_cents, and a uniqueidempotency_key. Reuse the key on retries. - Pay the existing order using its
payment_urlwith a linked wallet, or give the customer thecheckout_url. - Follow
GET /v1/letters/{id}or subscribe to webhooks. Payment can be followed by review before mailing.
Linked wallet payments
POST an empty object to the payment URL to receive an HTTP 402 MPP challenge. Have the wallet approve it, then retry the same request and body with its credential in Payment-Authorization. Keep your account token in Authorization. The challenge expires after 15 minutes. Success returns a Payment-Receipt and the existing order status. A host holding an approved Stripe shared payment token can instead POST {"shared_payment_token":"…"} to that URL.
Availability depends on the payment configuration for your credential's mode. PaperAgent test keys use test payments. An unavailable or declined payment includes a checkout fallback when available. After a timeout, retry the original token and order; a 409 means payment may still be resolving. Never create a second letter to retry a charge. Muse wallet authorization still needs validation with the platform; the integration tests use mock payments.
| Method | Endpoint | Permission |
|---|---|---|
| GET | /v1/account/sessionRead the Google browser session and CSRF token. | Google session + CSRF for writes |
| POST | /v1/account/logoutSign out of this browser session. | Google session + CSRF for writes |
| POST | /v1/account/sender/validateValidate a customer return address and show postal corrections. | Google session + CSRF for writes |
| POST | /v1/account/senderConfirm the validated address receives the customer’s mail. | Google session + CSRF for writes |
| GET | /v1/account/connectionsList connected agents and their unverified labels. | Google session + CSRF for writes |
| DELETE | /v1/account/connections/{id}Revoke an agent’s entire access and refresh token family. | Google session + CSRF for writes |
| GET | /v1/account/api-keysList API key metadata; never secrets. | Google session + CSRF for writes |
| POST | /v1/account/api-keysCreate a named test or live key with letter scopes; secret shown once. | Google session + CSRF for writes |
| DELETE | /v1/account/api-keys/{id}Revoke one customer API key. | Google session + CSRF for writes |
| GET | /v1/pricingPublished prices, available products and limits. | Public |
| POST | /v1/addresses/validateValidate a US mailing address. | Public |
| POST | /v1/draftsCreate a letter draft and quote. Nothing is printed or charged. | letters:write |
| PATCH | /v1/drafts/{id}Edit a draft and refresh its quote. | letters:write |
| GET | /v1/drafts/{id}Retrieve a draft and its stored quote. | letters:read |
| GET | /v1/drafts/{id}/previewReview the PDF, current total and mailing requirements before approval. | letters:read |
| POST | /v1/lettersCreate one order for an approved draft and exact total. Reuse idempotency_key on retries. | letters:write |
| GET | /v1/letters/{id}Read payment, mailing status, scans and delivery estimates. | letters:read |
| GET | /v1/lettersList letters with cursor pagination. | letters:read |
| POST | /v1/letters/{id}/checkoutPay the existing letter with a shared payment token. An empty body requests an MPP challenge; use Payment-Authorization for its credential. | letters:write |
| GET | /v1/accountRead the connected account and credential mode. | letters:read |
| GET | /v1/account/notificationsRead email preferences; settings apply across both modes. | letters:read |
| PATCH | /v1/account/notificationsChange one email preference. | letters:write |
| POST | /v1/webhook_endpointsSubscribe an HTTPS endpoint; the signing secret is returned only once. | letters:write |
| GET | /v1/webhook_endpointsList webhook subscriptions. | letters:read |
| GET | /v1/webhook_endpoints/{id}Read a webhook subscription. | letters:read |
| PATCH | /v1/webhook_endpoints/{id}Update a webhook subscription. | letters:write |
| DELETE | /v1/webhook_endpoints/{id}Delete a webhook subscription. | letters:write |
| POST | /v1/abuse-reportsReport unwanted mail. Responses do not reveal recipient history. | Public |
Address validation defaults to 20 requests/minute before sign-in and 60 per account, with a shared daily provider budget. Abuse reports allow 5/minute per IP. Respect Retry-After on 429. Cancellation and refunds are handled by support.
Connect your agent
One address, every assistant that speaks MCP:
https://paperagent.dev/mcp
get_pricing and validate_address answer without signing in, so you can check a price and an address before connecting anything. Every other tool asks you to sign in with your email the first time it is called.
No platform publishes a link that pre-fills an MCP address, so all three come down to pasting the line above into a settings screen — and each one gates who is allowed to. Here is where it goes, and who it is open to:
ChatGPT
Settings → Connectors → Advanced → Developer mode.
Needs ChatGPT Plus, Pro, Business, Enterprise or Edu, and developer mode has to be switched on from a browser. Once the connector is added it works in the mobile apps too.
Claude
+ menu → Add connector → Add custom connector.
Works on every Claude plan. On Team and Enterprise an owner adds it once in organisation settings and everyone else connects from their own Connectors page.
Gemini
Connected apps → Custom apps for Spark → Add a custom app.
Google limits custom apps to people who are 18 or over, in the US, signed in with a personal Google Account rather than a work or school one, and who have Keep Activity switched on. The app has to be added from the Gemini web app on a computer; after that it works on your phone as well.
The address above already works here. We are not sending people down this path yet — the guided page goes up once we have walked it on a real Gemini account.
MCP tool reference
Read tools require letters:read; tools that change a draft or prepare payment require letters:write. Reconnect with the required permission if a call is refused. A send requires your approval of the preview and exact total.
- get_pricing
- Read available mail services, current prices and limits.
- Permission: No sign-in required
- validate_address
- Validate a US postal address before preparing a letter.
- Permission: No sign-in required
- create_draft
- Create a letter draft from the recipient and your text.
- Permission: letters:write
- update_draft
- Revise an existing draft before sending.
- Permission: letters:write
- preview_draft
- Read the PDF preview and current quote for approval.
- Permission: letters:read
- send_letter
- Prepare the approved letter and payment. Reuse the same idempotency key when retrying; a replay returns the existing letter and its current status.
- Permission: letters:write
- get_letter_status
- Read the current status and available postal visibility for a letter.
- Permission: letters:read
- list_letters
- List letters belonging to your account.
- Permission: letters:read
By default, address validation is limited to 20 requests per minute before sign-in and 60 per minute per connected account. A shared daily provider budget also applies. Respect Retry-After and the reset time in any refusal.
How it is called
MCP assistants display the service as:
paperagent.send_letter
The tool description reads, in the register a model matches against: Send a real, physical letter through the United States Postal Service — printed on paper, put in an envelope, stamped, and mailed. This is not email.
Constraints, stated up front
- US domestic addresses only.
- Mailed within one business day.
- A letter is at most 3 printed pages. A longer body is refused rather than billed at a higher price — shorten it, or split it into two letters.
- A plain First-Class letter gets no delivery scan. We show processing visibility and an expected delivery date, and we do not call that tracking.