Estimating an Order's Cost
Before you send mail through the API, you can price the exact order you are about to place. Post the same request body you would send to /api/v2/send/{mailer-type} to /api/v2/estimate/{mailer-type} instead. The response tells you what the order costs and whether your balance covers it.
An estimate never places an order: nothing is charged, nothing is printed or mailed, and no order appears in your account.
Endpoints
POST https://api.thanks.io/api/v2/estimate/{mailer-type}
There is one estimate endpoint for each send endpoint. Replace {mailer-type} with the same value you use to send:
| Estimate endpoint | Prices the same order as |
|---|---|
/api/v2/estimate/postcard | /api/v2/send/postcard |
/api/v2/estimate/letter | /api/v2/send/letter |
/api/v2/estimate/windowedletter | /api/v2/send/letter (windowed letter) |
/api/v2/estimate/windowlessletter | /api/v2/send/windowlessletter |
/api/v2/estimate/notecard | /api/v2/send/notecard |
/api/v2/estimate/magnacard | /api/v2/send/magnacard |
/api/v2/estimate/giftcard | /api/v2/send/giftcard |
Authenticate with the same Authorization: Bearer header you use to send. See Authorization Headers.
The request is validated exactly as the matching send is, so a payload that would be rejected on send (no recipients, no creative, an invalid field) comes back with the same 422 error from the estimate. That makes an estimate a safe first call while you build an integration.
Example
Request:
curl -X POST https://api.thanks.io/api/v2/estimate/postcard \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"size": "4x6",
"message": "Thanks for being a customer!",
"front_image_url": "https://example.com/front.jpg",
"recipients": [
{ "name": "Jane Doe", "address": "123 Main St", "city": "Austin", "province": "TX", "postal_code": "78701", "country": "US" }
]
}'
Response (values are illustrative):
{
"message": "OK",
"data": {
"type": "postcard",
"size": "4x6",
"total_recipients": 1,
"recipients": { "united_states": 1, "international": 0 },
"pending_email_lookups": 0,
"costs_in_cents": {
"united_states": 118,
"international": 0,
"additional_pages": 0,
"giftcard_face_value": 0,
"grand_total": 118
},
"total_cost_in_cents": 118,
"total_cost": "$1.18",
"current_balance_in_cents": 5000,
"covered_by_balance": true,
"test_mode": false,
"notes": []
}
}
Response fields
| Field | What it tells you |
|---|---|
type, size | The mailer type and size that were priced. |
total_recipients | How many pieces the order would mail. |
recipients.united_states, recipients.international | The recipient count split by destination. |
pending_email_lookups | Recipients sent with an email address but no mailing address. See Email-only recipients. |
costs_in_cents.united_states, costs_in_cents.international | Postage and printing for US and international pieces. |
costs_in_cents.additional_pages | Extra letter pages, charged per page. |
costs_in_cents.giftcard_face_value | The combined face value of every gift card in the order. 0 for other mailer types. |
costs_in_cents.grand_total | Everything in the order except gift card face value. |
total_cost_in_cents | The order total: grand_total plus giftcard_face_value. |
total_cost | The same total, formatted in dollars (for example $1.18). |
current_balance_in_cents | Your account's credit balance right now. |
covered_by_balance | true if your balance covers total_cost_in_cents. |
test_mode | true if API Test Mode is on for your account. |
notes | Plain-language caveats about anything that could make the real charge differ. Empty when there are none. |
For postcards, letters, Notecards, and MagnaCards, total_cost_in_cents is exactly what the same request is charged when you send it.
Things to know
Email-only recipients
When a recipient has an email address but no mailing address, a send looks up their address from the email, and that lookup is a paid data service. An estimate does not run the lookup. Instead, it prices those recipients as if the lookup finds an address, counts them in pending_email_lookups, and adds a note. When you send, any recipient whose address can't be found is not mailed and not charged, so the real charge can be lower than the estimate but not higher.
Additional letter pages
Extra pages for a letter are priced by counting the pages in the PDF you supply. If the PDF can't be read, those pages are left out of the estimate and a note says so. They are still charged per page when the order is sent, so in that case the real charge will be higher than the estimate.
Gift cards
A gift card estimate includes the face value of every card in costs_in_cents.giftcard_face_value and in total_cost_in_cents. On paid plans, a card's face value is only charged if the recipient redeems it (see Billing FAQs), so treat total_cost_in_cents as the most a gift card order can cost, and costs_in_cents.grand_total as the cost of mailing it.
If your account can't send gift cards, a gift card estimate is refused with HTTP 402 and the code giftcards_require_paid_plan, the same response the send endpoint returns.
Test mode
An estimate always quotes your account's real rates. If test_mode is true, sending the same request places an order that is cancelled automatically and not charged. Turn test mode off before you rely on the estimate as the amount you will pay. See API Test Mode.
Balance
If covered_by_balance is false, the send will need more credits than you have. For a gift card order on a paid plan, compare your balance to costs_in_cents.grand_total instead, since face value is charged later, as cards are redeemed. With Auto-Recharge on, your card is charged to top up your balance; with Auto-Recharge off, a send that would take your balance below $0 is blocked. See Credits, Balance & Auto-Recharge.
What an estimate doesn't check
An estimate prices the order and validates the request. It does not render your artwork or handwriting, so a problem that only shows up when the piece is rendered, such as a message too long to fit the card, is reported when you send, not by the estimate.