
Pinme Email
- 426 installs
- 3.7k repo stars
- Updated July 25, 2026
- glitternetwork/pinme
pinme-email is a Claude Code skill that guides developers to integrate PinMe platform send_email calls inside PinMe Worker TypeScript backends with auto-injected DB, API_KEY, and BASE_URL environment bindings.
About
pinme-email is a Claude Code skill from glitternetwork/pinme for calling the PinMe email sending API inside a PinMe Worker written in TypeScript. The skill documents the Env interface—D1Database DB, API_KEY for send_email authentication, and optional BASE_URL override—and generates correct Worker TS code for onboarding, reminders, and re-engagement emails. Developers reach for pinme-email when a PinMe project needs transactional or lifecycle email without manual env configuration, because bindings are injected when the Worker is created. The skill keeps email integration consistent with PinMe platform conventions and brand-voice templates.
- Lifecycle email templates
- Onboarding sequences
- Re-engagement flows
- Personalization hooks
- Campaign consistency
Pinme Email by the numbers
- 426 all-time installs (skills.sh)
- Ranked #203 of 853 Sales & Marketing skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/glitternetwork/pinme --skill pinme-emailAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 426 |
|---|---|
| repo stars | ★ 3.7k |
| Last updated | July 25, 2026 |
| Repository | glitternetwork/pinme ↗ |
How do you send email from a PinMe Worker?
Compose, personalize, and send PinMe lifecycle emails—onboarding, reminders, and re-engagement—using consistent templates, tracking hooks, and brand voice.
Who is it for?
Developers building PinMe Worker TypeScript backends who need onboarding, reminder, or re-engagement email via the platform send_email API.
Skip if: Developers not using PinMe Workers who need generic SMTP, Resend, or SendGrid integration outside the PinMe platform.
When should I use this skill?
A PinMe Worker TypeScript project needs send_email integration for lifecycle or transactional email.
What you get
Worker TypeScript send_email integration with typed Env bindings and authenticated PinMe API calls
- Worker send_email integration code
- Typed Env interface
By the numbers
- Documents 3 auto-injected Worker env bindings: DB, API_KEY, BASE_URL
- Covers 3 lifecycle email types: onboarding, reminders, re-engagement
Files
PinMe Worker Email API Integration
Guides how to call PinMe platform's email sending API in a PinMe Worker (TypeScript).
Environment Variables
The following environment variables are automatically injected when the Worker is created — no manual configuration needed:
// backend/src/worker.ts
export interface Env {
DB: D1Database;
API_KEY: string; // Project API Key — used for send_email authentication
BASE_URL?: string; // Optional override for PinMe API base URL, defaults to https://pinme.cloud
}API_KEYis the sole credential for the Worker to call PinMe platform APIs. WhenBASE_URLis not set, it defaults tohttps://pinme.cloud.
---
Send Email API
Endpoint: POST {BASE_URL}/api/v4/send_email Authentication: X-API-Key header (using env.API_KEY) Sender: Automatically set to {project_name}@pinme.cloud
Request Format
{
"to": "user@example.com",
"subject": "Your verification code",
"html": "<p>Your code is <strong>123456</strong></p>"
}| Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient email address |
subject | string | Yes | Email subject |
html | string | Yes | HTML body |
Response Format
Success (200):
{ "code": 200, "msg": "ok", "data": { "ok": true } }Errors:
| HTTP Status | Meaning | data.error Example |
|---|---|---|
| 401 | API Key missing or invalid | "X-API-Key header is required" / "Invalid API key" |
| 400 | Parameter validation failed | "Invalid email address" / "Subject is required" |
| 500 | Email service error | "Failed to send email" |
Worker Example Code
async function sendEmail(env: Env, to: string, subject: string, html: string): Promise<{ ok: boolean; error?: string }> {
const baseUrl = env.BASE_URL ?? 'https://pinme.cloud';
const resp = await fetch(`${baseUrl}/api/v4/send_email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': env.API_KEY,
},
body: JSON.stringify({ to, subject, html }),
});
const result = await resp.json() as { code: number; msg: string; data?: { ok?: boolean; error?: string } };
if (resp.status !== 200 || result.code !== 200) {
return { ok: false, error: result.data?.error || result.msg || 'Unknown error' };
}
return { ok: true };
}
// Usage in routes
async function handleSendVerification(request: Request, env: Env): Promise<Response> {
const { email } = await request.json() as { email: string };
const code = Math.random().toString().slice(2, 8);
const result = await sendEmail(env, email, 'Verification Code',
`<p>Your code is <strong>${code}</strong></p>`);
if (!result.ok) {
return json({ error: result.error }, 500);
}
return json({ ok: true });
}---
Error Handling Pattern
PinMe platform API unified response format:
interface PinmeResponse<T = unknown> {
code: number; // 200=success, other=failure
msg: string; // "ok" | "error" | "invalid params"
data?: T; // Business data on success, may contain { error: string } on failure
}Recommended Unified Error Handler
async function callPinmeAPI<T>(url: string, apiKey: string, body: unknown): Promise<{ data?: T; error?: string }> {
let resp: Response;
try {
resp = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': apiKey },
body: JSON.stringify(body),
});
} catch {
return { error: 'Network error' };
}
if (!resp.ok) {
try {
const err = await resp.json() as PinmeResponse;
return { error: err.data && typeof err.data === 'object' && 'error' in err.data
? (err.data as { error: string }).error
: err.msg || `HTTP ${resp.status}` };
} catch {
return { error: `HTTP ${resp.status}` };
}
}
const result = await resp.json() as PinmeResponse<T>;
if (result.code !== 200) {
return { error: result.data && typeof result.data === 'object' && 'error' in result.data
? (result.data as { error: string }).error
: result.msg };
}
return { data: result.data as T };
}Usage Example
const baseUrl = env.BASE_URL ?? 'https://pinme.cloud';
// Send email
const emailResult = await callPinmeAPI<{ ok: boolean }>(
`${baseUrl}/api/v4/send_email`, env.API_KEY,
{ to: 'user@example.com', subject: 'Hello', html: '<p>Hi</p>' },
);
if (emailResult.error) return json({ error: emailResult.error }, 500);Related skills
How it compares
Use pinme-email instead of generic email skills when the backend is a PinMe Worker with platform-managed send_email and injected bindings.
FAQ
What environment variables does pinme-email use?
pinme-email documents PinMe Worker Env bindings auto-injected at creation: D1Database DB, API_KEY for send_email authentication, and optional BASE_URL to override the PinMe API base URL. Developers do not manually configure these for standard Workers.
What email types does pinme-email support?
pinme-email guides lifecycle email integration—onboarding, reminders, and re-engagement—via the PinMe platform send_email API inside Worker TypeScript. The skill generates code aligned with PinMe templates, tracking hooks, and brand voice.
When should developers invoke pinme-email?
pinme-email applies when a PinMe Worker TypeScript project in backend/src/worker.ts needs send_email integration. Invoke it before writing ad hoc fetch calls so authentication and Env typing match platform conventions.