9 min read

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

  1. Navigate to your Dashboard
  2. Click API Keys in the left sidebar
  3. Click Create New API Key
  4. Enter a descriptive name (e.g., "Production Server", "CI/CD Pipeline")
  5. Click Generate Key
  6. 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

GET/v1/api-keys

Retrieve all API keys for your organization. Returns key metadata only - never the full key value.

Request Headers

ParameterTypeDescription
X-API-Keyrequired
stringYour API key for authentication

Query Parameters

ParameterTypeDescription
page
integerPage number for pagination
Default: 1
limit
integerNumber of keys per page (max 100)
Default: 20

Response

response.json
{
"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
curl -X GET "https://api.docurift.com/v1/api-keys?page=1&limit=20" \
-H "X-API-Key: frc_your_api_key_here"
python
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']})")
javascript
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

POST/v1/api-keys

Create 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

ParameterTypeDescription
X-API-Keyrequired
stringYour API key for authentication
Content-Typerequired
stringMust be application/json

Request Body

ParameterTypeDescription
namerequired
stringDescriptive name for the API key (3-50 characters)
expiresAt
stringISO 8601 expiration date (optional, null for no expiry)

Response

response.json
{
"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
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"
}'
python
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']}")
javascript
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

DELETE/v1/api-keys/:id

Permanently 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

ParameterTypeDescription
idrequired
stringThe unique ID of the API key to revoke (e.g., key_abc123def456)

Request Headers

ParameterTypeDescription
X-API-Keyrequired
stringYour API key for authentication

Response

response.json
{
"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
curl -X DELETE https://api.docurift.com/v1/api-keys/key_abc123def456 \
-H "X-API-Key: frc_your_api_key_here"
python
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']}")
javascript
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

error.json
{
"success": false,
"error": {
  "code": "INVALID_API_KEY",
  "message": "Invalid API key. 20 attempts remaining before IP block."
}
}

403 Forbidden - Admin Required

error.json
{
"success": false,
"error": {
  "code": "FORBIDDEN",
  "message": "Admin access required to manage API keys"
}
}

404 Not Found - Key Not Found

error.json
{
"success": false,
"error": {
  "code": "NOT_FOUND",
  "message": "API key not found"
}
}

422 Validation Error

error.json
{
"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:

.env
# Local development
DOCURIFT_API_KEY=frc_your_api_key_here
.gitignore
# Ignore environment files
.env
.env.local
.env.*.local

Platform-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:

  1. Create a new API key with a descriptive name (e.g., production-2024-q2)
  2. Update all applications to use the new key
  3. Monitor the old key's lastUsedAt to ensure no active usage
  4. 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 lastUsedAt timestamps may be stale
  • Unexpected activity - Sudden spikes in usage may indicate compromise
  • Expired keys - Remove or renew keys approaching expiration
python
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

Support

Need help with API keys?