courier
Use when building notifications with Courier across email, SMS, push, in-app inbox, Slack, Teams, and WhatsApp: sends, templates, translations, email client…
Skill by trycourier
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/trycourier-courier
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: productivity, agent-building
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/courier
What's inside
- Skill name
courier- Description
- Use when building notifications with Courier across email, SMS, push, in-app inbox, Slack, Teams, and WhatsApp: sends, templates, translations, email client previews, Elemental, journeys, preferences, routing, CLI and MCP.
- License
- MIT
- Instructions
- 244 lines in SKILL.md · view on GitHub
Files (42)
- SKILL.md
- email.md · references/channels/
- inbox.md · references/channels/
- ms-teams.md · references/channels/
- push.md · references/channels/
- slack.md · references/channels/
- sms.md · references/channels/
- whatsapp.md · references/channels/
- audiences.md · references/guides/
- batching.md · references/guides/
- brands.md · references/guides/
- bulk.md · references/guides/
- cli.md · references/guides/
- device-preview.md · references/guides/
- digests.md · references/guides/
- elemental.md · references/guides/
- journeys.md · references/guides/
- localization.md · references/guides/
- mcp.md · references/guides/
- metrics.md · references/guides/
- multi-channel.md · references/guides/
- patterns.md · references/guides/
- preferences.md · references/guides/
- providers.md · references/guides/
- quickstart.md · references/guides/
- reliability.md · references/guides/
- routing-strategies.md · references/guides/
- scheduling.md · references/guides/
- templates-as-code.md · references/guides/
- templates.md · references/guides/
- tenants.md · references/guides/
- throttling.md · references/guides/
- webhooks.md · references/guides/
- auth.md · references/inbox/
- legacy-v7.md · references/inbox/
- react-native.md · references/inbox/
- react.md · references/inbox/
- rendering.md · references/inbox/
- web-components.md · references/inbox/
- lifecycle-marketing.md · references/
- sdk-reference.md · references/
- transactional.md · references/
SKILL.md (first lines)
# Courier
Integrate Courier, add notification features, and debug delivery problems across email, SMS, push, in-app inbox, Slack, Teams, and WhatsApp.
## The Model
One `send` call does the whole job. You address a **user** (or list, audience, or tenant), content comes from a **template** or inline, **routing** picks the channels, and **preferences** gate delivery. Courier renders, routes, and delivers; your app supplies the trigger and the data.
Multi-step flows (anything with a delay, a branch, or aggregation) are **journeys**, defined as JSON and invoked by API.
## How to Use This Skill
1. **Route first.** [Where to Look](#where-to-look) picks the 1–2 files for the task. Don't read the tree.
2. **Ask when the request is ambiguous.** Channel? Transactional or lifecycle? New code or existing? Which language? Skip the questions when the request is already specific.
3. **Verify shapes against a [live source](#verifying-against-live-sources)** rather than memory. The installed SDK's own types are ground truth.
4. **Apply the rules.** [Universal Rules](#universal-rules) and each file's Quick Reference are constraints, not suggestions. (`sdk-reference.md` is a lookup table and has none.)
If the project already has `@trycourier/courier` or `trycourier` installed, skip quickstart's install steps and assume `client` exists.
## Addressing a Send
`message.to` accepts one of:
| Form | Sends to |
|---|---|
| `{ user_id: "user-123" }` | A stored user profile. The usual case |
| `{ email: "…" }` / `{ phone_number: "…" }` | An inline recipient, no profile required |
| `{ list_id: "…" }` | Every subscriber of a list |
| `{ list_pattern: "eng.*" }` | Every list matching the pattern |
| `{ audience_id: "…" }` | A filter whose membership Courier stores and keeps current |
| An array of the above | Multiple recipients in one call, with a **hard cap of 500** |
Above 500 ad-hoc recipients, a `to` array returns `400 message.to has N recipients. Max is 500`.
Use a list, an audience, or a [Bulk API job](./references/guides/bulk.md) instead.
Multi-tenant sends carry the tenant as `tenant_id`, either on the recipient (`to.tenant_id`) or in `message.context.tenant_id`. Both load that tenant's brand and preference defaults; pick one and use it consistently.
## Canonical SDK Shape
Ground every Courier code path in this shape. Where a resource file disagrees, this block wins. Confirm against a [live source](#verifying-against-live-sources).
**Node.js (`@trycourier/courier`):**
```typescript
import Courier from "@trycourier/courier";
// Reads process.env.COURIER_API_KEY by default
const client = new Courier();
await client.send.message({
message: {
to: { user_id: "user-123" }, // or { email }, { phone_number }, { list_id }, { audience_id }, etc.
template: "nt_01kmrbq6ypf25tsge12qek41r0", // OR content: { title, body } / { version, elements }
data: { /* merge variables */ },
},
"Idempotency-Key": "order-confirmation-12345",
});
```
**Python (`trycourier`):**
```python
from courier import Courier
# Reads COURIER_API_KEY from env by default
client = Courier()
client.send.message(
message={
"to": {"user_id": "user-123"},
"template": "nt_01kmrbq6ypf25tsge12qek41r0",
"data": {},
},
idempotency_key="order-confirmation-12345",
)
```
Full method-name lookup for both SDKs: **[sdk-reference.md](./references/sdk-reference.md)**.
**The 23 namespaces are the complete SDK surface.** If an operation isn't here, it isn't in the SDK:
```
audiences auditEvents auth automations brands
broadcasts bulk digests inbound journeys
lists messages notifications previews profiles
providers requests routingStrategies send tenants
translations users workspacePreferences
```
Sub-namespaces: `automations.invoke`, `automations.runs`, `digests.schedules`, `journeys.runs`, `journeys.templates`, `lists.subscriptions`, `notifications.checks`, `notifications.previews`, `notifications.previews.runs`, `profiles.lists`, `providers.catalog`, `tenants.preferences`, `tenants.preferences.items`, `tenants.templates`, `tenants.templates.versions`, `users.preferences`, `users.tenants`, `users.tokens`, `workspacePreferences.topics`.
`auditEvents` and `inbound` (`inbound.trackEvent`) have no dedicated guide; use MCP or the CLI. `requests.archive` is in [inbox.md](./references/channels/inbox.md).
### Common operations
| Operation | Method |
|---|---|
| Archive a sent message | `client.requests.archive(requestId)` |
| Delete a provider | `client.providers.delete(id)` |
| Change one provider setting, the title, or the alias | `client.providers.patch(id, { settings: { … } })` |
| Replace a provider's whole config (full PUT) | `client.providers.update(id, …)` |
| Subscribe a user to a list | `client.lists.subscriptions.subscribeUser(userId, { list_id })` |
| Set a user's topic preference | `client.users.preferences.updateOrCreateTopic(topicId, { user_id, topic })` |
| Configure a provider | `client.providers.*` · type catalog at `client.providers.catalog.*` |
### Writing a user profile
| Call | HTTP | Behavior |
|---|---|---|
| `client.profiles.create(id, { profile })` | POST | Deep-merge, the everyday write |
| `client.profiles.update(id, { patch: [...] })` | PATCH | JSON Patch (RFC 6902) |
| `client.profiles.replace(id, { profile })` | PUT | Full overwrite; omitted fields are removed |
## Universal Rules
- Use idempotency keys for sends where duplicates would be harmful (payments, security alerts, OTPs)
- Use E.164 format for phone numbers
- Only send to channels the user has asked for or that make sense for the use case. Don't blast every channel by default
- For template sends, pass the Courier-generated `nt_...` ID or a template alias as `template`; treat IDs as opaque, workspace-specific valuesFrom trycourier/courier-skills, MIT.
Signals
- Stars
- 15
- Forks
- 3
- Open issues
- 0
- Last commit (this folder)
- Oct 22, 2026 (8 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/trycourier/courier-skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from trycourier
Cite this page
courier skill. Agent Mart. https://agentmart.dev/skills/trycourier-courier (last updated 2026-10-24)