Skip to main content
The postmark__email service sends transactional email: the notification, the receipt, the alert, the question a person is expected to answer. Two steps ship, both authored on the same shared REST foundation every other integration uses, and both authenticated by selecting a credential rather than by pasting a key into a step.
Marketing email is out of scope, deliberately. There are no campaigns, no bulk template rendering and no open/click analytics surface here. A step sends one message to a named set of recipients; a flow that mails a list does it by running that step per record, which is what keeps one bad address from failing everybody else’s mail.

The two steps

There is no third step for reading an attachment, and its absence is the design rather than a gap. When a reply arrives, its attachments are stored at that moment and the flow is handed a file reference for each one — so there is nothing left to fetch. Read the file with getdialed__files__read_text, or hand its file_id straight to getdialed__records__parse_csv. The send-and-wait guide walks the whole chain.

Sending

postmark__email__send takes recipients and a message: The 50-per-field cap is Postmark’s, and a send that exceeds it is refused before the request leaves — so an over-large recipient list costs no send and no pacing budget. The whole message, including anything attached, may not exceed 10 MB. It reports:
No output field can carry a recipient address, and that is structural rather than a convention. Step outputs are persisted into the platform’s run history, which outlives whatever retention rule governed the recipient list — an address there could never be redacted afterwards. So suppression is reported as counts, never as the addresses themselves, and there is no field on this step that could hold one. The same rule governs failure messages: a refusal names the reason and the count, never the address.Postmark itself is less careful — it echoes recipients back on a successful send and names skipped addresses in its own prose. Those are read here only to be counted, and the count is the only thing that leaves the step.

Connecting Postmark

The credential is a Postmark server token — not an account token. Create it as an api_key credential whose key is presented as an X-Postmark-Server-Token header:
GetDialed calls Postmark with the token, reads back which Server it belongs to, and files the credential under that server — you never look up or type a provider identifier. See platform tenancy for what that record owns.
One credential is one Postmark server, and the boundary matters more here than it looks. A server token can read that server’s own message history, including message content Postmark retains after delivery. So the server is the isolation boundary, not just the budget key: one server per account is what keeps one customer’s mail out of another’s reach. A token that covered several accounts’ mail would be a content leak rather than a shared allowance.

Where mail is sent from

Postmark checks that you are entitled to the from address on every send, in one of two ways.

Sender signature

A sender signature is a single address Postmark has confirmed — it emails the address and somebody clicks the link. Nothing to publish in DNS, and you can send the first message minutes after confirming it. It is the right choice for trying the integration out and for internal notifications from one fixed address. A signature covers that address only. A flow that sends from several addresses on the same domain wants a verified domain instead.

Verified sending domain

Verify the whole domain and any address on it can send. Postmark generates the DNS records; you publish them and then ask Postmark to verify. Two matter for sending: Publish an SPF and a DMARC record for the domain too. Neither is Postmark-specific and neither is generated for you, but a domain sending real mail without them will land in spam folders that a verified domain would not.

Receiving replies

Reply-waiting steps additionally need an inbound domain, and it is a separate piece of configuration from the sending one:
  • The domain is bound as an inbound domain on the server your credential belongs to.
  • Its MX record points at inbound.postmarkapp.com.
That MX record takes over the domain’s mail. Use a dedicated subdomain — never an apex that already receives mail.Publishing it on a domain that already receives mail — your company’s main domain, the one your staff read their inbox on — hands that mail to Postmark and stops it reaching your existing mail provider. This is the single most expensive mistake available on this page and it is not reversible in the minutes it takes to notice.Create a subdomain for the purpose (reply.example.com, mail.example.com) and bind that. A subdomain has no existing mail to lose, and it keeps your reply address obviously distinct from a human mailbox.
You only need an inbound domain if you intend to use send and wait for a reply. A send-only setup needs no MX change at all.
An inbound domain binds to exactly one server. That is a Postmark constraint, and it is worth knowing before you plan around it: two servers cannot share one reply domain, so a second server needs its own subdomain.

Suppressed recipients

Postmark maintains a suppression list per server: addresses that hard-bounced or reported spam are marked inactive, and Postmark will not deliver to them. GetDialed exposes no way to bypass that. There is no parameter, no flag and no override — that is the design, not a missing feature. What GetDialed adds is that you always find out. Suppression arrives in three shapes and none of them is reported as a clean success: That last row is the one worth internalising, and Postmark makes it easy to miss. It answers a partially suppressed send with a 200 and its own success error code — the same status line as a perfect send — and names the skipped addresses only in a free-text sentence. Reported as success it would look identical to a fully delivered message everywhere downstream, so the count is extracted and reported instead. The same is true of a fully suppressed send: Postmark may answer it with a success status line and an empty delivery, or with a 422. Both are the same outcome — nothing was delivered — so both fail under the same name, rather than one being a failure and the other a success with a suspicious count.
A count, not a reason list. Postmark publishes no reason vocabulary for a skipped recipient — it reports the fact in prose and nothing else — so this step carries no suppressed_reasons field. An always-empty reasons field would read as “no suppression happened”, which is exactly the misreading the count exists to prevent.Because that prose is the entire detection mechanism and it is Postmark’s to reword at any time, a message this step cannot interpret sets message_unrecognized and logs a warning rather than passing as clean. A rewording is then visible in your flow, instead of turning every mixed send into a silent success.
To change any of this, review the inactive recipients on your own Postmark server. Nothing in a flow can reach past it.

Pacing, and sending exactly once

Sends are paced, and the pacing is the dispatcher’s job rather than the step’s. Every email call draws from the Email rate bucket on your Postmark Server record, spends it in the interactive lane, and waits rather than failing when the budget is spent. A transactional email is user-visible latency — somebody is waiting on the password reset — which is why it sits in the lane reserved for work a person is watching, and not behind a bulk record load.
The published cap for email is ours, not Postmark’s. Postmark’s rate-limit response headers describe API request throughput per second, not the mail-volume budget this cap governs, so they are not used as send limits. The catalog ships a deliberately conservative GetDialed default that errs low: too low costs latency, while too high costs throttling and a reputation hit on a sending domain, which no later correction undoes. The value is corrected from observed pacing behaviour and written onto the Server record, the same way every other provider cap is.
A send is never retried automatically. Both send steps declare retry_safety: at_most_once in the catalog, which routes them to a single-attempt policy: if the answer to a send is lost in transit, the platform does not send again to find out. A duplicate email cannot be recalled, and for a send-and-wait a duplicate would be worse than an extra message — it would create a second reply address for a wait that only one of them can resume, so the human could answer the copy nothing is listening on.Postmark publishes no idempotency key, so unlike some providers there is no second line of defence at the provider’s end. The single-attempt declaration is the whole of the guarantee.

Quiet hours do not apply to email

Email carries no send-time restriction here, and that is a deliberate position rather than a gap. Quiet-hours rules are an obligation on calls and text messages; email sits under different rules that impose no time-of-day restriction on sending. So there is no quiet-hours gate on an email step, and none is coming for email. If your own policy says a particular flow should not mail people overnight, express it with the windowed execution model, which confines a task to a recurring local-time window and will wait until the window next opens.

Next steps

Human in the loop

Pause a flow until a person replies, and what lands in context when they do.

Send and wait for a reply

The end-to-end walkthrough: ask for a CSV, wait, parse it, fan out.

Credentials

Create the Postmark credential these steps select.

Dispatch pacing

How sends are paced against your server’s budget, and what a pause holds.