First-party app
Postmark

Postmark

Send transactional email and inspect messages, bounces, templates, and server info via Postmark.

stable EmailCommunication

About

Postmark ships in the w6w first-party pack. It declares 13 actions, 2 health checks, and the host runs its code in a sandbox that never sees the credential.

App id
io.w6w.postmark
Version
0.1.2
Author
w6w
Licence
MIT
Categories
Email · Communication

Overview

Postmark sends transactional email and gives visibility into what happened to it after. Send a single message, a batch, or one built from a template, then look up a specific outbound message, see who opened it, and check bounce details — including reactivating an address that bounced once the underlying problem is fixed.

Server-level actions cover the day-to-day work a sending server needs: server configuration and stats, plus creating and listing the templates a send can reference. Account-level operations — provisioning new servers, verifying sending domains, billing — stay out of scope, since those are occasional admin tasks rather than something a workflow should trigger.

Good for transactional email from an app — receipts, password resets, notifications — with enough visibility into delivery and bounces to react when something didn’t arrive, without leaving the workflow to check the Postmark dashboard by hand.

Build with Postmark

Three routes to the same 13 actions. The Workflow tab is generated from Postmark's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.

Activate Bounce

activate-bounce

Reactivate a deactivated recipient address for a specific bounce.

Create Template

create-template

Create a new email template or layout on this server.

Get Bounce

get-bounce

Get full details for a single bounce by ID.

Get Outbound Message

get-outbound-message

Get full details (body, status, delivery events) for one outbound message by ID.

Get Outbound Stats

get-outbound-stats

Get an outbound sending overview: sent, bounced, opens, clicks, spam complaints.

Get Server Info

get-server-info

Get this server's configuration (name, tracking defaults, webhook URLs, ...).

List Bounces

list-bounces

Search this server's bounce log.

List Message Opens

list-message-opens

List open-tracking events for sent messages.

List Outbound Messages

list-outbound-messages

Search sent (outbound) messages by recipient, tag, status, subject, or date range.

List Templates

list-templates

List this server's saved templates and layouts.

Send Email

send-email

Send a single transactional email via Postmark. Provide `htmlBody` or `textBody`.

Send Email Batch

send-email-batch

Send up to 500 emails in one call. Each result carries its own ErrorCode — a 200 response does not mean every message succeeded.

Send Email with Template

send-email-with-template

Send a transactional email rendered from a saved Postmark template.

A workflow step names the app and the action, and the editor fills in the connection when you pick one. This is the Step shape from the workflow spec, carrying Postmark's real ids.

{
  "manifestVersion": "2",
  "name": "postmark-example",
  "steps": [
    {
      "id": "activate-bounce",
      "uses": {
        "app": "io.w6w.postmark",
        "action": "activate-bounce",
        "connection": "conn_YOUR_CONNECTION_ID"
      },
      "with": {
        "bounceId": "<bounceId>"
      }
    }
  ]
}

Here are some of the things you can do

  • Activate Bounce

    perform
    activate-bounce
  • Create Template

    perform
    create-template
  • Get Bounce

    read
    get-bounce
  • Get Outbound Message

    read
    get-outbound-message
  • Get Outbound Stats

    read
    get-outbound-stats

+8 more actions available

Every app-specific value here is a blank you have to fill in. An app action is reached through the connection that authenticates it, so the address is a connection id, not the app id — and connections belong to your account, so a public page cannot know yours. Create one for Postmark, then fill in the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the parameters that action declares. The call itself is real — the shape is transcribed from the studio's own snippet builder, which prints the same kind of blanks — but nothing in it is specific to Postmark. The Workflow tab is where this app's real ids are.

Install
npm install @w6w/sdk
yarn add @w6w/sdk
pnpm add @w6w/sdk
deno add npm:@w6w/sdk
Code
import { W6wClient, isActionRun } from "@w6w/sdk";

// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();

const envelope = await client.run({
  urn: "conn_YOUR_CONNECTION_ID",
  action: "send-email",
  payload: {
    from: "<value>",
    to: "<value>",
    // cc: "<value>",
    // bcc: "<value>",
    // subject: "<value>",
    // htmlBody: "<value>",
    // textBody: "<value>",
    // tag: "<value>",
    // replyTo: "<value>",
    // trackOpens: "<value>",
    // trackLinks: "<value>",
    // headers: "<value>",
    // attachments: "<value>",
    // metadata: "<value>",
    // messageStream: "<value>",
  },
});

if (isActionRun(envelope)) console.log(envelope.value);
Install the CLI
npm install -g @w6w/cli
CLI
w6w run conn_YOUR_CONNECTION_ID --action send-email --payload '{"from":"<value>","to":"<value>"}'

Give an AI agent Postmark — without giving it Postmark's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.

One tool call
{
  "name": "w6w_invoke",
  "arguments": {
    "ref": "app:io.w6w.postmark#activate-bounce",
    "input": {
      "bounceId": "<bounceId>"
    }
  }
}

Every tool names its target with a single ref. The app: form above doesn't name a connection at all — the host resolves which of the caller's Postmark connections to sign with, and refuses rather than guesses when the answer is ambiguous.

What the agent gets

Credentials it can't read

The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.

A tool surface scoped to the caller

Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.

A durable workflow in one call

Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.

Health-aware discovery

Postmark's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.

The MCP surface is part of the hosted platform. Postmark itself is MIT, and the runtime that executes it is source-available (FSL).

Request MCP access

Health checks

Postmark declares its own checks, so its health is a property of the app rather than something the host guesses at.

service

Postmark platform status

status.postmarkapp.com's own JSON status API (/api/v1/status + /api/v1/components), with per-component detail. Unauthenticated and unsigned.

quota

Sending quota headroom