IgnitePOST public API reference
Authentication
We're using API keys for authentication.
Set up an API key at profile/API Keys
You have to provide the secret token when making API calls as a request header in the following format:
X-TOKEN: your-secret-api-token
Testing the authentication can be done by querying the https://dashboard.ignitepost.com/api/v1/authenticate endpoint (see below).
Errors
We use HTTP response codes to indicate the success or failure of an API request:
- codes in the 2xx range indicate success
- codes in the 4xx range indicate an error that failed given the information provided (e.g. a required parameter was omitted, a resource was not found)
- codes in the 5xx range indicate an error with IgnitePost's servers
Common Objects
The Order Object
The fields of an IgnitePost order are as follows:
id: string - Unique identifier for the order
uid: string - Unique external identifier for the orders from your own system
message: string - The letter text
font: string
image_url: string
image_inside_url: string
image_backside_url: string
insert: string
metadata: string - Use this field to attach key-value data to order objects.
As an example, you could store your user's name, id: "metadata[id]=42"
recipient_name: string
recipient_email: string
recipient_company_name: string
recipient_address_one: string
recipient_address_two: string
recipient_city: string
recipient_state: string
recipient_zip: string
sender_name: string
sender_address_one: string
sender_address_two: string
sender_city: string
sender_state: string
sender_zip: string
created_at: datetime
send_on: date - The date the letter is scheduled to be mailed. Set this yourself on
create, or leave it out and we schedule it for you. Always a working
day: a date landing on a weekend or a holiday we observe is moved
to the next one. See the create order endpoint for the full rules.
sent_at: datetime
Test Mode
There are two ways to use the API in test mode:
1. Send an 'X-TESTING' request header with the value of 'true'
2. Use an API key that has not been switched to live
When the API is in test mode the orders you send will not be persisted.
Endpoints
Authenticate
- description: Used to test your authentication
- endpoint: GET https://dashboard.ignitepost.com/api/v1/authenticate
- arguments: none
- response:
{ "email":"your@email.com" }
- example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X GET https://dashboard.ignitepost.com/api/v1/authenticate
List letter templates
- description: Returns the list of available letter-templates that can be used as a template for the handwritten letter. Attributes passed in the create order payload will override the template attributes.
- endpoint: GET https://dashboard.ignitepost.com/api/v1/letter_templates
- arguments: none
- response:
{
"data": [
{
"id" :"42",
"name": "Congratulations Card",
},
{...},
{...}
]
}
- example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X GET https://dashboard.ignitepost.com/api/v1/letter_templates
List fonts
- description: Returns the list of available fonts that can be used for the handwritten message
- endpoint: GET https://dashboard.ignitepost.com/api/v1/fonts
- arguments: none
- response:
{
"data": [
{
"key": "becca",
"label": "Becca"
},
{...},
{...}
]
}
- example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X GET https://dashboard.ignitepost.com/api/v1/fonts
List default images
- description: Returns the list of available stock images that can be used for the note
- endpoint: GET https://dashboard.ignitepost.com/api/v1/images
- arguments: none
- response:
{
"data": [
{
"key": "thank_you",
"label": "Thank You",
"url": "http://ignitepost.com/thank-you.jpg"
},
{...},
{...}
]
}
- example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X GET https://dashboard.ignitepost.com/api/v1/images
List inserts
- description: Returns the list of available inserts (gift cards) that can be attached to the handwritten letter
- endpoint: GET https://dashboard.ignitepost.com/api/v1/inserts
- arguments: none
- response:
{
"data": [
{
"key" :"starbucks_5_giftcard",
"name": "$5 Starbucks Giftcard",
"denomination": 5.0,
"purchase_fee": 0.0
},
{...},
{...}
]
}
- example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X GET https://dashboard.ignitepost.com/api/v1/inserts
Retrieve an order
- description: Returns an order object
- endpoint: GET https://dashboard.ignitepost.com/api/v1/orders/:id
- arguments: none
- response: an order object
- example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X GET https://dashboard.ignitepost.com/api/v1/orders/42
Cancel an order
- description: Cancels an order and refunds any charge back to your account balance (or restores an included send, if applicable). Orders that have already been fulfilled or are part of a batch that has started processing cannot be cancelled.
- endpoint: DELETE https://dashboard.ignitepost.com/api/v1/orders/:id
- arguments: none
- response:
{ "message": "Order cancelled successfully." }
errors:
422 Unprocessable Entity— order cannot be cancelled (already fulfilled or in a started batch)404 Not Found— order not found
example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X DELETE https://dashboard.ignitepost.com/api/v1/orders/42
Create an order
- endpoint: POST https://dashboard.ignitepost.com/api/v1/orders
- arguments:
font: string (required)
- accepted values
- known IgnitePost fonts - see the list fonts endpoint
message: string (required)
- accepted values
- max length of 450 chars
image: string (required)
- accepted values
- a known IgnitePost image-key - see the default images endpoint
- an image url (max file size: 4mb, max dimensions: 4200px width x 3000px height)
image_inside: string (optional)
- accepted values
- a known IgnitePost image-key - see the default images endpoint
- an image url (max file size: 4mb, max dimensions: 4200px width x 3000px height)
image_backside: string (optional)
- accepted values
- a known IgnitePost image-key - see the default images endpoint
- an image url (max file size: 4mb, max dimensions: 4200px width x 3000px height)
insert: string (optional)
- accepted values
- known IgnitePost inserts - see the list inserts endpoint
recipient_name: string (optional)
recipient_email: string (optional)
recipient_company_name: string (optional)
recipient_address_one: string (required)
recipient_address_two: string (optional)
recipient_city: string (required)
recipient_state: string (required)
recipient_zip: string (required)
sender_name: string (optional)
sender_address_one: string (optional)
sender_address_two: string (optional)
sender_city: string (optional)
sender_state: string (optional)
sender_zip: string (optional)
send_on: date (optional)
- the date we mail the letter
- format YYYY-MM-DD
- leave this field empty to send order ASAP: we schedule it 3 business days
out, counting only working days. Weekends and the holidays we observe are
skipped, since those are the days mail does not move. An order placed the
Tuesday before a Thursday holiday, for example, is scheduled for the
following Monday rather than that Friday.
- the earliest date you can ask for is tomorrow. Tomorrow is accepted at every
hour of the day, right up to 23:59 US Eastern; today or earlier is rejected
with a validation error
- mail only leaves on working days, so a date landing on a weekend or a
holiday we observe is moved forward to the next working day rather than
being rejected. Asking for Saturday the 8th gets you Monday the 10th
- the create response echoes the send_on we recorded, so read it back from
the response rather than assuming the date you sent was stored verbatim
letter_template_id: integer (optional)
- accepted values
- see the list letter-templates endpoint
- arguments passed in the create order payload will override the template attributes
uid: string (optional)
metadata: string (optional)
- attach key-value data to your order objects
- each key should be sent separately
- example: -d 'metadata[key_name]=key_value'
response: if successfully created, the newly created order object. If validations failed, returns an errors object
example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X POST https://dashboard.ignitepost.com/api/v1/orders -d 'message=Thank you for your business' -d 'font=pea' -d 'image=thank_you' -d 'image_inside=happy_birthday' -d 'image_backside=congratulations' -d 'recipient_name=Stan Marsh' -d 'recipient_address_one=1st Main str' -d 'recipient_city=South Park' -d 'recipient_state=CO' -d 'recipient_zip=12345' -d 'metadata[key1]=value1' -d 'metadata[key2]=value2'
Preview note
- endpoint: POST https://dashboard.ignitepost.com/api/v1/preview
- arguments:
font: string (required)
message: string (required)
image: string (required - this argument can be:
a known IgnitePost image-key
an image url)
image_inside: string (required - this argument can be:
a known IgnitePost image-key
an image url)
image_backside: string (required - this argument can be:
a known IgnitePost image-key
an image url)
transparent_background: boolean (optional - defaults to false)
When true, the front, inside, inside_image, backside_image, and envelope
preview images are returned as PNGs with a transparent background instead
of opaque white JPEGs.
- response - returns a list of images urls:
{
"front": "http://ignitepost.com/front.jpg",
"inside": "http://ignitepost.com/inside.jpg",
"inside_image": "http://ignitepost.com/inside_image.jpg",
"backside_image": "http://ignitepost.com/back_image.jpg"
}
Note: when transparent_background is true, the preview blobs are uploaded with Content-Type: image/png (instead of image/jpeg).
- example:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X POST https://dashboard.ignitepost.com/api/v1/preview -d 'message=Lorem ipsum dolor sit amet' -d 'font=pea' -d 'image=thank_you' -d 'image_inside=happy_birthday' -d 'image_backside=congratulations'
- example with a transparent background:
curl -H "X-TOKEN: aVaLIdAP1t0kEN" -X POST https://dashboard.ignitepost.com/api/v1/preview -d 'message=Lorem ipsum dolor sit amet' -d 'font=pea' -d 'image=thank_you' -d 'image_inside=happy_birthday' -d 'image_backside=congratulations' -d 'transparent_background=true'
Webhooks
Rather than polling us for the state of an order, you can have us tell you: when one of
your orders is fulfilled - the card written and handed over to be mailed - we send a
POST request to a URL of your choosing. Order fulfilment is currently the only event
that triggers a webhook.
Setting one up
An endpoint can live in three places, and exactly one of them is used for any given order. We pick the most specific one that applies:
- the Shopify flow the order came from, if that flow has an endpoint set
- otherwise, the letter template the order was created from, if that template has an endpoint set
- otherwise, the account-level webhooks you set up at profile/Webhooks
Only that one is notified. An order created from a letter template that carries its own endpoint does not also reach your account-level webhooks, which is worth keeping in mind if you set up both and see fewer deliveries than you expected. Account-level webhooks are the only tier that can hold several endpoints at once; when they apply, every one of them is notified.
The request
A delivery is sent when the order is fulfilled, not when it is created. Orders are usually fulfilled days after they are created, so expect the webhook then rather than in response to the call that created the order.
POST https://your-endpoint.example.com/hook
Content-Type: application/json
Accept: application/json
Every endpoint is sent these headers: account-level webhooks, letter templates and Shopify flows alike.
The body is the fulfilled order, JSON-encoded:
{
"id": 1242,
"letter_template_id": 183,
"message": "Congratulations! So happy to see you accomplishing great things!",
"font": "becca",
"insert": null,
"image_url": "https://.../1x1_transparent.png",
"inside_image_url": "https://.../1x1_transparent.png",
"backside_image_url": "https://.../1x1_transparent.png",
"metadata": {
"uid": "abc123",
"any extra data submitted upon creation": "will be returned here"
},
"uid": "abc123",
"recipient_name": "John Doe",
"recipient_email": "john@acmeinc.com",
"recipient_company_name": "Acme Inc.",
"recipient_address_one": "12 Galactic Lane",
"recipient_address_two": "Unit 3",
"recipient_city": "Capital City",
"recipient_state": "CA",
"recipient_zip": "12345",
"recipient_country": "US",
"sender_name": "Jane Doe",
"sender_address_one": "10880 Malibu Point",
"sender_address_two": null,
"sender_city": null,
"sender_state": "CA",
"sender_zip": "54321",
"sender_country": "US",
"created_at": "2026-09-06 11:11:24 UTC",
"send_on": "2026-09-14",
"sent_at": "2026-09-09 11:11:24 UTC",
"sent_at_unix": "1788952284"
}
Those are the fields of the Order object, plus three worth calling out:
sent_at: datetime - When the order was fulfilled
sent_at_unix: string - The same moment as a Unix timestamp, for systems that would
rather not parse the date
letter_template_id: integer - The template the order was created from, if any
uid: string - Your own identifier for the order, if you set one on create. This is
usually what you want to match the delivery against your own records
Responding
Reply with any 2xx status to acknowledge a delivery. We record the status code and
body of your response either way, so a non-2xx reply is a useful place to leave a
reason.
Failed deliveries are retried. If you answer with a non-2xx status, take too long
to answer, or cannot be reached at all, we try again, waiting longer before each retry.
A delivery gets up to 5 attempts in total, spread over roughly six minutes, and we stop
as soon as one succeeds.
If all 5 attempts fail, we don't try again automatically. An outage on your side that lasts longer than a few minutes can therefore still cost you deliveries. Get in touch and we can re-send them. Polling Retrieve an order is the more robust option if you cannot afford to miss one.
Make your handler safe to receive the same delivery twice. If your endpoint processes
a delivery but takes too long to answer, we record a timeout and send it again. Key your
handler on the order id, or on your own uid, so a repeated delivery is not
double-counted.
Testing your endpoint
Each webhook on profile/Webhooks
has a Show Test Code link that gives you a curl command reproducing exactly what
we send to that endpoint - same headers, same payload shape - so you can exercise your
handler without waiting for a real order to be fulfilled.
Known Issues
We'll be listing here any issues that are brought to our attention until we can fix them.