Skip to main content
This guide covers how to manage your DocIntell API keys programmatically. API keys provide secure access to the DocIntell API for your applications and services.
DocIntell is currently invite-only. Contact your account manager to get started.

Overview

DocIntell uses API keys for programmatic access to the platform. Each API key:
  • Is scoped to a single tenant (your organization)
  • Can be either live (production) or test (development)
  • Is hashed before storage (we never store plaintext keys)
  • Can be rotated with zero downtime using grace periods
  • Can be revoked immediately if compromised

Key Environments

DocIntell supports two key environments:
EnvironmentPrefixPurposeBilling
Testdk_test_Development and testingFree (no billing)
Livedk_live_Production workloadsBillable usage
Always use test keys for development and staging environments. Only use live keys in production.

Creating an API Key

Create a new API key by calling POST /v1/keys:
curl -X POST https://api.docintell.com/v1/keys \
  -H "Authorization: Bearer dk_live_YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Server",
    "environment": "live"
  }'
Response:
{
  "key_id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Production Server",
  "api_key": "dk_live_K7gNU3sdo-OL0wNhqoVWhr3g6s1xYv72ol_pe_Unols",
  "environment": "live",
  "created_at": "2024-01-15T10:30:00Z"
}
The API key is shown ONLY ONCE in this response. Copy it immediately and store it securely. If you lose the key, you’ll need to create a new one.

Listing Your API Keys

View all API keys in your account with GET /v1/keys:
curl -X GET https://api.docintell.com/v1/keys \
  -H "Authorization: Bearer dk_live_YOUR_API_KEY"
Response:
{
  "keys": [
    {
      "key_id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Production Server",
      "key_prefix": "dk_live_",
      "key_suffix": "nols",
      "environment": "live",
      "is_active": true,
      "status": "active",
      "created_at": "2024-01-15T10:30:00Z",
      "last_used_at": "2024-01-15T12:45:00Z"
    },
    {
      "key_id": "660e8400-e29b-41d4-a716-446655440001",
      "name": "Old Production Key",
      "key_prefix": "dk_live_",
      "key_suffix": "aBc1",
      "environment": "live",
      "is_active": true,
      "status": "deprecated",
      "created_at": "2024-01-01T10:30:00Z",
      "last_used_at": "2024-01-15T12:45:00Z",
      "deprecated_at": "2024-01-15T10:30:00Z",
      "grace_period_ends_at": "2024-01-22T10:30:00Z",
      "grace_period_days_remaining": 5
    }
  ]
}
For security, the full API key is never shown after creation. Only the prefix (dk_live_) and last 4 characters are displayed for identification.

Response Fields

FieldDescription
key_prefixFirst 8 characters (e.g., dk_live_)
key_suffixLast 4 characters for identification
statusactive, deprecated, or revoked
is_activeWhether the key can still be used for authentication
deprecated_atWhen key rotation began (if status is deprecated)
grace_period_ends_atWhen the deprecated key will stop working
grace_period_days_remainingDays left before deprecated key expires

Rotating API Keys

Key rotation is the recommended way to update your API keys without service disruption. When you rotate a key:
  1. A new key is created
  2. The old key is marked as deprecated (but still works)
  3. You have 7 days to migrate your systems
  4. After 7 days, the old key automatically expires

Why Rotate Keys?

Security Best Practice

Regular rotation limits the window of exposure if a key is compromised.

Zero Downtime

Grace period allows gradual migration without service interruption.

Compliance

Many compliance frameworks require periodic credential rotation.

Incident Response

Quick response to suspected key compromise without breaking production.

Step-by-Step Rotation

1

Initiate Rotation

Call POST /v1/keys/rotate to create a new key:
curl -X POST https://api.docintell.com/v1/keys/rotate \
  -H "Authorization: Bearer dk_live_YOUR_CURRENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Server",
    "environment": "live"
  }'
Response:
{
  "new_key": {
    "key_id": "770e8400-e29b-41d4-a716-446655440002",
    "name": "Production Server",
    "api_key": "dk_live_newKeyXYZ123456789abcdefghijklmnop",
    "environment": "live",
    "created_at": "2024-01-15T10:30:00Z"
  },
  "deprecated_key": {
    "key_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Production Server",
    "key_prefix": "dk_live_",
    "key_suffix": "xY9z",
    "environment": "live",
    "is_active": true,
    "status": "deprecated",
    "created_at": "2024-01-01T10:30:00Z",
    "last_used_at": "2024-01-15T10:29:00Z",
    "deprecated_at": "2024-01-15T10:30:00Z",
    "grace_period_ends_at": "2024-01-22T10:30:00Z",
    "grace_period_days_remaining": 7
  }
}
Save the new_key.api_key value immediately - it’s shown only in this response!
2

