Permit Post API Reference
Base URL: https://api.ttpost.com/v1/permit-post
Authentication
All requests must include your API key in the Authorization header as a Bearer token. Use your sandbox key for testing and your production key for live batches.
curl https://api.ttpost.com/v1/permit-post/... \ -H "Authorization: Bearer sk_test_permit_..."
Rate limits:
- Starter tier: 50 requests / minute
- Pro tier: 500 requests / minute
- Enterprise tier: Unlimited
Exceeded limits return 429 Too Many Requests. Retry after the delay indicated in the Retry-After header.
Submit batch
/v1/permit-post/batches
Submit a batch of mail pieces for permit post delivery. TTPOST validates every recipient address against the postal-code authority before printing begins.
Request body
| Parameter | Type | Description |
|---|---|---|
name | string | Human-readable batch name for your records |
type | string | statement, notice, or marketing |
service | string | regular or registered |
recipients_csv_url | string | HTTPS URL to a CSV file of recipients (mutually exclusive with recipients) |
recipients | array | Inline JSON array of recipient objects (mutually exclusive with recipients_csv_url) |
scheduled_send_date | string | ISO 8601 date — earliest date to begin delivery. Defaults to next business day. |
callback_url | string | Your webhook endpoint for batch lifecycle events |
Example request
curl -X POST https://api.ttpost.com/v1/permit-post/batches \
-H "Authorization: Bearer sk_test_permit_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Electricity bills — May 2026",
"type": "statement",
"service": "regular",
"recipients_csv_url": "https://your-cdn.com/recipients.csv",
"scheduled_send_date": "2026-05-02",
"callback_url": "https://your-app.com/webhooks/ttpost-pp"
}'
Response
{
"batch_id": "pp-2026-05-001",
"status": "validating",
"piece_count": 82400,
"estimated_cost": 27299.00
}
Validate addresses
/v1/permit-post/addresses/validate
Validate a recipient list before submitting a batch. Accepts a CSV URL or inline recipient array. Returns per-row validation results including postal-code match status and any flagged issues.
Shared engine with Address API
This endpoint uses the same underlying validation engine as the Address Lookup API. If you already have an Address API key, you don't need a separate key for this endpoint — your existing key works here too.
Example request
curl -X POST https://api.ttpost.com/v1/permit-post/addresses/validate \
-H "Authorization: Bearer sk_test_permit_..." \
-H "Content-Type: application/json" \
-d '{
"recipients_csv_url": "https://your-cdn.com/recipients.csv"
}'
Response
{
"total": 82400,
"valid": 82196,
"flagged": 2,
"unresolvable": 1,
"results": [
{ "row": 4, "status": "flagged",
"reason": "Ambiguous postal code (3 possible matches)" },
{ "row": 5, "status": "flagged",
"reason": "Address not found in TTPOST registry — new construction?" },
{ "row": 9, "status": "unresolvable",
"reason": "Missing all address fields" }
]
}
Status values: valid · flagged (deliverable with warnings) · unresolvable (cannot be delivered)
Retrieve batch status
/v1/permit-post/batches/{batch_id}
Retrieve the current processing status of a batch, along with piece-level counts at each stage.
curl https://api.ttpost.com/v1/permit-post/batches/pp-2026-05-001 \ -H "Authorization: Bearer sk_test_permit_..."
Response
{
"batch_id": "pp-2026-05-001",
"status": "in_flight",
"piece_count": 82400,
"pieces_delivered": 61200,
"pieces_in_transit": 21000,
"pieces_returned": 200,
"updated_at": "2026-05-04T11:22:00-04:00"
}
Status values:
validating · validated · printing · in_flight · delivered · returns_pending
Webhooks
Subscribe by providing a callback_url when submitting a batch. TTPOST POSTs batch lifecycle events to this URL. Verify the X-TTPOST-Signature header (HMAC-SHA256 over the raw body with your webhook secret).
Events:
batch.validated— address validation complete, piece count confirmedbatch.printed— all pieces have been printed at the facilitybatch.in_flight— pieces dispatched to the postmaster networkbatch.delivered— final delivery complete for all piecesbatch.returns_report— end-of-run returns report ready for download
Retry policy: 3 attempts with exponential backoff (1 s, 10 s, 100 s).
Sample webhook payload
{
"event": "batch.delivered",
"batch_id": "pp-2026-05-001",
"timestamp": "2026-05-05T17:10:00-04:00",
"piece_count": 82400,
"pieces_delivered": 82196,
"pieces_returned": 204,
"returns_report_url": "https://reports.ttpost.com/pp-2026-05-001-returns.csv",
"signature": "sha256=..."
}
Error codes
| Code | Meaning |
|---|---|
400 | Malformed request body |
401 | Invalid or missing API key |
404 | Batch ID not found |
422 | Missing required parameter or recipient list could not be retrieved |
429 | Rate limit exceeded — see Retry-After header |
500 | Internal server error — retry with backoff |
{
"error": "recipients_required",
"message": "Either 'recipients_csv_url' or 'recipients' must be provided.",
"docs": "https://developer.ttpost.com/permit-post/errors"
}