Using the Letterhead API
Edit in CMSThe Letterhead API lets you work with your newsletters from your own code — your audience, your content, your sending, and your reporting. Everything you can do in the dashboard, you can build around.
Authentication
Section titled “Authentication”Every request needs an API key sent as a Bearer token in the Authorization header:
Authorization: Bearer <your-api-key>One key reaches every newsletter in your account, so you don’t need a separate key per newsletter. See Generate & manage API keys to create one.
Most read endpoints also expect api=true in the query string. It tells Letterhead you’re
authenticating with a key rather than a signed-in session, and the reference notes it wherever it
applies.
Base URL
Section titled “Base URL”Requests go to the same subdomain you sign in with — just swap api in for app:
- If you sign in at
https://{yourPrefix}.app.tryletterhead.com, your API base URL ishttps://{yourPrefix}.api.tryletterhead.com. For example,acme.app.tryletterhead.combecomesacme.api.tryletterhead.com. - If you sign in at the plain
https://app.tryletterhead.com(no subdomain), your API base URL is the plainhttps://api.tryletterhead.com.
What you can build
Section titled “What you can build”- Your audience — add, update, and remove contacts, set their subscription status per newsletter, and tag people in bulk
- Segments — create and update saved audience groups, count who’s in one, preview the members, and pull engagement over time — or list Letterhead’s built-in system segments (see below) instead of hard-coding their IDs
- Content — push articles into your curation library and distribute them across newsletters, including in bulk for many articles in one request
- Sending — draft a letter from your own HTML or from a template, then send it — see Sending your own HTML for what’s tracked automatically and what can get a send rejected
- Your newsletters — list what you’ve published, across your whole account or a chosen few of your newsletters, and narrow the list to the ones carrying a tag you organize by (see below)
- Promotions — create and manage the paid placements running inside your newsletters
- Reporting — pull opens, clicks, bounces, and unsubscribes, with a daily breakdown and per-newsletter detail
- Audience overlap — shared subscriber counts for every pair of newsletters, and combined unique reach for a selection
Filtering your newsletters by tag
Section titled “Filtering your newsletters by tag”If you organize your newsletters with tags, you can ask for just the ones carrying a tag rather than pulling everything and sorting it out in your own code.
First list your tags to get their ids, then pass those ids when you list your newsletters:
GET /api/v3/letters/tags?api=trueGET /api/v3/letters?api=true&allChannels=true&tags[]=<tagId>Two things worth knowing before you build against it:
- Naming more than one tag narrows the list, it doesn’t widen it. Asking for two tags returns the newsletters carrying both of them, not the ones carrying either. To gather everything across several tags, ask for one tag at a time and combine the results yourself.
- You can name up to 50 tags in a request, and the filter works the same way whichever set you’re listing — your templates, a chosen few newsletters, or everything at once.
The same filter works when you pull performance numbers for many newsletters at once. The metrics request
takes its tags inside a filters object, and the total it returns counts only the newsletters that match:
POST /api/v3/letters/metrics?api=true{ "filters": { "tags": ["<tagId>"] } }Each tag must be sent as its id, as text, exactly as the tag list returns it — a number, an empty entry, or more than 50 tags is rejected rather than quietly ignored.
Listing the built-in system segments
Section titled “Listing the built-in system segments”Alongside the segments you build yourself, every account has a set of built-in, read-only system segments — Loyalists, New & Engaged, Casual, Fading, Ghosts, Single Newsletter, Everyone but Ghosts, and (on some accounts) a 60-day version of Everyone but Ghosts. Each already sends to a reserved numeric ID, but until now the only way to find that number was to copy it out of the app’s URL. List them from their own endpoint instead:
GET /api/v3/contacts/segments/system?api=trueEach entry in the response carries an id — the number to pass as segment when scheduling or sending
a letter — a stable key, and a display name. It’s a separate, read-only listing: it doesn’t affect
GET /api/v3/contacts/segments above, and a system segment can’t be created, updated, or deleted.
Use the TypeScript package
Section titled “Use the TypeScript package”If you’re building in JavaScript or TypeScript, you don’t have to write the requests by hand. Letterhead
publishes an official package, @tryletterhead/sdk, with a ready-made, typed method for every operation in
the API reference. Your editor suggests the methods and tells you what each one takes and returns, and it adds
the api=true flag for you.
npm install @tryletterhead/sdkIt needs Node 18 or later, or any runtime with a built-in fetch. Create an API key as described above, then add a contact and tag them in a few lines:
import { createLetterheadClient } from '@tryletterhead/sdk';
const letterhead = createLetterheadClient({ apiKey: process.env.LETTERHEAD_API_KEY! });
If your account signs in on its own subdomain, pass your API base URL (see above) as baseUrl. When a request
fails, the method throws an error that carries the status and the response, so you can handle it in one place.
Keep your API key on a server. A company API key can read and change your whole audience, and anything in code that runs in a browser is public. Use the package in your own backend or a serverless function, and have a website or React app call that instead — never put the key in front-end code.
When the API changes, the package is updated and released again, so new endpoints arrive in a new version soon after they reach the API reference. Update the package to pick them up. Its page on npm has the full list of methods and more examples.
Use the command line
Section titled “Use the command line”If you’d rather work from a terminal, or from a script, the letterhead command-line tool does the same job
without any code. Every operation in the API reference is a command, so a new endpoint becomes a new command
when the tool is next updated.
npm install -g @tryletterhead/cliexport LETTERHEAD_API_KEY=<your-api-key>
letterhead contacts upsert --email [email protected] --first-name Pat --tag vipletterhead tags add-to-contacts --tag webinar-attendee --email [email protected]It needs Node 18 or later, and reads your API key from the LETTERHEAD_API_KEY environment variable (or
--api-key, which leaves the key in your shell history). If your account signs in on its own subdomain, set
LETTERHEAD_BASE_URL to your API base URL (see above). It never saves your key anywhere.
letterhead --helplists the groups of commands, andletterhead <group> <command> --helpshows what a command takes. A command’s options are the endpoint’s parameters; anything else can be sent as JSON with--body, from a file (--body @contact.json) or standard input (--body -).- Answers print as JSON on standard output. If the API returns an error, the error is printed to standard error and the command exits with a non-zero code, so scripts can tell something went wrong.
- Commands that delete something ask you to type
yeswhen you’re at a terminal. In a script, or anywhere else without one, they refuse unless you add--yes, so nothing is deleted by accident. - Commands that upload a file aren’t supported yet; use the TypeScript package for those.
The same advice as for the package applies: keep your API key out of shared shells and scripts.
Reading these docs from a coding agent
Section titled “Reading these docs from a coding agent”If you’re working with an AI coding agent, you can point it at this documentation in a form it can read without picking apart web pages:
/llms.txtis a short index: what Letterhead is, how to authenticate, where the API description and the TypeScript package live, and a link to every article./llms-full.txtis every article in one Markdown file, for agents that can take it all in at once.- Every article also has a Markdown copy: add
.mdto its address (this page is at/api/using-the-letterhead-api.md). - The full API description is available as an OpenAPI file at
/openapi.yaml.
These contain only the articles anyone can read on this site.
API reference
Section titled “API reference”The complete endpoint reference — paths, parameters, request and response formats, and examples — is in the API reference on this site. It’s generated from the API’s own specification, so it stays in step with what the API actually does.
Next steps
Section titled “Next steps”Still can’t find what you need? Contact support.