Update Your Applications

During the 7-day grace period, update your applications to use the new key:
  • Update environment variables
  • Redeploy services with the new key
  • Update CI/CD pipelines
  • Update secrets in your secrets manager (AWS Secrets Manager, GCP Secret Manager, etc.)
Both the old and new keys work during the grace period. There’s no rush to migrate everything at once.
3

Monitor Usage

Track which systems are still using the old key by checking the last_used_at timestamp:
curl -X GET https://api.docintell.com/v1/keys \
  -H "Authorization: Bearer dk_live_YOUR_NEW_KEY"
If the deprecated key’s last_used_at timestamp is recent, some systems are still using it.
4

Wait for Grace Period to Expire

After 7 days, the old key automatically expires. If you’ve migrated all systems, you can manually revoke it early:
curl -X DELETE https://api.docintell.com/v1/keys/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer dk_live_YOUR_NEW_KEY"

Grace Period Details

TimelineOld KeyNew Key
Day 0 (rotation)deprecated (still works)active
Days 1-7Both keys workBoth keys work
Day 8+Automatically expiresActive
The 7-day grace period is fixed and cannot be extended. Plan your migration accordingly.

Revoking API Keys

If a key is compromised or no longer needed, revoke it immediately with DELETE /v1/keys/{key_id}:
curl -X DELETE https://api.docintell.com/v1/keys/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer dk_live_YOUR_ADMIN_KEY"
Response: 204 No Content
Revocation is immediate. The key stops working as soon as the request completes. There is no grace period.

When to Revoke vs Rotate

ScenarioAction
Suspected key compromiseRevoke immediately, then create a new key
Routine security hygieneRotate (7-day grace period)
Decommissioning a serviceRevoke once the service is shut down
Employee offboardingRevoke keys associated with that employee
Revoked keys are retained in the database for audit purposes but cannot be used for authentication.

Monitoring Your API Keys

Effective API key monitoring helps you maintain security, track usage, and prevent service disruptions during key rotation. The GET /v1/keys endpoint provides comprehensive visibility into your key inventory.

List All Keys

Retrieve all API keys in your account with their metadata:
curl -X GET https://api.docintell.com/v1/keys \
  -H "Authorization: Bearer dk_live_YOUR_API_KEY"
Example Response:
{
  "keys": [
    {
      "key_id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Production Server",
      "key_prefix": "dk_live_",
      "key_suffix": "nols",
      "environment": "live",
      "is_active": true,
      "status": "active",
      "created_at": "2024-01-15T10:30:00Z",
      "last_used_at": "2024-01-15T12:45:00Z",
      "deprecated_at": null,
      "grace_period_ends_at": null,
      "grace_period_days_remaining": null
    },
    {
      "key_id": "660e8400-e29b-41d4-a716-446655440001",
      "name": "Old Production Key",
      "key_prefix": "dk_live_",
      "key_suffix": "aBc1",
      "environment": "live",
      "is_active": true,
      "status": "deprecated",
      "created_at": "2024-01-01T10:30:00Z",
      "last_used_at": "2024-01-15T12:45:00Z",
      "deprecated_at": "2024-01-15T10:30:00Z",
      "grace_period_ends_at": "2024-01-22T10:30:00Z",
      "grace_period_days_remaining": 5
    }
  ]
}

Query Parameters

ParameterTypeDefaultDescription
include_deprecatedbooleantrueInclude keys in grace period (deprecated but still active)
Example: Hide deprecated keys
curl -X GET "https://api.docintell.com/v1/keys?include_deprecated=false" \
  -H "Authorization: Bearer dk_live_YOUR_API_KEY"

Response Fields

