Skip to main content

Troubleshooting Authentication

Fix issues with API keys and authentication.

Common Errors

401 Unauthorized

Error:
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid API key"
  }
}
Causes & Solutions:
Ensure you’re including the Authorization header:
curl -H "Authorization: Bearer le_xxxxxxxxxxxx" ...
API keys must start with le_ or le_test_. Check for typos or extra spaces.
The key may have been deleted. Create a new one in the dashboard.
Test keys (le_test_) only work in test mode. Use production keys for live sending.

403 Forbidden

Error:
{
  "error": {
    "code": "forbidden",
    "message": "API key lacks required permission: emails:send"
  }
}
Solution: Create a new key with the required permissions or update your existing key:
const key = await lettr.apiKeys.create({
  name: 'Full Access Key',
  permissions: ['*']  // Or specific permissions
});

IP Restriction Errors

Error:
{
  "error": {
    "code": "forbidden",
    "message": "Request from unauthorized IP address"
  }
}
Solution:
  1. Check your API key’s IP restrictions in the dashboard
  2. Add your current IP or remove restrictions:
await lettr.apiKeys.update('key_123', {
  ipRestrictions: ['203.0.113.0/24']  // Your IP range
});

Verifying Your API Key

Test your key with a simple request:
curl https://api.lettr.dev/v1/domains \
  -H "Authorization: Bearer le_xxxxxxxxxxxx"
Expected response for valid key:
{
  "object": "list",
  "data": [...]
}

SDK Authentication

Node.js

import { Lettr } from 'lettr';

// From environment variable (recommended)
const lettr = new Lettr(process.env.LETTR_API_KEY);

// Or direct (not recommended for production)
const lettr = new Lettr('le_xxxxxxxxxxxx');

PHP

use Lettr\Lettr;

// From environment variable
$lettr = new Lettr(getenv('LETTR_API_KEY'));

// Or direct
$lettr = new Lettr('le_xxxxxxxxxxxx');

Environment Variables

Store keys in environment variables:
# .env file
LETTR_API_KEY=le_xxxxxxxxxxxx

# Shell
export LETTR_API_KEY=le_xxxxxxxxxxxx

Key Security Best Practices

Add .env to your .gitignore file.
Separate keys for development, staging, and production.
Create new keys and retire old ones every 90 days.
Only grant permissions that are actually needed.

Webhook Authentication

For webhook signature verification issues:
import { verifyWebhook } from 'lettr';

try {
  const event = verifyWebhook(
    req.body,
    req.headers['lettr-signature'],
    process.env.LETTR_WEBHOOK_SECRET
  );
} catch (err) {
  // Common issues:
  // - Wrong webhook secret
  // - Body already parsed (use raw body)
  // - Timestamp too old (>5 minutes)
  console.error('Verification failed:', err.message);
}
Ensure you’re using the raw request body, not a parsed JSON object:
// Express.js - use raw body
app.post('/webhooks', express.raw({ type: 'application/json' }), handler);