API

Compliance API reference

The live subject-check, sandbox, account API-key, and webhook signing endpoints in one focused reference.

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>
Compromised token. If the current secret is available, rotate it immediately, save the one-time replacement, and switch callers. Otherwise, revoke it through the session-authenticated account endpoint, mint a replacement, deploy it, and remove the exposed value from secret storage, logs, and code.

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.

401 Unauthorized · invalid_key_format
{
  "error": {
    "code": "invalid_key_format",
    "message": "API key required. Use Authorization: Bearer vda_<token>"
  }
}
Remediation. Check for a missing or malformed 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.
400 Bad Request · invalid_payload
{
  "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"
    ]
  }
}
Remediation. Check the request shape in the sandbox guidance and the full schema at POST /subject-checks/sandbox. Correct every named field in error.errors before retrying.
429 Too Many Requests · rate_limited
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded: 60 subject checks/hour. Check Retry-After header."
  }
}
Remediation. Read the accompanying 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.
500 Internal Server Error · internal_error
{
  "error": {
    "code": "internal_error",
    "message": "Failed to start subject check"
  }
}
Remediation. Retry the request, then follow the subject-check guidance and contact support if the failure persists.

Live endpoints

Every path below is registered by the current application. Use the existing Compliance API reference for the full request and response schemas.

Live route names. Account key minting and listing use 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

Method
POST
Path
/api/v1/compliance/subject-checks
Required request headers
Authorization: Bearer vda_<token>
Content-Type: application/json
Auth model
Account-scoped third-party bearer authentication via authenticateAccountApiKey.
Description
Starts an asynchronous subject check and returns a 201 handoff with a running check ID.
400 Bad Request · invalid_payload
{
  "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"
    ]
  }
}
401 Unauthorized · invalid_key_format
{
  "error": {
    "code": "invalid_key_format",
    "message": "API key required. Use Authorization: Bearer vda_<token>"
  }
}
500 Internal Server Error · internal_error
{
  "error": {
    "code": "internal_error",
    "message": "Failed to start subject check"
  }
}
Remediation. Correct the request payload and its required fields, supply a live vda_ bearer token, or retry and contact support if the server returns 500.

Sandbox subject check

Method
POST
Path
/api/v1/compliance/subject-checks/sandbox
Required request headers
Authorization: Bearer vda_<token>
Content-Type: application/json
Auth model
Account-scoped third-party bearer authentication via authenticateAccountApiKey.
Description
Returns a deterministic completed clear_no_match verdict without a database write, quota decrement, or rate-limit decrement.
400 Bad Request · invalid_payload
{
  "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"
    ]
  }
}
401 Unauthorized · invalid_key_format
{
  "error": {
    "code": "invalid_key_format",
    "message": "API key required. Use Authorization: Bearer vda_<token>"
  }
}
500 Internal Server Error · internal_error
{
  "error": {
    "code": "internal_error",
    "message": "Failed to run sandbox subject check"
  }
}
Remediation. Payload and authentication failures are fixed by the caller: correct the request and supply a live vda_ bearer token. Retry a 500 sandbox failure.

Mint an account API key

Method
POST
Path
/api/account/api-keys
Required request headers
Cookie: auth_token=<session>
Content-Type: application/json
Auth model
Authenticated browser/session JWT via authenticateToken, scoped to the signed-in account.
Description
Mints a vda_ integration key and returns its plaintext exactly once.
401 Unauthorized
{
  "success": false,
  "message": "Authentication required"
}
400 Bad Request
{
  "success": false,
  "message": "name is required (1-100 characters)"
}
201 Created
{
  "success": true,
  "id": 42,
  "name": "production",
  "token_prefix": "vda_a1b2",
  "created_at": "2026-09-12T12:00:00.000Z",
  "key": "vda_<token>"
}
500 Internal Server Error
{
  "success": false,
  "message": "Failed to mint API key"
}
Remediation. Sign in again or refresh the session, provide a key name from 1–100 characters, or retry and report a server failure to support.

List account API keys

Method
GET
Path
/api/account/api-keys
Required request headers
Cookie: auth_token=<session>
Auth model
Authenticated browser/session JWT via authenticateToken, scoped to the signed-in account.
Description
Lists key IDs and masked metadata for the signed-in account. Plaintext secrets are never returned.
200 OK
{
  "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
    }
  ]
}
Secret handling. Use 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

Method
POST
Path
/api/v1/compliance/api-keys/rotate
Required request headers
Authorization: Bearer vda_<current-token>
Auth model
Account-scoped third-party bearer authentication via authenticateAccountApiKey.
Description
Replaces the current token on the same key row, invalidates the old token immediately, and returns the replacement plaintext exactly once. The request has no body.
201 Created
{
  "success": true,
  "id": 42,
  "account_id": 7,
  "token_prefix": "vda_c3d4",
  "created_at": "2026-09-12T12:05:00.000Z",
  "key": "vda_<replacement-token>"
}
One-time response. Store the replacement immediately; the old bearer token returns 401 with invalid_key after rotation.

Revoke an account API key

Method
DELETE
Path
/api/account/api-keys/:id
Required request headers
Cookie: auth_token=<session>
No body header required.
Auth model
Authenticated browser/session JWT via authenticateToken, scoped to the signed-in account.
Description
Immediately revokes the selected API key when it belongs to the authenticated account.
401 Unauthorized
{
  "success": false,
  "message": "Authentication required"
}
400 Bad Request
{
  "success": false,
  "message": "Invalid key id"
}
404 Not Found
{
  "success": false,
  "message": "API key not found"
}
500 Internal Server Error
{
  "success": false,
  "message": "Failed to revoke API key"
}
Remediation. Sign in again or refresh the session, send a valid numeric key ID, or retry and report a server failure to support.

Webhook signing

Method
POST setup
POST delivery
Path
/api/v1/compliance/webhooks setup
<registered callback URL> delivery
Required request headers
Setup: Authorization: Bearer vda_<token> Content-Type: application/json
Delivery: Content-Type: application/json X-Veridact-Signature: sha256=<hex>
Auth model
The setup call uses the account-scoped bearer token; your callback verifies delivery with the returned signing_secret.
Description
Registers or updates a callback URL, then signs each outbound JSON POST with HMAC-SHA256 over the exact raw JSON bytes.
Verify the exact body bytes
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 note. Store the signing_secret returned by the setup call and preserve the raw request bytes before parsing the JSON body.
Was this page helpful?