Mail by PonyDocs

Reference

Errors

View as Markdown

Every error uses the same format:

JSON
{
  "error": {
    "code": "INSUFFICIENT_FUNDS",
    "message": "Credit is insufficient for this quote. Add funds in Account → Credits.",
    "retryable": false,
    "request_id": "req_…",
    "action_url": "/app?view=credits&amount_minor=1000",
    "details": {"required_minor": 499, "available_minor": 200, "shortfall_minor": 299,
                "suggested_topup_minor": 1000, "currency": "USD"}
  }
}
Field Always present Meaning
code Yes A stable code from the table below. Branch on this.
message Yes A human-readable explanation. Don't parse it; it may change.
retryable Yes true if the problem is temporary and repeating the same request with the same key may succeed
request_id No Include this when you contact support
action_url No A page where the account owner can fix the problem
details No Extra data, such as reason for ACTION_NEEDED

Over MCP, the same error object comes back in the tool result's structuredContent, with isError: true.

Error codes#

Code HTTP What happened What to do
UNAUTHENTICATED 401 The credential is missing, expired or revoked Check the Authorization header. Refresh the OAuth token or create a new key.
INSUFFICIENT_FUNDS 402 Your available balance is less than the quote Open action_url to add credits (the amount is filled in), then send again with a new key
FORBIDDEN 403 The credential lacks the scope, or the permission belongs to another key or assistant Check the key's scopes and the permission's client ID
LIMIT_EXCEEDED 403 The send would go over a sending permission's limit Wait for the daily reset at midnight UTC, or raise the limit on the website
LIMIT_EXCEEDED 409 You already have 10 webhook endpoints Remove one you don't use
NOT_FOUND 404 The resource doesn't exist or isn't yours Check the ID, and that you're using a live key for live records and a test key for test records
REQUEST_NOT_FOUND 404 No request was recorded for that operation and key Repeat the original request with the same key and body
ACTION_NEEDED 409 Something must be done first. See details.reason below. Fix the cause, often by showing the owner action_url, then retry with a new key
VERSION_CONFLICT 409 The draft changed since you read it Read the draft again and use its current version
PROOF_STALE 409 The draft or renderer changed since the proof was made Render a new proof, then get a new quote
QUOTE_EXPIRED 409 The quote is past expires_at Get a new quote with a new key
QUOTE_MISMATCH 409 The quote, proof, total or send intent doesn't match Build the send request from the latest quote
IDEMPOTENCY_CONFLICT 409 The key was already used with a different body Use the original body, or a new key for a new request
PAYMENT_ROUTE_CONFLICT 409 This mailing or draft version already has an order Read the order in details.order_id instead of sending again
CANCELLATION_TOO_LATE 409 The order is already being prepared The letter will be mailed. Nothing was changed.
VALIDATION_ERROR 422 A field is missing or invalid Fix the request body, then send it with a new key. The message names the field; missing template variables are listed in details.missing.
RATE_LIMITED 429 Too many requests Wait for the Retry-After header's seconds, then repeat the same request and key
TEMPORARILY_UNAVAILABLE 503 A temporary problem on Pony's side Wait, then repeat the same request and key

ACTION_NEEDED reasons#

details.reason What it means
grant_required This assistant has no sending permission. Add one under Let my assistant send letters.
grant_unavailable The sending permission expired or was revoked. Create a new one.
recipient_not_permitted The permission doesn't allow this recipient or sender
option_not_permitted The permission doesn't allow this paper, envelope or style
address_confirmation Confirm the sender and recipient addresses on the website
unsupported_destination Use a US address
account_frozen A refund, dispute or negative balance has paused sending. Resolve it in Account → Credits.
test_mode Test keys can't create real funding links. Use POST /test/credits.
missing_final_price, missing_final_tax Pony can't price this letter right now. Try again later.
Anything else Contact support with the request_id

Retrying safely#

There are two kinds of retry, and they use keys differently:

  • Temporary failure (retryable: true, 429, 5xx or no response at all): repeat the same request with the same idempotency key. Pony returns the original result if the first attempt got through.
  • Rejected request (any other 4xx): Pony stores the rejection against that key, so repeating it returns the same error. Fix the cause, then send the request with a new idempotency key. For a send, keep the same client_reference and send_intent_id so the letter still can't go out twice.

Also:

  • Back off between retries, starting at a few seconds and doubling. Honor Retry-After when it's present.
  • If you aren't sure whether a write succeeded, look it up before retrying.
  • Never respond to an error by raising a limit, switching recipients or adding credits automatically. Those are the owner's decisions.