API token lifecycle
Keep vda_ tokens server-side and treat the plaintext as a one-time credential. Follow this mint → store → rotate → revoke sequence to keep an integration live without leaving the API reference.
1. Mint. Use the account API-key endpoint with an authenticated session. Send Cookie: auth_token=<session> and Content-Type: application/json; the JSON body must include a name.
POST /api/account/api-keys
Cookie: auth_token=<session>
Content-Type: application/json
{"name":"production"}
2. Store. The 201 response’s key field contains the vda_ plaintext exactly once. Copy it immediately into server-side secret storage. Never put it in source control, browser code, request or console logs, or client-visible configuration. It cannot be reconstructed later: the service retains only the SHA-256 hash and token prefix. See the mint reference for the one-time response.
3. Rotate. For zero downtime, mint a second key, deploy the new secret, switch callers to Authorization: Bearer vda_<new-token>, verify traffic, then revoke the old key. For in-place rotation, use the POST /api/v1/compliance/api-keys/rotate endpoint with the current bearer header; its 201 response returns a one-time replacement key and invalidates the old token immediately.
POST /api/v1/compliance/api-keys/rotate Authorization: Bearer vda_<current-token>
4. Revoke. Get the numeric key ID from the account key list endpoint, then use the account revoke endpoint with DELETE /api/account/api-keys/:id and Cookie: auth_token=<session>. Revocation is immediate; subsequent bearer calls return 401 with invalid_key.
DELETE /api/account/api-keys/<id> Cookie: auth_token=<session>
Error handling
Branch on the HTTP status and stable error.code, not the human-readable message. The response body follows the examples below; messages may become more specific as validation and platform behavior evolve.
{
"error": {
"code": "invalid_key_format",
"message": "API key required. Use Authorization: Bearer vda_<token>"
}
}
Authorization: Bearer vda_<token> header, then follow the token lifecycle guidance. For invalid_key or key_expired, rotate or replace the revoked/expired token and see the detailed error-code contract.
{
"error": {
"code": "invalid_payload",
"message": "first_name is required",
"errors": [
"first_name is required",
"last_name is required",
"At least one location is required",
"purpose is required",
"Consent certification is required"
]
}
}
error.errors before retrying.
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded: 60 subject checks/hour. Check Retry-After header."
}
}
Retry-After response header, whose value is in seconds; it is not part of the JSON body. Follow the rate-limit guidance and sandbox guidance, then wait/back off instead of retrying immediately.
{
"error": {
"code": "internal_error",
"message": "Failed to start subject check"
}
}
Live endpoints
Every path below is registered by the current application. Use the existing Compliance API reference for the full request and response schemas.
POST/GET /api/account/api-keys; revocation uses DELETE /api/account/api-keys/:id. In-place bearer rotation uses POST /api/v1/compliance/api-keys/rotate.
Subject check
POST/api/v1/compliance/subject-checksAuthorization: Bearer vda_<token>Content-Type: application/jsonauthenticateAccountApiKey.201 handoff with a running check ID.{
"error": {
"code": "invalid_payload",
"message": "first_name is required",
"errors": [
"first_name is required",
"last_name is required",
"At least one location is required",
"purpose is required",
"Consent certification is required"
]
}
}
{
"error": {
"code": "invalid_key_format",
"message": "API key required. Use Authorization: Bearer vda_<token>"
}
}
{
"error": {
"code": "internal_error",
"message": "Failed to start subject check"
}
}
vda_ bearer token, or retry and contact support if the server returns 500.
Sandbox subject check
POST/api/v1/compliance/subject-checks/sandboxAuthorization: Bearer vda_<token>Content-Type: application/jsonauthenticateAccountApiKey.clear_no_match verdict without a database write, quota decrement, or rate-limit decrement.{
"error": {
"code": "invalid_payload",
"message": "first_name is required",
"errors": [
"first_name is required",
"last_name is required",
"At least one location is required",
"purpose is required",
"Consent certification is required"
]
}
}
{
"error": {
"code": "invalid_key_format",
"message": "API key required. Use Authorization: Bearer vda_<token>"
}
}
{
"error": {
"code": "internal_error",
"message": "Failed to run sandbox subject check"
}
}
vda_ bearer token. Retry a 500 sandbox failure.
Mint an account API key
POST/api/account/api-keysCookie: auth_token=<session>Content-Type: application/jsonauthenticateToken, scoped to the signed-in account.vda_ integration key and returns its plaintext exactly once.{
"success": false,
"message": "Authentication required"
}
{
"success": false,
"message": "name is required (1-100 characters)"
}
{
"success": true,
"id": 42,
"name": "production",
"token_prefix": "vda_a1b2",
"created_at": "2026-09-12T12:00:00.000Z",
"key": "vda_<token>"
}
{
"success": false,
"message": "Failed to mint API key"
}
List account API keys
GET/api/account/api-keysCookie: auth_token=<session>authenticateToken, scoped to the signed-in account.{
"success": true,
"keys": [
{
"id": 42,
"name": "production",
"token_prefix": "vda_a1b2",
"created_at": "2026-09-12T12:00:00.000Z",
"last_used_at": null,
"revoked_at": null
}
]
}
id from this response for revocation. token_prefix is prefix-only metadata; the plaintext key is not listed or recoverable.
Rotate an account API key in place
POST/api/v1/compliance/api-keys/rotateAuthorization: Bearer vda_<current-token>authenticateAccountApiKey.{
"success": true,
"id": 42,
"account_id": 7,
"token_prefix": "vda_c3d4",
"created_at": "2026-09-12T12:05:00.000Z",
"key": "vda_<replacement-token>"
}
401 with invalid_key after rotation.
Revoke an account API key
DELETE/api/account/api-keys/:idCookie: auth_token=<session>No body header required.
authenticateToken, scoped to the signed-in account.{
"success": false,
"message": "Authentication required"
}
{
"success": false,
"message": "Invalid key id"
}
{
"success": false,
"message": "API key not found"
}
{
"success": false,
"message": "Failed to revoke API key"
}
Webhook signing
POST setupPOST delivery/api/v1/compliance/webhooks setup<registered callback URL> deliveryAuthorization: Bearer vda_<token> Content-Type: application/jsonDelivery:
Content-Type: application/json X-Veridact-Signature: sha256=<hex>signing_secret.const crypto = require('crypto'); const signature = req.get('X-Veridact-Signature'); const expected = 'sha256=' + crypto .createHmac('sha256', signingSecret) .update(rawBody) .digest('hex'); const valid = signature === expected;
signing_secret returned by the setup call and preserve the raw request bytes before parsing the JSON body.