Skip to main content

API key types

Plunk has two types of API keys. Which one you use depends on where your code runs.
TypePrefixUsed forSafe to expose?
Secret keysk_All endpointsNo — server-side only
Public keypk_POST /v1/track onlyYes — 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.
Browser (public key)
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

  1. Open the Plunk dashboard.
  2. Go to Settings for your project.
  3. Find your secret key and public key under API Keys.

Rotating keys

If a key is compromised or you want to cycle credentials:
1

Create a new key

Generate a replacement key in Settings → API Keys.
2

Update your applications

Replace the old key in all services and environment variables that use it.
3

Delete the old key

Remove the compromised key from the dashboard once all applications are updated.

Authentication errors

CodeStatusCause
MISSING_AUTH401The Authorization header is absent or not in Bearer <key> format
INVALID_API_KEY401The key does not match any project or is the wrong key type for the endpoint
PROJECT_DISABLED403The project associated with this key has been disabled
PROJECT_ACCESS_DENIED403The key does not have access to the requested project

Missing authorization header

{
  "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.

Build docs developers (and LLMs) love