Each key in the response includes the following fields:
FieldTypeDescription
key_idUUIDUnique identifier for the key
namestringDescriptive name (e.g., “Production Server”)
key_prefixstringFirst 8 characters (e.g., dk_live_)
key_suffixstringLast 4 characters for identification
environmentstringlive or test
is_activebooleanWhether the key can still be used for authentication
statusstringKey lifecycle status: active, deprecated, or expired
created_attimestampWhen the key was created
last_used_attimestampMost recent successful authentication (null if never used)
deprecated_attimestampWhen rotation began (null if not deprecated)
grace_period_ends_attimestampWhen deprecated key expires (null if not deprecated)
grace_period_days_remainingintegerDays left before deprecated key expires (null if not deprecated)
For security, the full API key is never shown after creation. Only the prefix (dk_live_) and last 4 characters are displayed for identification.

Key Status Lifecycle

API keys transition through three lifecycle states:
1

Active

Normal operation
  • Key is working and valid
  • status: "active"
  • is_active: true
  • Can authenticate API requests
  • No expiration date
2

Deprecated

Grace period after rotation
  • Key was replaced via rotation
  • status: "deprecated"
  • is_active: true (still works!)
  • Can still authenticate for 7 days
  • Monitor grace_period_days_remaining
  • Automatically expires after grace period
Timeline:
Day 0: Rotation initiated → deprecated_at set
Days 1-7: Grace period → key still works
Day 8: Automatic expiration → status becomes "expired"
3

Expired

Grace period ended
  • Key can no longer authenticate
  • status: "expired"
  • is_active: false
  • Retained for audit purposes
  • Cannot be reactivated (create a new key instead)
Revoked keys have a special status:
  • status: "revoked" (not shown in lifecycle above)
  • is_active: false
  • Immediately stopped (no grace period)
  • Result of manual DELETE /v1/keys/{key_id} call

Monitoring Best Practices

Track Unused Keys

Identify keys that haven’t been used in 30+ days for security audits.
from datetime import datetime, timedelta

cutoff = datetime.utcnow() - timedelta(days=30)

for key in keys:
    if key["last_used_at"] is None:
        print(f"⚠️ Never used: {key['name']}")
    elif datetime.fromisoformat(key["last_used_at"].replace("Z", "+00:00")) < cutoff:
        print(f"⚠️ Unused (30+ days): {key['name']}")

Monitor Grace Periods

Track keys nearing expiration during rotation.
for key in keys:
    if key["status"] == "deprecated":
        days = key["grace_period_days_remaining"]
        if days <= 2:
            print(f"🚨 Expires soon: {key['name']} ({days} days)")
        else:
            print(f"⏳ In rotation: {key['name']} ({days} days)")

Verify Active Keys

Ensure production services use active (non-deprecated) keys.
active_keys = [k for k in keys if k["status"] == "active"]
deprecated_keys = [k for k in keys if k["status"] == "deprecated"]

print(f"✅ Active: {len(active_keys)}")
print(f"⏳ In grace period: {len(deprecated_keys)}")

Set Up Alerts

Create automated alerts for key expiration.Example cron job (daily check):
# /etc/cron.daily/check-api-keys
#!/bin/bash
python /scripts/check_api_keys.py

Example: Automated Key Health Check

Here’s a complete script that monitors API key health and warns about potential issues:
#!/usr/bin/env python3
"""API Key Health Check - Run daily to monitor key status."""
import os
import sys
from datetime import datetime, timedelta

import requests

API_KEY = os.environ["DOCINTELL_API_KEY"]
BASE_URL = "https://api.docintell.com"

def check_api_keys():
    """Check API key health and report issues."""
    response = requests.get(
        f"{BASE_URL}/v1/keys",
        headers={"Authorization": f"Bearer {API_KEY}"}
    )
    response.raise_for_status()

    keys = response.json()["keys"]
    issues = []

    # Check 1: Unused keys (never used or >30 days)
    cutoff = datetime.utcnow() - timedelta(days=30)
    for key in keys:
        if key["last_used_at"] is None:
            issues.append(f"⚠️ UNUSED: '{key['name']}' has never been used")
        else:
            last_used = datetime.fromisoformat(
                key["last_used_at"].replace("Z", "+00:00")
            )
            if last_used < cutoff:
                days_ago = (datetime.utcnow().replace(tzinfo=last_used.tzinfo) - last_used).days
                issues.append(
                    f"⚠️ STALE: '{key['name']}' not used in {days_ago} days"
                )

    # Check 2: Keys in grace period
    for key in keys:
        if key["status"] == "deprecated":
            days = key["grace_period_days_remaining"]
            if days <= 2:
                issues.append(
                    f"🚨 URGENT: '{key['name']}' expires in {days} days!"
                )
            else:
                issues.append(
                    f"⏳ GRACE PERIOD: '{key['name']}' expires in {days} days"
                )

    # Check 3: Multiple active keys (should only have 1 per environment)
    active_live = [k for k in keys if k["status"] == "active" and k["environment"] == "live"]
    active_test = [k for k in keys if k["status"] == "active" and k["environment"] == "test"]

    if len(active_live) > 1:
        issues.append(
            f"⚠️ MULTIPLE LIVE KEYS: {len(active_live)} active live keys found"
        )
    if len(active_test) > 3:
        issues.append(
            f"⚠️ MANY TEST KEYS: {len(active_test)} active test keys found"
        )

    # Report results
    if issues:
        print("API Key Health Check - Issues Found:")
        for issue in issues:
            print(f"  {issue}")
        return 1
    else:
        print("✅ API Key Health Check - All keys healthy")
        return 0

