Authentication
All API requests require authentication via an API key.
On This Page
API Keys
Include your API key in the X-API-Key header with every request:
curl -X POST https://api.thelawin.dev/v1/generate \
-H "X-API-Key: env_live_abc123..." \
-H "Content-Type: application/json" \
-d @invoice.json
X-API-Key header (not Authorization: Bearer). This is a design choice to avoid conflicts with OAuth flows in complex systems.
Examples in Multiple Languages
JavaScript (fetch)
const response = await fetch('https://api.thelawin.dev/v1/generate', {
method: 'POST',
headers: {
'X-API-Key': process.env.THELAWIN_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(invoiceData)
});
Python (requests)
import requests
import os
response = requests.post(
'https://api.thelawin.dev/v1/generate',
headers={
'X-API-Key': os.environ['THELAWIN_API_KEY'],
'Content-Type': 'application/json'
},
json=invoice_data
)
Ruby
require 'thelawin'
client = Thelawin::Client.new(api_key: ENV['THELAWIN_API_KEY'])
result = client.generate(invoice: invoice_data, template: 'minimal')
Environments
We provide two types of API keys:
| Type | Prefix | Use Case |
|---|---|---|
| Sandbox | env_sandbox_* |
Development & testing. Free, unlimited usage. Adds watermark to PDFs. |
| Live | env_live_* |
Production use. Counts against your monthly quota. No watermark. |
Managing API Keys
Create and manage your API keys in the Dashboard. You can:
- Create multiple keys - One per project, service, or environment
- Name your keys - Add descriptive labels for easy identification
- Toggle on/off - Disable keys without deleting them (useful for debugging)
- Monitor usage - See last usage timestamp and request counts
- Rotate keys - Generate new keys and phase out old ones
Rate Limits
Rate limits protect the API from abuse and ensure fair usage. Limits apply per API key:
| Plan | Requests/sec | Burst Limit | Monthly Quota |
|---|---|---|---|
| Sandbox | 5/sec |
10 requests | Unlimited (watermarked) |
| Starter | 10/sec |
20 requests | 500 invoices |
| Pro | 50/sec |
100 requests | 2,000 invoices |
Rate Limit Headers
Every response includes rate limit information in HTTP headers:
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1735680000
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests allowed per second |
X-RateLimit-Remaining |
Requests remaining in current window |
X-RateLimit-Reset |
Unix timestamp when the limit resets |
When you exceed the rate limit, the API returns 429 Too Many Requests with a Retry-After header (in seconds).
Security Best Practices
1. Use Environment Variables
Store API keys in environment variables, never hardcode them in source code. Use .env files (excluded from git) or secrets management tools (AWS Secrets Manager, HashiCorp Vault).
2. Rotate Keys Regularly
Create a new key, update your applications, then delete the old key. This minimizes impact if a key is compromised. Rotate keys every 90 days or after team changes.
3. Use Separate Keys per Environment
Create distinct keys for development, staging, and production. This allows you to revoke a compromised key without affecting other environments.
4. Keep Keys Server-Side
Never expose API keys in client-side JavaScript, mobile apps, or public repositories. Always call the API from your backend server.
5. Monitor Unusual Activity
Check the Dashboard regularly for unexpected usage patterns. Set up alerts for quota approaching limits. Immediately revoke any suspected compromised keys.
Troubleshooting
❌ 401 Unauthorized
Symptom: API returns {"error": "unauthorized"}
Common Causes:
- Missing
X-API-Keyheader (check spelling and capitalization) - API key disabled in Dashboard (toggle it back on)
- Wrong key prefix (
env_sandbox_*vsenv_live_*) - Extra whitespace in key value (trim the string)
❌ 429 Too Many Requests
Symptom: API returns {"error": "rate_limit_exceeded"}
Solutions:
- Implement exponential backoff (wait 1s, 2s, 4s, 8s...)
- Respect the
Retry-Afterheader - Upgrade your plan for higher limits (Pro: 50 req/sec)
- Use multiple API keys to distribute load
❌ 402 Payment Required
Symptom: API returns {"error": "quota_exceeded"}
Solutions:
- Check your usage in the Dashboard (Settings → Usage)
- Upgrade to a higher plan (Starter: 500/mo, Pro: 2,000/mo)
- Use Sandbox keys for development/testing (unlimited with watermark)
- Wait until next billing cycle (quotas reset monthly)
❌ CORS Errors (Browser)
Symptom: Browser console shows "CORS policy" error
Solution:
You cannot call the API directly from browser JavaScript due to security restrictions. Always proxy requests through your backend server to keep API keys secure.