User guide

API reference


Send a single email

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.

Example request with curl

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"

Authentication headers

In order to authenticate yourself to the service, you need to use the X-Postmark-Server-Tokenheader 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.

Example header

X-Postmark-Server-Token: server token

JSON message format

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.

  • You must have a registered and confirmed sender signature with the sender email. Otherwise you will receive an HTTP Response 422 (Unprocessable Entity).
  • It’s possible to override the 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. 
  • You can pass multiple recipient addresses in the ToCc, and Bcc fields. Multiple addresses are comma separated and have a limit of 50 max recipients per message. This means that all recipients (ToCc, and Bcc) are totaled and not allowed to exceed 50.
  • You can categorize outgoing email using the 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.
  • You can add metadata to an email using the Metadata property.
  • For email addresses that have names or titles with punctuation, you should quote them as such: "To" : "\"Joe Receiver, Jr.\" <receiver@example.com>"
  • To send an email with a custom Message-ID header, you can pass the value you desire into the headers array: "Headers": [{"Name":"Message-ID", "Value": "<my-id-123@example.com>"}]
  • MessageStream will default to the outbound message stream ID (Default Transactional Stream) if no message stream ID is provided.
  • The subject character limit is 2000 chars, and the “From address character limit is 255. For calculating the length we count the number of UTF-16 code points, when the Unicode points are in the range of 0000 - FFFF they’re counted as 1, and when the Unicode points are above FFFF they’re counted as 2.

Example JSON message format

  "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": {
  "Headers": [
      "Name": "CUSTOM-HEADER",
      "Value": "value"
  "TrackOpens": true,
  "TrackLinks": "HtmlOnly",
  "MessageStream": "outbound"

Tracking opens

There are three ways that you can activate open tracking for your emails:

Example API request with open tracking

  "TrackOpens" : true

Tracking links

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.

Learn more about Link Tracking.

Example API request with link tracking

  "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:

  • Forbidden File Types: vbs, exe, bin, bat, chm, com, cpl, crt, hlp, hta, inf, ins, isp, jse, lnk, mdb, pcd, pif, reg, scr, sct, shs, vbe, vba, wsf, wsh, wsl, msc, msi, msp, mst.

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.NETPHPRuby


  • If a file type with a disallowed extension is detected, the message will be rejected — or if using SMTP you will receive an SMTP API bounce.
  • Messages have some size limitations, which if exceeded will cause the message to be rejected:
    • The TextBody and HtmlBody can be up to 5MB each.
    • Total message size, including attachments, can be up to 10MB total. This can be as a single attachment, or many attachments that together don’t exceed 10MB. Please note: Base64-encoded strings may make your data seem larger than it really is, but Postmark calculates the attachment size after Base64-encoding.
  • We recommend sending emails with attachments from a background job, rather than as a response to a user action in the same web request handler. This is because an increased message size will take longer to submit to the Postmark servers. Your users will love you for that!

Example message with attachments

  "Attachments": [
      "Name": "readme.txt",
      "Content": "dGVzdCBjb250ZW50",
      "ContentType": "text/plain"
      "Name": "report.pdf",
      "Content": "dGVzdCBjb250ZW50",
      "ContentType": "application/octet-stream"

Inline image attachments

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.

Example message with an inline image attachment

Example message with an inline image attachment

  "Attachments": [
      "Name": "bacon.jpg",
      "Content": "/9j/4AAQSkZJRgABAgEAAAAAAAD/4",
      "ContentType": "image/jpeg",
      "ContentID": "cid:part1.01030607.06070005@gmail.com"

HTML inline image example

<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.

Example JSON response

  "ErrorCode": 0,
  "Message": "OK",
  "MessageID": "b7bc2f4a-e38e-4336-af7d-e6c392c2f817",
  "SubmittedAt": "2010-11-26T12:01:05.1794748-05:00",
  "To": "receiver@example.com"

Retrieving Attachments

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.