unopost

x402 API

Post a letter from code, pay in USDC

Apps and AI agents can post a letter anywhere in Australia and pay per letter in USDC over x402. No account, API key or subscription: just a wallet and an HTTP client.

10 USDC per letter by regular post20 USDC per letter by Express Post

One price for up to 20 pages flat, GST included. Paid in USDC on Base, gas covered.

QuickstartOpenAPI spec

Why post letters over x402?

The same letter as the website, paid for over HTTP.

  • No account or API key Nothing to sign up for. Your code creates a letter, gets a price and pays with a signed USDC payment.
  • A fixed price per letter 20 USDC by Express Post, flat in a B4 envelope, or 10 USDC by regular post, folded to fit a letterbox, covers printing, the envelope, postage and tracking for up to 12 pages folded or 20 flat, then 0.30 USDC a page. GST included, and gas is on us.
  • The same letter as the website Printed as uploaded on 80gsm A4, tracked, and posted the same business day if paid by 2:30pm Melbourne time.
  • Refunded if it can't be posted If we can't post it, we refund the paying wallet in full, in USDC. A letter we cancel is refunded the same way.

Who it's for

  • AI agents An agent handling a bond dispute, insurance claim or council complaint can post the letter itself and pay from its own wallet.
  • Apps and scripts Property management, legal and billing software that posts letters, without a merchant account or monthly plan.

Quickstart

  1. Create a letter
  2. Upload the document
  3. Retrieve a letter
  4. Pay and post
  5. Follow the letter

Five requests take a letter from your code to the post. There's no account or key: the payment is all we need.

send-letter.sh
# 1. Create the letter
curl -X POST https://unopost.com.au/api/x402 \
  -H "Content-Type: application/json" \
  -d '{
  "fileName": "notice.pdf",
  "recipient": {
    "name": "Ruth Mitchell",
    "line1": "7 High Street",
    "suburb": "Echuca",
    "postcode": "3564"
  },
  "sender": {
    "name": "Sam Nguyen",
    "company": "Nguyen Property",
    "line1": "14 Carnarvon Street",
    "suburb": "Broome",
    "postcode": "6725"
  },
  "service": "express",
  "signature": true
}'

# 2. Upload the document to the uploadUrl you got back
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/pdf" \
  --data-binary @notice.pdf

# 3. Poll until the status is ready_to_send, and check the price
curl https://unopost.com.au/api/x402/$JOB_ID

# 4. Ask to send it: the 402 says what to pay
curl -i -X POST https://unopost.com.au/api/x402/$JOB_ID/send

# 5. Sign the payment with an x402 client, and send it again
curl -i -X POST https://unopost.com.au/api/x402/$JOB_ID/send \
  -H "PAYMENT-SIGNATURE: $PAYMENT_SIGNATURE"

Endpoints

Endpoints are relative to https://unopost.com.au. Requests and responses are JSON; errors are {"error": "..."}. Full reference: the OpenAPI spec.

Base URL
https://unopost.com.au

Create a letter

POST/api/x402

POST the file name, the recipient's address and your return address. You get a jobId, a signed uploadUrl, and URLs to check and pay for the letter.

Request body

fileNamestring · required
The file name with its extension: .pdf, .doc, .docx, .jpg, .jpeg or .png.
recipientAddress · required
The address to post the letter to.
senderAddress · required
Your return address, printed on the envelope so undeliverable mail comes back to you.
servicestring · optional
"express" for Express Post (the default) or "regular" for regular post.
duplexboolean · optional
Print double-sided. Defaults to false. Statutory declarations are always single-sided.
monoboolean · optional
Print in black and white. Defaults to false: a document with colour in it is printed in colour.
stapleboolean · optional
Staple the pages once in the top-left corner. Only for documents of up to 12 pages; a longer one is rejected when it is priced. Defaults to false.
foldboolean · optional
Express Post only: fold the letter into a C5 envelope instead of posting it flat in a B4 one, at no extra cost. Ignored for documents of more than 20 pages, which go flat. Regular letters are always folded.
signatureboolean · optional
Signature on delivery, 6 USDC extra, with either service. With regular, the letter goes by Registered post.

Address

The recipient must be in Australia. The return address can be anywhere: set its country, and its postcode becomes optional. Each line can be up to 40 characters.

