Transactional and bulk email delivery via Resend API with single or batch endpoints.
Works with
Choose single endpoint for individual emails with attachments or scheduling; use batch endpoint for 2–100 distinct emails in one request to reduce API calls
Implement idempotency keys ( <event-type>/<entity-id> format) to prevent duplicate sends on retries, with 24-hour expiration
Retry only 429 (rate limit) and 500 (server error) responses using exponential backoff; fix 400/422 validation
AI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionsend-emailExecute the skills CLI command in your project's root directory to begin installation:
Fetches send-email from resend/resend-skills and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
Restart Cursor to activate send-email. Access via /send-email in your agent's command palette.
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your environment. Always review source, verify the publisher, and test in isolation before production.
Submit your Claude Code skill and start earning
Automate repetitive workflows and reduce manual effort
Example
Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Learn new skills, understand complex topics, get expert guidance
Example
Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Enhance output quality through reviews, suggestions, and refinements
Example
Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
0
total installs
0
this week
98
GitHub stars
0
upvotes
Run in your terminal
0
installs
0
this week
98
stars
Resend provides two endpoints for sending emails:
| Approach | Endpoint | Use Case |
|---|---|---|
| Single | POST /emails |
Individual transactional emails, emails with attachments, scheduled sends |
| Batch | POST /emails/batch |
Multiple distinct emails in one request (max 100), bulk notifications |
Choose batch when:
Choose single when:
Always implement these for production email sending. See references/best-practices.md for complete implementations.
Prevent duplicate emails when retrying failed requests.
| Key Facts | |
|---|---|
| Format (single) | <event-type>/<entity-id> (e.g., welcome-email/user-123) |
| Format (batch) | batch-<event-type>/<batch-id> (e.g., batch-orders/batch-456) |
| Expiration | 24 hours |
| Max length | 256 characters |
| Duplicate payload | Returns original response without resending |
| Different payload | Returns 409 error |
| Code | Action |
|---|---|
| 400, 422 | Fix request parameters, don't retry |
| 401, 403 | Check API key / verify domain, don't retry |
| 409 | Idempotency conflict - use new key or fix payload |
| 429 | Rate limited - retry with exponential backoff (by default, rate limit is 2 requests/second) |
| 500 | Server error - retry with exponential backoff |
Endpoint: POST /emails (prefer SDK over cURL)
| Parameter | Type | Description |
|---|---|---|
from |
string | Sender address. Format: "Name <[email protected]>" |
to |
string[] | Recipient addresses (max 50) |
subject |
string | Email subject line |
html or text |
string | Email body content |
| Parameter | Type | Description |
|---|---|---|
cc |
string[] | CC recipients |
bcc |
string[] | BCC recipients |
reply_to* |
string[] | Reply-to addresses |
scheduled_at* |
string | Schedule send time (ISO 8601) |
attachments |
array | File attachments (max 40MB total) |
tags |
array | Key/value pairs for tracking (see Tags) |
headers |
object | Custom headers |
*Parameter naming varies by SDK (e.g., replyTo in Node.js, reply_to in Python).
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send(
{
from: 'Acme <[email protected]>',
to: ['[email protected]'],
subject: 'Hello World',
html: '<p>Email body here</p>',
},
{ idempotencyKey: `welcome-email/${userId}` }
);
if (error) {
console.error('Failed:', error.message);
return;
}
console.log('Sent:', data.id);
See references/single-email-examples.md for all SDK implementations with error handling and retry logic.
Endpoint: POST /emails/batch (but prefer SDK over cURL)
Since the entire batch fails on any validation error, validate all emails before sending:
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.batch.send(
[
{
from: 'Acme <[email protected]>',
to: ['[email protected]'],
subject: 'Order Shipped',
html: '<p>Your order has shipped!</p>',
},
{
from: 'Acme <[email protected]>',
to: ['[email protected]'],
subject: 'Order Confirmed',
html: '<p>Your order is confirmed!</p>',
},
],
{ idempotencyKey: `batch-orders/${batchId}` }
);
if (error) {
console.error('Batch failed:', error.message);
return;
}
console.log('Sent:', data.map(e => e.id));
See references/batch-email-examples.md for all SDK implementations with validation, error handling, and retry logic.
For sends larger than 100 emails, chunk into multiple batch requests:
<batch-prefix>/chunk-<index>See references/batch-email-examples.md for complete chunking implementations.
Follow these practices to maximize inbox placement.
For more help with deliverability, install the email-best-practices skill with npx skills add resend/email-best-practices.
| Practice | Why |
|---|---|
| Valid SPF, DKIM, DMARC record | authenticate the email and prevent spoofing |
| Links match sending domain | If sending from @acme.com, link to https://acme.com - mismatched domains trigger spam filters |
| Include plain text version | Use both html and text parameters for accessibility and deliverability (Resend generates a plain text version if not provided) |
| Avoid "no-reply" addresses | Use real addresses (e.g., support@) - improves trust signals |
| Keep body under 102KB | Gmail clips larger messages |
| Practice | Why |
|---|---|
| Use subdomains | Send transactional from notifications.acme.com, marketing from mail.acme.com - protects reputation |
| Disable tracking for transactional | Open/click tracking can trigger spam filters for password resets, receipts, etc. |
Tracking is configured at the domain level in the Resend dashboard, not per-email.
| Setting | How it works | Recommendation |
|---|---|---|
| Open tracking | Inserts 1x1 transparent pixel | Disable for transactional emails - can hurt deliverability |
| Click tracking | Rewrites links through redirect | Disable for sensitive emails (password resets, security alerts) |
When to enable tracking:
When to disable tracking:
Configure via dashboard: Domain → Configuration → Click/Open Tracking
Track email delivery status in real-time using webhooks. Resend sends HTTP POST requests to your endpoint when events occur.
| Event | When to use |
|---|---|
email.delivered |
Confirm successful delivery |
email.bounced |
Remove from mailing list, alert user |
email.complained |
Unsubscribe user (spam complaint) |
email.opened / email.clicked |
Track engagement (marketing only) |
Verify webhook signatures for every request. Without verification, anyone can send fake events to your endpoint.
See references/webhooks.md for setup, signature verification code, and all event types.
Tags are key/value pairs that help you track and filter emails.
tags: [
{ name: 'user_id', value: 'usr_123' },
{ name: 'email_type', value: 'welcome' },
{ name: 'plan', value: 'enterprise' }
]
Use cases:
Constraints: Tag names and values can only contain ASCII letters, numbers, underscores, or dashes. Max 256 characters each.
Use pre-built templates instead of sending HTML with each request.
const { data, error } = await resend.emails.send({
from: 'Acme <[email protected]>',
to: ['[email protected]'],
subject: 'Welcome!',
templatePrerequisites
Time Estimate
15-45 minutes depending on use case complexity
Steps
Common Pitfalls
✓ Do
✗ Don't
💡 Pro Tips
✓ Use when
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid when
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
shadowcz007/skills
aaronontheweb/dotnet-skills
davila7/claude-code-templates
intellectronica/agent-skills
am-will/codex-skills
sickn33/antigravity-awesome-skills
We added send-email from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
send-email fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
Keeps context tight: send-email is the kind of skill you can hand to a new teammate without a long onboarding doc.
Registry listing for send-email matched our evaluation — installs cleanly and behaves as described in the markdown.
Registry listing for send-email matched our evaluation — installs cleanly and behaves as described in the markdown.
send-email is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
send-email reduced setup friction for our internal harness; good balance of opinion and flexibility.
send-email reduced setup friction for our internal harness; good balance of opinion and flexibility.
I recommend send-email for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
Solid pick for teams standardizing on skills: send-email is focused, and the summary matches what you get after install.
showing 1-10 of 29