if __name__ == "__main__":
    sys.exit(check_api_keys())
Usage:
# Set up environment variable
export DOCINTELL_API_KEY="dk_live_YOUR_KEY"

# Run the check
python check_api_keys.py

# Or set up as a cron job (daily at 9 AM)
0 9 * * * /usr/local/bin/check_api_keys.py
Integrate this health check into your monitoring stack:
  • Send alerts to Slack or PagerDuty when issues are detected
  • Track key usage metrics in Datadog or Prometheus
  • Run checks before deployments to catch expiring keys early

Best Practices

Store Keys Securely

Environment Variables

Store keys in environment variables, never in code:
export DOCINTELL_API_KEY="dk_live_..."
Access in your application:
import os
api_key = os.environ["DOCINTELL_API_KEY"]

Secrets Managers

Use a secrets manager for production:
  • AWS Secrets Manager
  • GCP Secret Manager
  • HashiCorp Vault
  • Azure Key Vault
Never commit API keys to version control. Add .env files to your .gitignore:
# .gitignore
.env
.env.local
.env.*.local

Use Separate Keys per Environment

EnvironmentKey TypeStoragePurpose
Developmentdk_test_.env.localLocal development
Stagingdk_test_Secrets managerIntegration testing
Productiondk_live_Secrets managerCustomer-facing workloads
Test keys (dk_test_) are free and never billed. Use them liberally for development and testing.

Rotate Keys Regularly

1

Set a Rotation Schedule

Rotate keys every 90 days as a security best practice.Set calendar reminders or use automation:
# Example: Rotate keys quarterly
0 0 1 */3 * /usr/local/bin/rotate-docintell-keys.sh
2

Monitor Grace Periods

Track upcoming key expirations to avoid service disruptions.Check grace_period_days_remaining in the API response.
3

Audit Key Usage

Review last_used_at timestamps monthly to identify:
  • Unused keys (can be revoked)
  • Keys in use by unknown systems (investigate)

Minimize Key Scope

One Key per Service

Create separate API keys for each service or application.This limits the blast radius if one key is compromised.

Descriptive Names

Use clear, descriptive names:
  • “Production API Server - us-east-1”
  • “CI/CD Pipeline - GitHub Actions”
  • “My Key”
  • “Test”

Monitor for Suspicious Activity

Check last_used_at timestamps regularly:
# List all keys with usage timestamps
curl -X GET https://api.docintell.com/v1/keys \
  -H "Authorization: Bearer dk_live_YOUR_API_KEY" \
  | jq '.keys[] | {name, last_used_at, status}'
If a key shows unexpected usage, revoke it immediately and investigate.

Error Handling

Missing Authorization Header

{
  "error": "missing_api_key",
  "message": "Authorization header is required"
}
HTTP Status: 401 Unauthorized Fix: Include the Authorization: Bearer header in all requests.

Invalid API Key

{
  "error": "invalid_api_key",
  "message": "The provided API key is invalid or has been revoked"
}
HTTP Status: 401 Unauthorized Possible Causes:
  • Key was revoked
  • Key expired after grace period
  • Typo in the key value
  • Wrong environment (using test key on production URL or vice versa)

Malformed Authorization Header

{
  "error": "malformed_auth_header",
  "message": "Authorization header must use Bearer scheme"
}
HTTP Status: 401 Unauthorized Fix: Ensure the header format is exactly: Authorization: Bearer dk_live_...

Next Steps