API key types
Plunk has two types of API keys. Which one you use depends on where your code runs.
| Type | Prefix | Used for | Safe to expose? |
|---|
| Secret key | sk_ | All endpoints | No — server-side only |
| Public key | pk_ | POST /v1/track only | Yes — safe in browsers and mobile apps |
Never include a secret key in client-side code, public repositories, or anywhere it could be read by users. Treat it like a password. If a secret key is compromised, rotate it immediately.
Public keys are designed for front-end and mobile use. You can safely embed a pk_ key in a browser app or native app to track events without exposing your secret key.
Passing your API key
Include your API key in the Authorization header of every request using the Bearer token format.
Authorization: Bearer YOUR_API_KEY
Examples
curl -X POST https://next-api.useplunk.com/v1/send \
-H "Authorization: Bearer sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{"to": "[email protected]", "subject": "Hello", "body": "<p>Hi</p>"}'
Tracking events with a public key
The /v1/track endpoint accepts public keys, so you can call it directly from a browser or mobile app.
await fetch('https://next-api.useplunk.com/v1/track', {
method: 'POST',
headers: {
'Authorization': 'Bearer pk_your_public_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: '[email protected]',
event: 'signed_up',
}),
});
Public keys only work with POST /v1/track. Using a public key on any other endpoint returns a 401 INVALID_API_KEY error.
Getting your API keys
- Open the Plunk dashboard.
- Go to Settings for your project.
- Find your secret key and public key under API Keys.
Rotating keys
If a key is compromised or you want to cycle credentials:
Create a new key
Generate a replacement key in Settings → API Keys.
Update your applications
Replace the old key in all services and environment variables that use it.
Delete the old key
Remove the compromised key from the dashboard once all applications are updated.
Authentication errors
| Code | Status | Cause |
|---|
MISSING_AUTH | 401 | The Authorization header is absent or not in Bearer <key> format |
INVALID_API_KEY | 401 | The key does not match any project or is the wrong key type for the endpoint |
PROJECT_DISABLED | 403 | The project associated with this key has been disabled |
PROJECT_ACCESS_DENIED | 403 | The key does not have access to the requested project |
{
"success": false,
"error": {
"code": "MISSING_AUTH",
"message": "Authorization header is required",
"statusCode": 401,
"requestId": "abc-123",
"suggestion": "Include an Authorization header with format: \"Authorization: Bearer YOUR_API_KEY\""
},
"timestamp": "2025-11-30T10:30:00.000Z"
}
Invalid API key
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid secret API key. This endpoint requires a secret key (sk_*), not a public key.",
"statusCode": 401,
"requestId": "abc-123",
"suggestion": "Verify your API key is correct and starts with \"sk_\" for secret keys or \"pk_\" for public keys."
},
"timestamp": "2025-11-30T10:30:00.000Z"
}
Project disabled
{
"success": false,
"error": {
"code": "PROJECT_DISABLED",
"message": "Project is disabled due to security violations. All write operations are blocked.",
"statusCode": 403,
"requestId": "abc-123"
},
"timestamp": "2025-11-30T10:30:00.000Z"
}
A project is disabled automatically when bounce or complaint rates exceed AWS SES thresholds. Contact support with your requestId if you believe this is in error.