PostalForm Projects

PostalForm Projects API Reference

Use this Cloudflare-hosted API for Stripe Projects-style provisioning, PDF uploads, quotes, test sends, live sends, credits, and signed customer webhooks.

Download OpenAPI YAML Download SDK YAML Open dashboard

Base URLs

Dashboard: https://projects.postalform.com
API:       https://projects.postalform.com/api/v1

Authentication

Authorization: Bearer pf_test_...
Authorization: Bearer pf_live_...

Typical test flow

POST /api/v1/documents/upload-intent
PUT  {upload_url}
POST /api/v1/documents/{document_id}/complete
		POST /api/v1/letters/quotes
		POST /api/v1/letters
		GET  /api/v1/letters/{order_id}
		GET  /api/v1/letters/{order_id}/document.pdf

Core Request Parameters

POST /api/v1/documents/upload-intent
{
  "content_type": "application/pdf",
  "byte_size": 123456,
  "page_count": 4
}

POST /api/v1/letters/quotes
{
  "document_id": "doc_...",
  "mail_class": "usps_first_class",
  "color": false,
  "double_sided": true,
  "certified": false,
  "destination_country_code": "US",
  "origin_country_code": "US"
}

POST /api/v1/letters
Idempotency-Key: unique-order-key
{
  "quote_id": "quote_...",
  "recipient": { "name": "...", "line1": "...", "city": "...", "postal_code": "...", "countryCode": "US" },
  "sender": { "name": "...", "line1": "...", "city": "...", "postal_code": "...", "countryCode": "US" },
	  "metadata": { "customer_id": "..." }
	}

Provider routing is automatic. Public API clients should not send provider_strategy; unsupported provider overrides are rejected.

Projects uses developer-infrastructure pricing separate from the public PostalForm.com one-off workflow pricing. Standard letters start with a $1.80 base fee plus $0.20 per billable black-and-white page or $0.40 per billable color page. U.S./Canada Priority/Express stays on Click2Mail cost-plus pricing, proof-mail add-ons remain $8.00 for U.S. Certified Mail plus $3.00 for Electronic Return Receipt, and PostGrid fallback mail from Canada to the Netherlands includes a sheet-count postage guard when PinGen cannot accept the letter.

International Mailing

Letter quotes accept destination_country_code and origin_country_code; both default to US. Supported destination countries are US, CA, AT, BE, CH, DE, FR, GB, IN, LU, and NL.

U.S. and Canada letters prefer Lob when eligible. U.S./Canada Priority/Express letters route through Click2Mail. Supported non-U.S./Canada standard letters can route through PinGen cheap for local print when PinGen credentials are configured and the PDF fits PinGen's 8 MB and destination page limits. International Express routes through PinGen Fast for AT, CH, DE, GB, IN, and NL with a $4 surcharge; it is unavailable for destinations without a distinct PinGen Fast product. Ineligible standard letters fall back to PostGrid where available.

Postcards require a composed two-page PDF and do not support certified or registered mail. Lob-routed international postcards must be 4x6 and use a U.S. sender return address; larger international postcards or non-U.S. return addresses route to PostGrid where available.

Proof Mail

For U.S. standard letters, certified=true requests USPS Certified Mail through Lob when the piece fits Lob limits. For Belgium, Switzerland, and France standard letters, certified=true requests PinGen registered mail when the piece fits PinGen limits. Postcards do not support certified or registered mail.

Credits And Webhooks

Use /api/v1/credits/balance, /api/v1/credits/checkout-session, /api/v1/credits/payment-methods/setup-session, and /api/v1/credits/auto-refill for prepaid live-mail credits and automatic refill setup. Use /api/v1/webhook-endpoints and /api/v1/webhook-events/:id/replay for signed customer status webhooks.

Customer webhook events are emitted for provider status changes only, with postalform.{letter|postcard}.{status} event names: accepted_by_provider, in_transit, delivered, returned, failed, and canceled. Internal timeline states such as queued, document_preparing, document_prepared, submitted_to_provider, and submission_pending are visible on order reads but are not customer webhooks.

PostalForm-Signature: t=1777592400,v1=<hmac_sha256_hex>

{
  "id": "evt_123",
  "type": "postalform.letter.in_transit",
  "data": {
    "object": {
      "id": "ord_123",
      "object": "letter",
      "status": "in_transit",
      "mode": "live",
	      "price_cents": 2012,
      "currency": "usd",
      "funds_status": "captured",
      "billing_rail": "prepaid_credits",
      "selected_provider": "click2mail",
      "metadata": {}
    }
  },
  "provider": {
    "name": "click2mail",
    "provider_letter_id": "c2m_123",
    "status_raw": "MAILED",
    "status_normalized": "in_transit",
    "tracking_number": "9405500000000000000001",
    "tracking_status": "In Transit"
  }
}