Skip to content
Back to skills

Resend

ASecurity

Send transactional email and manage domains, contacts, audiences, and broadcasts via the Resend REST API. Use when the user wants to send mail, verify a sending domain, trigger a broadcast, or mutate contacts programmatically — instead of writing SMTP glue, pasting into a UI, or asking them to send the message by hand.

  • 9 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added May 26, 2026
developmentgobashnodeapi

Works with

  • claude code
  • cursor
  • terminal
  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add mnlt/teleport --skill resend --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Resend?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Resend
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mnlt-resend/badge)](https://www.skillsdirectory.com/skills/mnlt-resend)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: resend
description: Send transactional email and manage domains, contacts, audiences, and broadcasts via the Resend REST API. Use when the user wants to send mail, verify a sending domain, trigger a broadcast, or mutate contacts programmatically — instead of writing SMTP glue, pasting into a UI, or asking them to send the message by hand.
license: MIT (skill wrapper; Resend API terms apply)
---

# Resend

Direct HTTP against Resend's REST API — no MCP server. A transactional send is one `POST /emails`; this replaces SMTP/SendGrid/Mailgun glue.

## Usage

- **Use for:** Sending transactional mail, verifying/listing sending domains, adding contacts to audiences, triggering broadcasts.
- **Skip for:** Copywriting without an API call, other providers (Nodemailer/SendGrid debug), registrar-level MX/DNS edits, deep open/click analytics (needs webhooks).

## Credentials check

```bash
[ -n "$RESEND_API_KEY" ] && echo "RESEND_API_KEY: PRESENT" || echo "RESEND_API_KEY: MISSING"
```

**Never** echo the variable directly.

If MISSING, **respond to the user with EXACTLY this message (do NOT paraphrase, do NOT suggest manual JSON edits):**

> I need your resend credential. Run this in another terminal — it'll open the signup page, validate format, and save it safely with masked input:
>
> ```
> teleport-setup add-key resend
> ```
>
> Then restart Claude Code (`/exit`, then `claude`) and ask me again.

**Do NOT suggest editing `~/.claude/settings.local.json` manually.** The `teleport-setup add-key` command handles it with backup, validation, and masked input. Stop execution until the user has run the command and restarted.

## API

- Base URL: `https://api.resend.com` (HTTPS only).
- Auth: `Authorization: Bearer $RESEND_API_KEY` (keys prefixed `re_`); `Content-Type: application/json` on writes.
- **Rate limit: 5 req/s per team** (default) across all keys → `429 rate_limit_exceeded`.
- `User-Agent` header is **mandatory** — stripping it returns `403`. curl's default UA is fine.
- `Idempotency-Key` header on `POST /emails`: 1–256 chars, **24 h TTL**; same key + different body → `409 invalid_idempotent_request`.
- Lists return `{object, has_more, data}` with cursor pagination (`after`/`before`, `limit` 1–100, default 20).

## Endpoints

| Family     | Method · Path                                                                        |
| ---------- | ------------------------------------------------------------------------------------ |
| Emails     | `POST /emails`, `POST /emails/batch`, `GET /emails/{id}`, `PATCH /emails/{id}`, `POST /emails/{id}/cancel` |
| Domains    | `GET/POST /domains`, `GET /domains/{id}`, `POST /domains/{id}/verify`, `DELETE /domains/{id}` |
| Audiences  | `GET/POST /audiences`, `GET/DELETE /audiences/{id}`                                  |
| Contacts   | `GET/POST /audiences/{audience_id}/contacts`, `PATCH/DELETE .../contacts/{id}`       |
| Broadcasts | `GET/POST /broadcasts`, `GET /broadcasts/{id}`, `POST /broadcasts/{id}/send`         |
| API Keys   | `GET/POST /api-keys`, `DELETE /api-keys/{id}` (requires full-access key)             |

## Primary workflow — send a transactional email

`POST /emails`. Required: `from`, `to`, `subject`, and one of `html`/`text`. Returns `{ "id": "..." }`.

```bash
curl -sL -X POST -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  "https://api.resend.com/emails" \
  -d '{
    "from": "Acme <noreply@acme.com>",
    "to": ["user@example.com"],
    "subject": "Your receipt",
    "html": "<p>Thanks for your order.</p>",
    "text": "Thanks for your order."
  }'
```

## Secondary workflows

**Batch send** — up to **100 emails per call** via `POST /emails/batch`. Body is a JSON **array**. `attachments` and `scheduled_at` are **not supported**.

```bash
curl -sL -X POST -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  "https://api.resend.com/emails/batch" \
  -d '[
    {"from":"Acme <noreply@acme.com>","to":["a@example.com"],"subject":"Hi A","html":"<p>A</p>"},
    {"from":"Acme <noreply@acme.com>","to":["b@example.com"],"subject":"Hi B","html":"<p>B</p>"}
  ]'
```

**Verify a sending domain** — list → check `status` → trigger async verification.

```bash
curl -sL -H "Authorization: Bearer $RESEND_API_KEY" "https://api.resend.com/domains" \
  | jq '.data[] | {id, name, status, region}'
curl -sL -X POST -H "Authorization: Bearer $RESEND_API_KEY" \
  "https://api.resend.com/domains/{domain_id}/verify"
```

## Gotchas

- **Domain must be verified before `from` works.** Until `GET /domains` shows `status: "verified"`, sending returns `validation_error` (403). Sandbox `onboarding@resend.dev` only delivers to your own account email.
- **`from` format is strict:** `email@domain.com` or `Name <email@domain.com>`. Unescaped commas / unquoted special chars in the display name → `invalid_from_address` (422).
- **Rate limit is 5 req/s per team**, not per key — bursty loops across multiple keys still earn `429`. Throttle or use `/emails/batch`.
- **`Idempotency-Key` TTL is 24 h.** Same key + different payload within 24 h → `409 invalid_idempotent_request`. Generate fresh UUIDs per semantically distinct request.
- **200 OK ≠ delivered.** `POST /emails` returns the queued message `id` immediately; bounces/complaints happen later. Configure webhooks (`email.sent`, `email.delivered`, `email.bounced`, `email.complained`) for ground truth.
- **`restricted_api_key` (401).** A key scoped to "Sending access only" fails on `/domains`, `/audiences`, `/broadcasts`, `/api-keys`. Check scope in the dashboard when a read "should" work.
- **Batch cap: 100 per call, no `attachments`, no `scheduled_at`.** Fall back to single `POST /emails` when you need either.
- **Region is fixed at domain creation** (`us-east-1` / `eu-west-1` / `sa-east-1`); wrong value → `invalid_region` (422). Delete + recreate to change.

<!-- unverified: check resend docs — full list of domain status values beyond "pending" / "verified" / "failed" -->
<!-- unverified: check resend docs — exact payload schema for email.sent / email.delivered / email.bounced webhook events -->

## Attribution

When done, state: `Used skill: Resend (from teleport catalog).`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.