Skip to content
← Community packages

Send transactional email and manage Postmark servers, domains, and message search with dry-run mutations.

Browse files

  • Other
  • postmark
  • email
  • transactional
  • servers
  • domains
  • messages
  • search
  • dry-run
License
MIT
Published
August 22, 2026
Pinned commit
d6b8701
Rating
No ratings yet
Forks
0
Stars
0
Adaptation effort

README

@kody/postmark

Intent

Reusable Postmark helpers so Kody agents can send transactional email, inspect the current server, manage account servers and sending domains, and search outbound or inbound messages on the caller's Postmark account — not a shared platform inbox. Auth is a saved Server API token by default. Reads are free-form; mutations support dryRun: true, and sends or deletes also require confirm: true.

This listing is meant to be forked. After you fork, save your own postmark credential and call the helpers in your account. There are no baked-in server tokens or from-addresses.

Agent setup

Default auth is a Postmark Server API token (secret-backed). There is no built-in platform OAuth app. Do not paste the token into chat.

  1. Open a server at account.postmarkapp.com/servers and copy the Server API token from its API Tokens tab. Sending also needs a confirmed sender signature or verified domain on that server.
  2. Save it in Kody:

https://kody.codes/account/secrets/new?name=postmark&description=Postmark%20Server%20API%20token%20for%20sending%2C%20the%20current%20server%2C%20and%20message%20search&allowedHosts=api.postmarkapp.com&scope=user

  1. In the account secrets UI, approve host api.postmarkapp.com. Saving the secret does not approve hosts by itself.

Optional Account API token

Listing every server, creating/deleting servers, and managing domains use X-Postmark-Account-Token. Copy that token from the account API Tokens tab (Account Owner / Admin only):

https://kody.codes/account/secrets/new?name=postmark-account&description=Postmark%20Account%20API%20token%20for%20listing%20servers%20and%20managing%20domains&allowedHosts=api.postmarkapp.com&scope=user

GET /server, sending, and message search stay on the Server token.

Multi-account

There are no hard-coded account aliases:

  • account: "work" reads secrets postmark-work and postmark-account-work
  • or pass secretName: "postmark-work" / accountSecretName: "postmark-account-work"

https://kody.codes/account/secrets/new?name=postmark-work&description=Postmark%20Server%20API%20token%20for%20the%20work%20account&allowedHosts=api.postmarkapp.com&scope=user

https://kody.codes/account/secrets/new?name=postmark-account-work&description=Postmark%20Account%20API%20token%20for%20the%20work%20account&allowedHosts=api.postmarkapp.com&scope=user

Hosts, 401, and 422

StatusMeaningNext step
401Missing, invalid, or wrong token typeSave postmark (or postmark-account for /servers and /domains) at the secrets URL
422 + senderfrom is not a confirmed senderConfirm a sender signature or verify the domain, then pass from at call time
422 + streammessageStream does not exist on this serverOmit it (defaults to outbound) or pass a stream id from the server
429Rate limitBack off; batch with sendBatch when sending many messages

Approve api.postmarkapp.com on the secret. Host approval lives in the account security UI.

Mutation safety

  • Pass dryRun: true on any mutation to return { dryRun: true, method, path, body, tokenKind } without contacting Postmark.
  • sendEmail, sendBatch, sendTemplateEmail, deleteServer, deleteDomain, and rotateDkim also throw unless confirm: true.
  • This package never stores a default from. Pass the confirmed sender at call time.
  • Server payloads strip ApiTokens so tokens cannot leak through helpers.
import { sendEmail } from 'kody:@kody/postmark/emails'

const preview = await sendEmail({
	from: 'Name <hello@yourdomain.com>',
	to: 'person@example.com',
	subject: 'Hello from Kody',
	htmlBody: '<p>It works!</p>',
	dryRun: true,
})

const sent = await sendEmail({
	from: 'Name <hello@yourdomain.com>',
	to: 'person@example.com',
	subject: 'Hello from Kody',
	htmlBody: '<p>It works!</p>',
	confirm: true,
})

Exports

  • kody:@kody/postmark — action dispatcher (defaults to smoke-test); also re-exports every helper below
  • kody:@kody/postmark/emails — send, batch, and template send
  • kody:@kody/postmark/servers — current server (Server token) plus account server list/create/edit/delete
  • kody:@kody/postmark/domains — list, create, verify DKIM / Return-Path, delete
  • kody:@kody/postmark/messages — outbound and inbound search plus details
  • kody:@kody/postmark/smoke-test — dry-run self-check, then a live server and recent-message read when credentials exist
  • kody:@kody/postmark/scheduled-server-health — no-argument read-only wrapper for the disabled server-health job

Low-level transport (postmarkRequest, postmarkCall, PostmarkApiError) stays pinned to https://api.postmarkapp.com. postmarkCall writes default to dry-run until you pass dryRun: false.

The package-owned server-health job starts with "enabled": false.

Smoke test

import { smokeTest } from 'kody:@kody/postmark'

export default async function main() {
	return await smokeTest()
}

Without a postmark secret this still returns { ok: true, live: false } plus the setup URLs. With a Server API token it reads the current server and one page of recent outbound messages — no writes and no live email.

Share https://kody.codes/@kody/postmark — never a /community/{listing_id} URL.

Import the official package as kody:@kody/postmark. Do not invoke a personal postmark kody id; that can resolve a different account package.

Example

import postmark from 'kody:@kody/postmark'

export default async function main() {
	return await postmark({ action: 'get-server' })
}

Branding

community-icon.svg uses Postmark's official stamp from postmarkapp.com/images/logo-stamp-simple.svg (yellow #FFDE00 scalloped mark and letter). The paths are unmodified. Postmark® is a trademark of ActiveCampaign, LLC. This package is not affiliated with or endorsed by Postmark or ActiveCampaign.

Docs

Report this listing

Log in to report this listing.