Sending single emails through Postmark is as simple as sending an HTTP POST request to our /email endpoint with the JSON message attached to the body.
curl "https://api.postmarkapp.com/email" \
-X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-Postmark-Server-Token: server token" \
-d '{
"From": "sender@example.com",
"To": "receiver@example.com",
"Subject": "Postmark test",
"TextBody": "Hello dear Postmark user.",
"HtmlBody": "<html><body><strong>Hello</strong> dear Postmark user.</body></html>",
"MessageStream": "outbound"
}'
In order to authenticate yourself to the service, you need to use the X-Postmark-Server-Token
header for authentication and authorization. Each Postmark server has its own API token, allowing you to isolate access and data for each application that connects to Postmark.
The header name and value are case insensitive. Should you execute the request with wrong or missing headers, you will receive an HTTP Response 401 (Unauthorized).
For testing purposes, Postmark lets you send test emails that won’t actually get delivered to the recipient. This method is typically used to verify that your data is valid. You can do this by passing POSTMARK_API_TEST
as your server API token.
X-Postmark-Server-Token: server token
JSON messages are passed in the body of the HTTP POST request. The From
and To
fields are able to accept name, in the format of John Doe <email@example.com>
. You can provide HtmlBody
for HTML formatted messages, TextBody
for plain text, or include both for multipart. Multipart sends HTML with a text version for clients that don’t support HTML. Passing headers is optional.
Name
in the sender signature through the API. This is useful if you want to use member’s information in the email while keeping your From
email address. Just pass the name into the From
field, "From": "John Smith <sender@example.com>"
. This also applies to the To
, Cc
, and Bcc
fields. To
, Cc
, and Bcc
fields. Multiple addresses are comma separated and have a limit of 50 max recipients per message. This means that all recipients (To
, Cc
, and Bcc
) are totaled and not allowed to exceed 50.Tag
property. This enables you to get detailed statistics for all of your tagged emails. Only one tag may be used for each message. The maximum Tag size is 1000 characters.Metadata
property."To" : "\"Joe Receiver, Jr.\" <receiver@example.com>"
"Headers": [{"Name":"Message-ID", "Value": "<my-id-123@example.com>"}]
{
"From": "sender@example.com",
"To": "receiver@example.com",
"Cc": "copied@example.com",
"Bcc": "blank-copied@example.com",
"Subject": "Test",
"Tag": "Invitation",
"HtmlBody": "<b>Hello</b>",
"TextBody": "Hello",
"ReplyTo": "reply@example.com",
"Metadata": {
"Color":"blue",
"Client-Id":"12345"
},
"Headers": [
{
"Name": "CUSTOM-HEADER",
"Value": "value"
}
],
"TrackOpens": true,
"TrackLinks": "HtmlOnly",
"MessageStream": "outbound"
}
There are three ways that you can activate open tracking for your emails:
{
...
"TrackOpens" : true
}
You can enable Link Tracking to get information about the links your recipients click in your emails. Link tracking can be enabled on a per-message or per-server basis.
{
...
"TrackLinks" : "HtmlAndText"
}
Attachments are specified in the Attachments
array in the JSON message. Individual attachments can then be stored as separate objects within that array.
The Name
field is the actual filename that will be displayed to the message recipient. To eliminate the possibility of spreading viruses or spyware we disallow certain file types:
The ContentType
field is the MIME content type that email clients use to interpret the attachment.
The Content
field stores the binary data for the file, which must be transmitted as a base64-encoded string. Most programming languages and libraries have this built in e.g. Java, .NET, PHP, Ruby
Limitations:
TextBody
and HtmlBody
can be up to 5MB each.{
...
"Attachments": [
{
"Name": "readme.txt",
"Content": "dGVzdCBjb250ZW50",
"ContentType": "text/plain"
},
{
"Name": "report.pdf",
"Content": "dGVzdCBjb250ZW50",
"ContentType": "application/octet-stream"
}
]
}
Postmark also allows you to send inline images via HTML messages. Images must be base64-encoded and the ContentID
field must match the image's CID.
Postmark will then automatically embed the images inline with your HTML as long as the CID tags match. NOTE: If you are referring to an attached image more than once in your message, it is only required to attach the image one time. Postmark will use the image as often as it is referred to in your HTML markup. This will save bandwidth against the attachment size limit.
{
...
"Attachments": [
{
"Name": "bacon.jpg",
"Content": "/9j/4AAQSkZJRgABAgEAAAAAAAD/4",
"ContentType": "image/jpeg",
"ContentID": "cid:part1.01030607.06070005@gmail.com"
}
]
}
<img src="cid:part1.01030607.06070005@gmail.com">
If all goes well, you will receive a JSON message looking like the example.
The MessageID
field can be used to log in your system. It can then be used to associate the message you sent to a possible bounce that you obtained from a bounce webhook or the bounce API.
See a full list of API errors for more details.
{
"ErrorCode": 0,
"Message": "OK",
"MessageID": "b7bc2f4a-e38e-4336-af7d-e6c392c2f817",
"SubmittedAt": "2010-11-26T12:01:05.1794748-05:00",
"To": "receiver@example.com"
}
Attachments are not retrievable via the Postmark UI, API, or webhooks as Postmark does not host the attachment in any way. More on that here.
We understand that developers with higher volumes or processing time constraints need to send their messages in batches. To facilitate this we provide a batching endpoint that permits you to send up to 500 well-formed Postmark messages in a single API call. If you are sending Broadcast (bulk) messages with the batch call, use the MessageStream field to set your sending Stream.
Please note that the batch endpoint accepts up to 500 messages per API call, and up to 50 MB payload size, including attachments.
The format of the batched message is a JSON array containing multiple message requests.
Batch request examples can be seen here.
curl "https://api.postmarkapp.com/email/batch" \
-X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-Postmark-Server-Token: server token" \
-d '[{
"From": "sender@example.com",
"To": "receiver1@example.com",
"Subject": "Postmark test #1",
"TextBody": "Hello dear Postmark user.",
"HtmlBody": "<html><body><strong>Hello</strong> dear Postmark user.</body></html>",
"MessageStream": "outbound"
},
{
"From": "sender@example.com",
"To": "receiver2@example.com",
"Subject": "Postmark test #2",
"TextBody": "Hello dear Postmark user.",
"HtmlBody": "<html><body><strong>Hello</strong> dear Postmark user.</body></html>",
"MessageStream": "outbound"
}
]'
Similarly, you will receive a matching JSON array containing each response for the messages you sent in your batched call.
See a full list of API errors for more details.
[
{
"ErrorCode": 0,
"Message": "OK",
"MessageID": "b7bc2f4a-e38e-4336-af7d-e6c392c2f817",
"SubmittedAt": "2010-11-26T12:01:05.1794748-05:00",
"To": "receiver1@example.com"
},
{
"ErrorCode": 0,
"Message": "OK",
"MessageID": "e2ecbbfc-fe12-463d-b933-9fe22915106d",
"SubmittedAt": "2010-11-26T12:01:05.1794748-05:00",
"To": "receiver2@example.com"
}
]