Skip to main content

API key management

This recipe shows how to manage API keys for your tenant. API keys are long-lived credentials suitable for server-to-server integrations where OAuth 2.0 is impractical (e.g., legacy systems, embedded devices, batch jobs).

Endpoints​

GET /v1/tenants/{id}/api-keys # List all API keys (metadata only)
POST /v1/tenants/{id}/api-keys # Create a new API key
DELETE /v1/tenants/{id}/api-keys/{keyId} # Revoke an API key
POST /v1/tenants/{id}/api-keys/{keyId}/rotate # Rotate an API key

API key secrets are returned only at creation or rotation time. They are never retrievable after the initial response.

Prerequisites​

  • A valid tenantId and bearer JWT.
  • The user must have the tenant_admin role.

Create an API key​

curl -X POST https://api.falconveritas.com/v1/tenants/$FVI_TENANT_ID/api-keys \
-H "Authorization: Bearer $FVI_JWT" \
-H "X-Tenant-Id: $FVI_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Production ETL job",
"description": "API key for the nightly reconciliation ETL job",
"scopes": ["read:reconciliations", "write:exceptions"],
"expires_at": "2027-08-22T00:00:00Z",
"ip_allowlist": ["203.0.113.0/24"],
"idempotency_key": "apikey-fvi-$RANDOM"
}'

Response​

{
"id": "key-001",
"name": "Production ETL job",
"key_id": "pk_live_abc123def456",
"key_secret": "sk_live_xyz789ghi012jkl345mno678pqr901stu234vwx567",
"scopes": ["read:reconciliations", "write:exceptions"],
"expires_at": "2027-08-22T00:00:00Z",
"ip_allowlist": ["203.0.113.0/24"],
"created_at": "2026-08-22T18:00:00Z",
"created_by": "user:admin",
"warning": "Store the key_secret securely. It will not be shown again."
}

Use the API key​

curl -X GET "https://api.falconveritas.com/v1/reconciliations" \
-H "Authorization: Bearer pk_live_abc123def456.sk_live_xyz789ghi012jkl345mno678pqr901stu234vwx567" \
-H "X-Tenant-Id: $FVI_TENANT_ID"

Rotate an API key​

Rotation creates a new key while keeping the old key valid for a grace period. This enables zero-downtime rotation for production integrations:

curl -X POST https://api.falconveritas.com/v1/tenants/$FVI_TENANT_ID/api-keys/key-001/rotate \
-H "Authorization: Bearer $FVI_JWT" \
-H "X-Tenant-Id: $FVI_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"grace_period_seconds": 86400,
"idempotency_key": "apikey-rotate-fvi-$RANDOM"
}'

The response returns the new key, while the old key remains valid for 24 hours. After the grace period expires, the old key is automatically revoked.

Revoke an API key​

curl -X DELETE "https://api.falconveritas.com/v1/tenants/$FVI_TENANT_ID/api-keys/key-001" \
-H "Authorization: Bearer $FVI_JWT" \
-H "X-Tenant-Id: $FVI_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"reason": "Compromised in vendor breach",
"idempotency_key": "apikey-revoke-fvi-$RANDOM"
}'

List API keys​

curl -X GET "https://api.falconveritas.com/v1/tenants/$FVI_TENANT_ID/api-keys" \
-H "Authorization: Bearer $FVI_JWT" \
-H "X-Tenant-Id: $FVI_TENANT_ID"

Returns metadata only — never the key secret. The response includes usage statistics (last used at, request count) for each key.

Best practices​

  1. Use OAuth where possible. Prefer OAuth 2.0 with PKCE over API keys for integrations that can support redirects.
  2. Scope keys narrowly. Each API key should have the minimum scopes required for its purpose.
  3. Set IP allowlists. Restrict API keys to the IP ranges of the systems that use them.
  4. Set expiry. Always set an expiry date to limit the blast radius of a leaked key.
  5. Rotate regularly. Rotate keys at least every 90 days, or immediately on staff changes.
  6. Audit usage. Review API key usage logs monthly for unexpected patterns.

Use cases​

  • Server-to-server integrations — authenticate backend services that cannot perform OAuth flows.
  • Legacy system integration — bring older systems that only support API key auth into FVI.
  • Embedded devices — authenticate IoT sensors or edge devices that pull reconciliation status.
  • Batch jobs — long-lived credentials for nightly ETL or reporting jobs.

Code samples​

TypeScript​

import { FVI } from '@falconveritas/sdk';

const fvi = new FVI({
baseUrl: 'https://api.falconveritas.com',
bearer: process.env.FVI_JWT!,
tenantId: process.env.FVI_TENANT_ID!,
});

// Create API key
const apiKey = await fvi.tenants.createApiKey(process.env.FVI_TENANT_ID!, {
name: 'Production ETL job',
scopes: ['read:reconciliations', 'write:exceptions'],
expiresAt: '2027-08-22T00:00:00Z',
idempotencyKey: `apikey-fvi-${Date.now()}`,
});

console.log('API Key ID:', apiKey.key_id);
console.log('API Key Secret (store securely!):', apiKey.key_secret);

// Rotate after 90 days
const rotated = await fvi.tenants.rotateApiKey(process.env.FVI_TENANT_ID!, apiKey.id, {
gracePeriodSeconds: 86400,
idempotencyKey: `apikey-rotate-fvi-${Date.now()}`,
});

console.log('New API Key Secret (store securely!):', rotated.key_secret);

Python​

from falconveritas import FVI

client = FVI(
bearer=os.environ["FVI_JWT"],
tenant_id=os.environ["FVI_TENANT_ID"],
)

api_key = client.tenants.create_api_key(
os.environ["FVI_TENANT_ID"],
name="Production ETL job",
scopes=["read:reconciliations", "write:exceptions"],
expires_at="2027-08-22T00:00:00Z",
idempotency_key=f"apikey-fvi-{int(time.time())}",
)
print("API Key ID:", api_key.key_id)
print("API Key Secret (store securely!):", api_key.key_secret)

rotated = client.tenants.rotate_api_key(
os.environ["FVI_TENANT_ID"],
api_key.id,
grace_period_seconds=86400,
idempotency_key=f"apikey-rotate-fvi-{int(time.time())}",
)
print("New API Key Secret (store securely!):", rotated.key_secret)

Last updated: 2026-08-22 · Page owner: Documentation · Source: src/lib/api/api-keys.ts.