namestring · optional
The person's full name.
companystring · optional
A business or organisation.
line1string · required
The street address, or a PO Box such as "PO Box 123".
line2string · optional
A second address line.
suburbstring · required
The suburb or town.
statestring · optional
Leave it out in Australia: the postcode sets it. If given, one of ACT, NSW, NT, QLD, SA, TAS, VIC or WA, matching the postcode.
postcodestring · required
Four digits.
countrystring · optional
Return address only. Leave it out for Australia.
Request
curl -X POST https://unopost.com.au/api/x402 \
  -H "Content-Type: application/json" \
  -d '{
  "fileName": "notice.pdf",
  "recipient": {
    "name": "Ruth Mitchell",
    "line1": "7 High Street",
    "suburb": "Echuca",
    "postcode": "3564"
  },
  "sender": {
    "name": "Sam Nguyen",
    "company": "Nguyen Property",
    "line1": "14 Carnarvon Street",
    "suburb": "Broome",
    "postcode": "6725"
  },
  "service": "express",
  "signature": true
}'
Response 200
{
  "jobId": "019d7a7f-a183-752d-9b3b-11511179033b",
  "uploadUrl": "https://unopost.com.au/uploads/019d7a7f-a183-752d-9b3b-11511179033b/notice.pdf?Expires=...&Signature=...&Key-Pair-Id=...",
  "statusUrl": "/api/x402/019d7a7f-a183-752d-9b3b-11511179033b",
  "sendUrl": "/api/x402/019d7a7f-a183-752d-9b3b-11511179033b/send",
  "status": "awaiting_upload"
}

Upload the document

PUTuploadUrl

PUT the raw file bytes to uploadUrl within 15 minutes. Up to 50 MB and 80 pages. Layout on A4 starts as soon as the upload lands; there's nothing else to call.

Request
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/pdf" \
  --data-binary @notice.pdf

Retrieve a letter

GET/api/x402/{jobId}

Wait for the price

Poll every few seconds until status is ready_to_send. The response then has the page count, the price in payment, the sendUrl, and a previewUrl for the print-ready PDF to check before paying.

fold now follows the service, true for regular post and false for Express Post, and duplex may be false: statutory declarations are printed single-sided. A regular letter over 12 pages is rejected when it is priced.

Follow the letter

Keep polling, less often, until the letter is posted, then delivered. There are no emails; every update appears in the status.

Request
curl https://unopost.com.au/api/x402/$JOB_ID
Response 200 · ready_to_send
{
  "jobId": "019d7a7f-a183-752d-9b3b-11511179033b",
  "service": "express",
  "duplex": false,
  "mono": false,
  "fold": false,
  "signature": true,
  "recipient": {
    "name": "Ruth Mitchell",
    "line1": "7 High Street",
    "suburb": "Echuca",
    "postcode": "3564"
  },
  "sender": {
    "name": "Sam Nguyen",
    "company": "Nguyen Property",
    "line1": "14 Carnarvon Street",
    "suburb": "Broome",
    "postcode": "6725"
  },
  "pageCount": 3,
  "status": "ready_to_send",
  "previewUrl": "/preview/019d7a7f-a183-752d-9b3b-11511179033b/notice.pdf?Expires=...&Signature=...&Key-Pair-Id=...",
  "payment": {
    "scheme": "exact",
    "network": "eip155:8453",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "amountAtomic": "20000000",
    "amountDisplay": "20 USDC",
    "payTo": "0x1111111111111111111111111111111111111111",
    "expiresAt": "2026-09-25T02:15:00Z"
  },
  "sendUrl": "/api/x402/019d7a7f-a183-752d-9b3b-11511179033b/send"
}
Response 200 · posted
{
  "jobId": "019d7a7f-a183-752d-9b3b-11511179033b",
  "service": "express",
  "duplex": false,
  "mono": false,
  "fold": false,
  "signature": true,
  "recipient": {
    "name": "Ruth Mitchell",
    "line1": "7 High Street",
    "suburb": "Echuca",
    "postcode": "3564"
  },
  "sender": {
    "name": "Sam Nguyen",
    "company": "Nguyen Property",
    "line1": "14 Carnarvon Street",
    "suburb": "Broome",
    "postcode": "6725"
  },
  "pageCount": 3,
  "status": "posted",
  "providerReference": "LTR-8F3A21C9"
}

Pay and post

POST/api/x402/{jobId}/send

POST to sendUrl without a payment. The response is 402 Payment Required, with the payment requirements base64-encoded in the PAYMENT-REQUIRED header.

Sign the payment as the x402 protocol describes (or let an x402 client library do it) and resend the request with the payload in a PAYMENT-SIGNATURE header. We verify and settle it, and the letter goes to print. The PAYMENT-RESPONSE header has the settlement.

Got 409 with job not ready to send just after ready_to_send? Wait a moment and retry. Calling again after paying returns the status without charging twice.

