--- title: API Reference description: Complete Plunk API documentation --- ## Base URL ``` {{API_URL}} ``` All API requests use this base URL. ## Authentication Include your API key in the `Authorization` header: ```bash Authorization: Bearer YOUR_API_KEY ``` - **Secret Key (sk_*)** — Required for all endpoints except `/v1/track` - **Public Key (pk_*)** — Only works with `/v1/track` for client-side event tracking ## Making requests ### Send transactional email ```bash curl -X POST {{API_URL}}/v1/send \ -H "Authorization: Bearer sk_your_secret_key" \ -H "Content-Type: application/json" \ -d '{ "to": "user@example.com", "subject": "Hello", "body": "

Your message here

" }' ``` ### Track event ```bash curl -X POST {{API_URL}}/v1/track \ -H "Authorization: Bearer pk_your_public_key" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "event": "signed_up" }' ``` ### Create contact ```bash curl -X POST {{API_URL}}/contacts \ -H "Authorization: Bearer sk_your_secret_key" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "subscribed": true, "data": { "firstName": "John", "plan": "pro" } }' ``` ## Response format All API responses follow a standardized format for easy parsing and error handling. ### Success response Public API endpoints (`/v1/send`, `/v1/track`): ```json { "success": true, "data": { "contact": "cnt_abc123", "event": "evt_xyz789", "timestamp": "2025-11-30T10:30:00.000Z" } } ``` Dashboard API endpoints (contacts, templates, campaigns): ```json { "success": true, "data": { "id": "cnt_abc123", "email": "user@example.com", "createdAt": "2025-11-30T10:30:00.000Z" } } ``` List endpoints with pagination: ```json { "success": true, "data": { "items": [...], "nextCursor": "abc123", "hasMore": true, "total": 1000 } } ``` ### Error response All errors include detailed information to help you debug issues: ```json { "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed", "statusCode": 422, "requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "errors": [ { "field": "email", "message": "Invalid email", "code": "invalid_string" } ], "suggestion": "One or more fields have incorrect types. Check that strings are quoted, numbers are unquoted, and booleans are true/false." }, "timestamp": "2025-11-30T10:30:00.000Z" } ``` **Error fields:** - `code` — Machine-readable error code for programmatic handling - `message` — Human-readable description - `statusCode` — HTTP status code - `requestId` — Unique ID for debugging (include when contacting support) - `errors` — Field-level validation details (when applicable) - `suggestion` — Helpful guidance for fixing the error See the [Error Codes documentation](/api-reference/errors) for complete details and examples. ## Pagination List endpoints support cursor-based pagination: ```bash GET /contacts?limit=100&cursor=abc123 ``` **Parameters:** - `limit` — Number of items per page (default: 20, max: 100) - `cursor` — Pagination cursor from previous response **Response:** ```json { "items": [...], "nextCursor": "def456", "hasMore": true, "total": 10000 } ``` Use `nextCursor` for the next page. When `hasMore` is false, you've reached the end. ## Rate limits Plunk enforces reasonable rate limits to ensure service quality: - **Email sending** — 14 emails/second (AWS SES default) - **API requests** — 1000 requests/minute per project - **Bulk operations** — Automatically queued for processing If you exceed limits, you'll receive a `429 Too Many Requests` response. ## Error codes The API uses standard HTTP status codes along with machine-readable error codes: **400 Bad Request** — Invalid request parameters or malformed request body **401 Unauthorized** — Missing or invalid API key **403 Forbidden** — Not authorized to access this resource or project disabled **404 Not Found** — Resource doesn't exist **422 Unprocessable Entity** — Request validation failed (see `errors` array for details) **429 Too Many Requests** — Rate limit exceeded **500 Internal Server Error** — An unexpected error occurred (contact support with request ID) For a complete list of error codes and troubleshooting guidance, see the [Error Codes documentation](/api-reference/errors). ## API endpoints ### Public API (transactional) **POST /v1/send** — Send transactional email(s) - Accepts single or multiple recipients - Template or inline content - Variable substitution **POST /v1/track** — Track event for contact - Creates/updates contact - Tracks custom event - Can use public key ### Contacts **GET /contacts** — List all contacts **POST /contacts** — Create new contact **GET /contacts/:id** — Get contact details **PATCH /contacts/:id** — Update contact **DELETE /contacts/:id** — Delete contact ### Templates **GET /templates** — List all templates **POST /templates** — Create new template **GET /templates/:id** — Get template details **PATCH /templates/:id** — Update template **DELETE /templates/:id** — Delete template ### Campaigns **GET /campaigns** — List all campaigns **POST /campaigns** — Create new campaign **GET /campaigns/:id** — Get campaign details **PATCH /campaigns/:id** — Update campaign **POST /campaigns/:id/send** — Send or schedule campaign **POST /campaigns/:id/cancel** — Cancel scheduled campaign **POST /campaigns/:id/test** — Send test email **GET /campaigns/:id/stats** — Get campaign analytics ### Segments **GET /segments** — List all segments **POST /segments** — Create new segment **GET /segments/:id** — Get segment details **PATCH /segments/:id** — Update segment **DELETE /segments/:id** — Delete segment **GET /segments/:id/contacts** — List segment members ### Workflows **GET /workflows** — List all workflows **POST /workflows** — Create new workflow **GET /workflows/:id** — Get workflow details **PATCH /workflows/:id** — Update workflow **DELETE /workflows/:id** — Delete workflow **GET /workflows/:id/executions** — List workflow executions ### Events **GET /events** — List all events **GET /events/names** — List unique event names ### Domains **GET /domains** — List verified domains **POST /domains** — Add domain for verification **DELETE /domains/:id** — Remove domain ## Client libraries ### Node.js ```javascript const PLUNK_SECRET_KEY = process.env.PLUNK_SECRET_KEY; async function sendEmail(to, subject, body) { const response = await fetch('{{API_URL}}/v1/send', { method: 'POST', headers: { 'Authorization': `Bearer ${PLUNK_SECRET_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ to, subject, body }) }); const data = await response.json(); if (!data.success) { throw new Error(`[${data.error.code}] ${data.error.message}`); } return data.data; } ``` ### Python ```python import os import requests PLUNK_SECRET_KEY = os.environ['PLUNK_SECRET_KEY'] def send_email(to, subject, body): response = requests.post( '{{API_URL}}/v1/send', headers={ 'Authorization': f'Bearer {PLUNK_SECRET_KEY}', 'Content-Type': 'application/json' }, json={'to': to, 'subject': subject, 'body': body} ) data = response.json() if not data.get('success'): error = data['error'] raise Exception(f"[{error['code']}] {error['message']}") return data['data'] ``` ### cURL ```bash curl -X POST {{API_URL}}/v1/send \ -H "Authorization: Bearer $PLUNK_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{"to": "user@example.com", "subject": "Hello", "body": "Message"}' ``` ## What's next - [Send your first email](/getting-started/quick-start) - [View detailed endpoint docs](/api-reference/public-api) - [Check error codes](/api-reference/errors)