Skip to main content

Standard Error Response Format

All Verilock API errors return a consistent JSON structure, making it easy to handle errors programmatically regardless of the error type.
FieldTypeDescription
errorstringMachine-readable error code. Use this for programmatic error handling.
messagestringHuman-readable description of what went wrong.
detailsobject|nullAdditional context. For validation errors, contains field-level messages. May be null for other error types.

Error Types

The error field will contain one of the following values:
Error CodeHTTP StatusDescription
validation_error422One or more fields failed validation. Check details for field-specific messages.
authentication_error401API key is missing, invalid, or revoked.
not_found404The requested resource does not exist or has been deleted.
rate_limit_exceeded429Too many requests. Back off and retry after the Retry-After header value.
server_error500, 503An internal error occurred. Safe to retry with exponential backoff.

Best Practices

Retry with exponential backoff — For 5xx errors and 429 rate limits, retry with increasing delays: 1s, 2s, 4s, 8s. Add random jitter to prevent thundering herd.
Respect the Retry-After header — When you receive a 429 response, always wait for the number of seconds specified in the Retry-After header before making another request.
Log error responses — Store the full error response and the X-Request-Id header for debugging. Include these when contacting support.
Do not retry 4xx errors (except 429) — Client errors like 400, 401, 403, 404, and 422 will not resolve on retry. Fix the request before retrying.

Error Response Body

Error Response
{
  "error": "validation_error",
  "message": "The given data was invalid.",
  "details": {
    "field_name": [
      "The field name is required.",
      "The field name must be a string."
    ]
  }
}

PHP Error Handling Example

PHP (Guzzle)
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

$client = new Client([
    'base_uri' => 'https://verilock.io/api/v1/',
    'headers'  => [
        'X-API-Key' => 'your_api_key_here',
        'Accept'    => 'application/json',
    ],
]);

$maxRetries = 3;

for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
    try {
        $response = $client->post('sessions', [
            'json' => ['workflow_id' => 'wf_abc123'],
        ]);

        $data = json_decode($response->getBody(), true);
        // Success — process $data
        break;

    } catch (RequestException $e) {
        $status = $e->getResponse()?->getStatusCode();
        $body   = json_decode($e->getResponse()?->getBody(), true);

        if ($status === 422) {
            // Validation error — do not retry
            log_error('Validation failed', $body['details'] ?? []);
            break;
        }

        if ($status === 429) {
            // Rate limited — wait and retry
            $wait = $e->getResponse()->getHeaderLine('Retry-After') ?: 5;
            sleep((int) $wait);
            continue;
        }

        if ($status >= 500) {
            // Server error — retry with backoff
            sleep(pow(2, $attempt));
            continue;
        }

        // Other client error — do not retry
        log_error($body['error'] ?? 'unknown', $body['message'] ?? '');
        break;
    }
}