API Keys
Programmatically manage API keys for secure access to the DocuRift API
API keys provide secure, programmatic access to the DocuRift API. This guide covers how to create, manage, and revoke API keys both through the dashboard and programmatically via the API.
Overview
What Are API Keys For?
API keys are unique identifiers that authenticate your requests to the DocuRift API. They enable:
- Server-to-server communication - Backend integrations without user sessions
- Automated workflows - CI/CD pipelines, batch processing, scheduled jobs
- Third-party integrations - Connect external services to DocuRift
- Development & testing - Separate keys for different environments
Key Format
All DocuRift API keys follow a consistent format:
frc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- Prefix:
frc_- DocuRift identifier - Length: 36 characters total (4-character prefix + 32 random characters)
- Characters: Alphanumeric (a-z, A-Z, 0-9)
Example: frc_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
Security Model
DocuRift implements robust security measures for API keys:
| Feature | Description |
|---------|-------------|
| SHA-256 Hashing | Keys are hashed before storage - we never store plaintext keys |
| One-time Display | Full key shown only at creation time |
| Prefix Visibility | Only frc_abc123de... visible after creation |
| Usage Tracking | Every request updates lastUsedAt timestamp |
| Organization-scoped | Keys are tied to a specific organization |
Creating API Keys
Via Dashboard
- Navigate to your Dashboard
- Click API Keys in the left sidebar
- Click Create New API Key
- Enter a descriptive name (e.g., "Production Server", "CI/CD Pipeline")
- Click Generate Key
- Copy and save your key immediately - it won't be shown again
Naming Conventions
Use descriptive names that indicate the key's purpose and environment:
| Good Names | Bad Names |
|------------|-----------|
| production-backend | key1 |
| staging-server | test |
| github-actions-ci | my-key |
| zapier-integration | asdf123 |
| dev-local-john | new-key |
API Endpoints
List All API Keys
/v1/api-keysRetrieve all API keys for your organization. Returns key metadata only - never the full key value.
Request Headers
| Parameter | Type | Description |
|---|---|---|
X-API-Keyrequired | string | Your API key for authentication |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number for pagination Default: 1 |
limit | integer | Number of keys per page (max 100) Default: 20 |
Response
{
"success": true,
"data": {
"keys": [
{
"id": "key_abc123def456",
"name": "production-backend",
"keyPrefix": "frc_a1b2c3d4...",
"createdAt": "2024-01-15T10:30:00Z",
"lastUsedAt": "2024-01-26T14:22:15Z",
"expiresAt": null,
"status": "active"
},
{
"id": "key_xyz789ghi012",
"name": "staging-server",
"keyPrefix": "frc_x9y8z7w6...",
"createdAt": "2024-01-20T08:15:00Z",
"lastUsedAt": "2024-01-25T09:45:30Z",
"expiresAt": "2024-06-01T00:00:00Z",
"status": "active"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 2,
"totalPages": 1
}
}
}Code Examples
curl -X GET "https://api.docurift.com/v1/api-keys?page=1&limit=20" \
-H "X-API-Key: frc_your_api_key_here"import requests
import os
API_KEY = os.getenv('DOCURIFT_API_KEY')
API_URL = 'https://api.docurift.com/v1'
response = requests.get(
f'{API_URL}/api-keys',
headers={'X-API-Key': API_KEY},
params={'page': 1, 'limit': 20}
)
data = response.json()
for key in data['data']['keys']:
print(f"{key['name']}: {key['keyPrefix']} (last used: {key['lastUsedAt']})")const API_KEY = process.env.DOCURIFT_API_KEY;
const API_URL = 'https://api.docurift.com/v1';
const response = await fetch(`${API_URL}/api-keys?page=1&limit=20`, {
method: 'GET',
headers: {
'X-API-Key': API_KEY
}
});
const { data } = await response.json();
data.keys.forEach(key => {
console.log(`${key.name}: ${key.keyPrefix} (last used: ${key.lastUsedAt})`);
});Create New API Key
/v1/api-keysCreate a new API key. The full key is returned only once in the response - store it securely.
Admin Access Required
Only organization owners and admins can create API keys.
Request Headers
| Parameter | Type | Description |
|---|---|---|
X-API-Keyrequired | string | Your API key for authentication |
Content-Typerequired | string | Must be application/json |
Request Body
| Parameter | Type | Description |
|---|---|---|
namerequired | string | Descriptive name for the API key (3-50 characters) |
expiresAt | string | ISO 8601 expiration date (optional, null for no expiry) |
Response
{
"success": true,
"data": {
"id": "key_new123abc456",
"name": "production-backend",
"key": "frc_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"keyPrefix": "frc_a1b2c3d4...",
"createdAt": "2024-01-26T15:00:00Z",
"expiresAt": null,
"status": "active"
},
"message": "API key created successfully. Save this key now - it won't be shown again."
}One-Time Display
The key field contains the full API key and is only included in the creation response. After this, only the keyPrefix is available.
Code Examples
curl -X POST https://api.docurift.com/v1/api-keys \
-H "X-API-Key: frc_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "production-backend",
"expiresAt": "2025-01-01T00:00:00Z"
}'import requests
import os
API_KEY = os.getenv('DOCURIFT_API_KEY')
API_URL = 'https://api.docurift.com/v1'
response = requests.post(
f'{API_URL}/api-keys',
headers={
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
json={
'name': 'production-backend',
'expiresAt': '2025-01-01T00:00:00Z' # Optional
}
)
data = response.json()
if data['success']:
# IMPORTANT: Save this key securely - it won't be shown again
new_key = data['data']['key']
print(f"New API key created: {new_key}")
print("Save this key now - it won't be displayed again!")
else:
print(f"Error: {data['error']['message']}")const API_KEY = process.env.DOCURIFT_API_KEY;
const API_URL = 'https://api.docurift.com/v1';
const response = await fetch(`${API_URL}/api-keys`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'production-backend',
expiresAt: '2025-01-01T00:00:00Z' // Optional
})
});
const data = await response.json();
if (data.success) {
// IMPORTANT: Save this key securely - it won't be shown again
const newKey = data.data.key;
console.log('New API key created:', newKey);
console.log('Save this key now - it will not be displayed again!');
} else {
console.error('Error:', data.error.message);
}Revoke API Key
/v1/api-keys/:idPermanently revoke an API key. This action is immediate and irreversible.
Immediate Effect
Revoked keys stop working immediately. Any requests using the revoked key will receive a 401 Unauthorized response.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
idrequired | string | The unique ID of the API key to revoke (e.g., key_abc123def456) |
Request Headers
| Parameter | Type | Description |
|---|---|---|
X-API-Keyrequired | string | Your API key for authentication |
Response
{
"success": true,
"data": {
"id": "key_abc123def456",
"name": "old-production-key",
"status": "revoked",
"revokedAt": "2024-01-26T16:00:00Z"
},
"message": "API key revoked successfully"
}Code Examples
curl -X DELETE https://api.docurift.com/v1/api-keys/key_abc123def456 \
-H "X-API-Key: frc_your_api_key_here"import requests
import os
API_KEY = os.getenv('DOCURIFT_API_KEY')
API_URL = 'https://api.docurift.com/v1'
key_id = 'key_abc123def456'
response = requests.delete(
f'{API_URL}/api-keys/{key_id}',
headers={'X-API-Key': API_KEY}
)
data = response.json()
if data['success']:
print(f"API key '{data['data']['name']}' revoked successfully")
else:
print(f"Error: {data['error']['message']}")const API_KEY = process.env.DOCURIFT_API_KEY;
const API_URL = 'https://api.docurift.com/v1';
const keyId = 'key_abc123def456';
const response = await fetch(`${API_URL}/api-keys/${keyId}`, {
method: 'DELETE',
headers: {
'X-API-Key': API_KEY
}
});
const data = await response.json();
if (data.success) {
console.log(`API key '${data.data.name}' revoked successfully`);
} else {
console.error('Error:', data.error.message);
}Error Responses
Common Error Codes
401 Unauthorized - Invalid Key
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid API key. 20 attempts remaining before IP block."
}
}403 Forbidden - Admin Required
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "Admin access required to manage API keys"
}
}404 Not Found - Key Not Found
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "API key not found"
}
}422 Validation Error
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request",
"details": {
"name": "Name must be between 3 and 50 characters"
}
}
}Security Best Practices
Never Expose in Client-Side Code
API keys should never be used in frontend/client-side code. They can be extracted from:
- Browser developer tools
- Network request inspection
- Decompiled mobile apps
- Cached JavaScript files
Security Risk
If your API key is exposed in client-side code, revoke it immediately and generate a new one.
Use Environment Variables
Never hardcode API keys in your source code. Use environment variables instead:
# Local development
DOCURIFT_API_KEY=frc_your_api_key_here# Ignore environment files
.env
.env.local
.env.*.localPlatform-specific secrets management:
| Platform | Method |
|----------|--------|
| Vercel | Environment Variables in Project Settings |
| Netlify | Site Settings > Environment Variables |
| AWS | Secrets Manager or Parameter Store |
| Docker | -e flag or Docker Compose secrets |
| Kubernetes | Kubernetes Secrets |
| GitHub Actions | Repository Secrets |
Rotate Keys Periodically
Establish a key rotation schedule:
- Create a new API key with a descriptive name (e.g.,
production-2024-q2) - Update all applications to use the new key
- Monitor the old key's
lastUsedAtto ensure no active usage - Revoke the old key after confirming it's no longer in use
Recommended Rotation
Rotate production API keys at least every 90 days, or immediately if you suspect a key has been compromised.
Monitor Key Usage
Regularly review your API keys for:
- Unused keys - Keys with old
lastUsedAttimestamps may be stale - Unexpected activity - Sudden spikes in usage may indicate compromise
- Expired keys - Remove or renew keys approaching expiration
import requests
from datetime import datetime, timedelta
import os
API_KEY = os.getenv('DOCURIFT_API_KEY')
API_URL = 'https://api.docurift.com/v1'
# Get all API keys
response = requests.get(
f'{API_URL}/api-keys',
headers={'X-API-Key': API_KEY}
)
data = response.json()
stale_threshold = datetime.now() - timedelta(days=30)
print("API Key Audit Report")
print("=" * 50)
for key in data['data']['keys']:
last_used = datetime.fromisoformat(key['lastUsedAt'].replace('Z', '+00:00'))
status = "Active"
if last_used.replace(tzinfo=None) < stale_threshold:
status = "STALE - Consider revoking"
print(f"Name: {key['name']}")
print(f" Prefix: {key['keyPrefix']}")
print(f" Last Used: {key['lastUsedAt']}")
print(f" Status: {status}")
print()Use Separate Keys per Environment
Maintain separate API keys for each environment:
| Environment | Key Name Example | Purpose |
|-------------|------------------|---------|
| Development | dev-local-[name] | Local development |
| Staging | staging-server | Pre-production testing |
| Production | production-backend | Live production traffic |
| CI/CD | github-actions-ci | Automated testing/deployment |
This allows you to:
- Revoke compromised keys without affecting other environments
- Track usage per environment
- Apply different rate limits or permissions
Next Steps
- Authentication Methods - Learn about all authentication options
- Process Your First Document - Start processing documents
- Credit Management - Monitor your API usage
Support
Need help with API keys?
- Email: support@docurift.com
- Discord: Join our community
- Documentation: Browse all docs