Request
curl -i -X POST https://unopost.com.au/api/x402/$JOB_ID/send
Response 402
HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6Mi...

{
  "error": "payment required"
}
PAYMENT-REQUIRED header, base64-decoded
{
  "x402Version": 2,
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:8453",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "amount": "20000000",
      "payTo": "0x1111111111111111111111111111111111111111",
      "maxTimeoutSeconds": 300,
      "extra": {
        "name": "USD Coin",
        "version": "2"
      }
    }
  ]
}
Request
curl -i -X POST https://unopost.com.au/api/x402/$JOB_ID/send \
  -H "PAYMENT-SIGNATURE: $PAYMENT_SIGNATURE"
Response 202
HTTP/2 202
payment-response: eyJzdWNjZXNzIjp0cnVlLC...

{
  "jobId": "019d7a7f-a183-752d-9b3b-11511179033b",
  "status": "sending"
}

Statuses

awaiting_upload
Waiting for the file.
processing
Laying the document out on A4 and pricing it.
ready_to_send
Priced and waiting for payment. The quote lasts 7 days.
sending
Paid, and queued for printing.
retrying
Printing hit a problem; we're retrying automatically.
posted
Printed and lodged with Australia Post.
delivered
Delivered by Australia Post. The document was deleted at dispatch.
failed
Not posted; the reason is in error, such as a quote that expired unpaid. A paid letter that can't be posted is refunded in full.
refunded
The payment has gone back to the wallet that paid for it.

Errors

400
Invalid request: for example a missing field, unsupported file type, address line over 40 characters, postcode outside the state, signature on delivery with regular post, or a regular letter of more than 12 pages.
402
Payment is required, or the payment couldn't be verified or settled. error says why.
404
There's no letter with that jobId.
409
job not ready to send: wait for ready_to_send and try again. quote expired: create the letter again.

Frequently asked questions

What is x402?

An open protocol for paying over HTTP. The server replies 402 Payment Required with a price; the client signs a stablecoin payment and resends the request. No account, card or invoice.

What do I need?

A wallet on Base with enough USDC, and an HTTP client. No ETH needed for gas: the payment is a signed USDC transfer authorisation, and we cover the network fee.

How much does a letter cost?

20 USDC by Express Post for up to 20 pages, then 0.30 USDC a page, or 10 USDC by regular post for a letter of up to 12 pages, GST included. Signature on delivery is 6 USDC extra with either service; regular post signed for is Registered post, 16 USDC. Tracking, double-sided and black-and-white printing, stapling up to 12 pages, and folding an Express Post letter into a DL window envelope are free. The status response shows the exact price before you pay.

Can I check the letter before paying?

Yes. Once it's ready to send, previewUrl is the print-ready PDF, laid out on A4 exactly as it will be printed. Nothing is charged until you pay.

When is it posted, and how long does it take to arrive?

Letters paid by 2:30pm Melbourne time on a business day are posted that day; later ones, the next business day. Express Post usually arrives the next business day within the Express Post network, regular post in 3 to 7 business days.

What if the letter can't be posted?

Its status changes to failed and we refund the full amount in USDC to the paying wallet, whether it failed or we cancelled it. For anything else, email support@unopost.com.au with the jobId.

What happens to my document?

It's encrypted in transit and permanently deleted, with its print-ready copy, once the letter is lodged with Australia Post. If a letter isn't paid for or can't be posted, it's deleted after 14 days.

Where can letters go?

Any address in Australia, including PO Boxes, in every state and territory. The API doesn't post overseas.

Who's responsible for what an agent sends?

You are. Every letter paid for from your wallet is yours, including one an agent wrote and sent on your instructions, and you need the right to send what's in it. Our terms list what can't go in the post: impersonation, harassment, scams, unsolicited advertising in bulk, and anything that breaches a court order. We cancel letters that break those rules, and refund them in full. If you post on someone else's behalf, you're responsible for their document as if it were yours.

Pricing

ItemPrice
Regular post, folded to fit a letterbox: up to 12 pages10 USDC
Registered post, regular post signed for on delivery: up to 12 pages16 USDC
Express Post, flat in a B4 envelope: 20 pages included, then 0.30 USDC for each extra page20 USDC
Express Post with signature on delivery: 20 pages included, then 0.30 USDC for each extra page26 USDC
Tracking, colour, double-sided or black-and-white printing, and staplingFree
Network fee (gas)Covered

Prices are in USDC on Base. The price is set once your document is laid out on A4; quotes last 7 days.

Pricing may change. Use of this service is subject to our Terms of Service and Privacy Policy.