Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use this skill when a PinMe project (Worker TypeScript) needs to integrate email sending (send_email). Guides AI to generate correct Worker TS code.
.claude/skills/glitternetwork-pinme-email/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 76% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -7% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 39% | 0% |
| case-08 | ✗→✓ | ▲ Improved | -1% | 0% |
Guides how to call PinMe platform's email sending API in a PinMe Worker (TypeScript).
The following environment variables are automatically injected when the Worker is created — no manual configuration needed:
typescript// 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_KEY is the sole credential for the Worker to call PinMe platform APIs. When BASE_URL is not set, it defaults to https://pinme.cloud.
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
json{ "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 |
Success (200):
json{ "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" |
typescriptasync 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 }); }
PinMe platform API unified response format:
typescriptinterface 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 }
typescriptasync 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 }; }
typescriptconst 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);
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 7,595 | 6,335 | -17% | 1 | 1 | 0% | 1,643 | 2,888 | +76% | 0 | 0 | — |
case-02 | fail→pass | 13,327 | 26,957 | +102% | 1 | 1 | 0% | 3,308 | 4,936 | +49% | 0 | 0 | — |
case-03 | fail→pass | 18,328 | 10,257 | -44% | 1 | 1 | 0% | 4,054 | 3,788 | -7% | 0 | 0 | — |
case-04 | pass→pass | 7,574 | 5,600 | -26% | 1 | 1 | 0% | 1,717 | 2,702 | +57% | 0 | 0 | — |
case-05 | pass→pass | 7,613 | 5,315 | -30% | 1 | 1 | 0% | 1,554 | 2,488 | +60% | 0 | 0 | — |
case-06 | pass→pass | 6,954 | 7,858 | +13% | 1 | 1 | 0% | 1,382 | 2,998 | +117% | 0 | 0 | — |
case-07 | fail→pass | 6,496 | 1,872 | -71% | 1 | 1 | 0% | 1,234 | 1,721 | +39% | 0 | 0 | — |
case-08 | fail→pass | 9,116 | 2,352 | -74% | 1 | 1 | 0% | 1,830 | 1,818 | -1% | 0 | 0 | — |
case-09 | fail→pass | 8,115 | 2,201 | -73% | 1 | 1 | 0% | 1,539 | 1,815 | +18% | 0 | 0 | — |
case-10 | fail→pass | 4,528 | 3,802 | -16% | 1 | 1 | 0% | 957 | 2,097 | +119% | 0 | 0 | — |
case-11 | fail→pass | 7,377 | 1,747 | -76% | 1 | 1 | 0% | 1,123 | 1,744 | +55% | 0 | 0 | — |
case-12 | fail→pass | 6,876 | 3,925 | -43% | 1 | 1 | 0% | 1,139 | 1,750 | +54% | 0 | 0 | — |
case-13 | fail→pass | 8,087 | 3,269 | -60% | 1 | 1 | 0% | 1,341 | 2,009 | +50% | 0 | 0 | — |
case-14 | fail→pass | 10,613 | 3,989 | -62% | 1 | 1 | 0% | 1,903 | 2,218 | +17% | 0 | 0 | — |
case-15 | fail→pass | 14,808 | 6,787 | -54% | 1 | 1 | 0% | 2,974 | 2,696 | -9% | 0 | 0 | — |
case-16 | pass→pass | 11,235 | 5,898 | -48% | 1 | 1 | 0% | 2,101 | 2,602 | +24% | 0 | 0 | — |
case-17 | fail→pass | 11,449 | 2,662 | -77% | 1 | 1 | 0% | 2,346 | 1,875 | -20% | 0 | 0 | — |
case-18 | pass→pass | 9,586 | 1,997 | -79% | 1 | 1 | 0% | 1,699 | 1,775 | +4% | 0 | 0 | — |
case-19 | pass→pass | 6,201 | 2,775 | -55% | 1 | 1 | 0% | 980 | 1,944 | +98% | 0 | 0 | — |
case-20 | pass→pass | 3,265 | 1,810 | -45% | 1 | 1 | 0% | 565 | 1,650 | +192% | 0 | 0 | — |
case-21 | fail→pass | 10,376 | 11,365 | +10% | 1 | 1 | 0% | 2,082 | 2,379 | +14% | 0 | 0 | — |
case-22 | pass→pass | 11,877 | 9,978 | -16% | 1 | 1 | 0% | 2,269 | 3,442 | +52% | 0 | 0 | — |
case-23 | fail→pass | 14,946 | 6,984 | -53% | 1 | 1 | 0% | 3,248 | 3,065 | -6% | 0 | 0 | — |
case-24 | pass→pass | 8,522 | 2,225 | -74% | 1 | 1 | 0% | 1,421 | 1,854 | +30% | 0 | 0 | — |
case-25 | fail→pass | 7,868 | 1,760 | -78% | 1 | 1 | 0% | 1,328 | 1,701 | +28% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +64 percentage points is the difference between those two pass rates over the 25 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.