Skip to main content
ClinikAPI uses standard HTTP status codes and returns structured JSON error responses on every failure. The TypeScript SDK maps these responses to typed error classes so you can handle specific error conditions without parsing raw strings. This page covers the error format, all status and error codes, SDK error handling, automatic retries, and rate limit headers.

Error response format

Every error response includes a human-readable message, a machine-readable code, a request ID for support, and an optional array of validation issues:
{
  "error": "Validation Error",
  "code": "VALIDATION_ERROR",
  "requestId": "req_k8f3a7x2",
  "issues": [
    {
      "severity": "error",
      "code": "invalid",
      "diagnostics": "firstName: Required"
    }
  ]
}
Include the requestId when contacting support — it traces the full request through ClinikAPI’s infrastructure.

HTTP status codes

StatusMeaning
400Bad request — malformed JSON or invalid parameters
401Unauthorized — missing or invalid API key
403Forbidden — key does not have the required scope
404Not found — resource does not exist or belongs to another tenant
409Conflict — resource version conflict
422Validation error — request body failed schema validation
429Rate limited — too many requests for your plan
500Internal error — something went wrong on ClinikAPI’s end

Error codes

CodeDescription
UNAUTHORIZEDMissing x-api-key header
INVALID_KEY_FORMATKey does not match clk_live_* or clk_test_* pattern
INVALID_KEYKey not found in the database
KEY_REVOKEDKey has been revoked
KEY_EXPIREDKey has passed its expiration date
VALIDATION_ERRORRequest body failed schema validation
RATE_LIMITEDPlan request limit exceeded
NOT_FOUNDResource not found
INTERNAL_ERRORUnexpected server error

SDK error handling

The SDK throws typed error classes that you can catch and branch on. This lets you handle validation failures, rate limits, and general API errors with different logic:
import { Clinik } from '@clinikapi/sdk';

const clinik = new Clinik(process.env.CLINIKAPI_SECRET_KEY!);

try {
  const { data } = await clinik.patients.create({
    firstName: 'Jane',
    lastName: 'Doe',
  });
} catch (err) {
  if (err.name === 'ClinikValidationError') {
    // Request body failed schema validation
    console.error('Validation issues:', err.issues);
  } else if (err.name === 'ClinikRateLimitError') {
    // Plan limit exceeded — err.retryAfter is seconds until reset
    console.error('Rate limited. Retry after:', err.retryAfter, 'seconds');
  } else if (err.name === 'ClinikApiError') {
    // All other API errors
    console.error('API error:', err.code, err.message);
    console.error('Request ID:', err.requestId);
  }
}
Pass err.requestId to ClinikAPI support when reporting unexpected ClinikApiError instances.

Automatic retries

The SDK automatically retries on 5xx errors and 429 rate limit responses using jittered exponential backoff:
  • Default: 2 retries
  • Backoff: random jitter up to min(1000 * 2^attempt, 10000) ms
  • Both retries and timeout are configurable at client initialization:
const clinik = new Clinik(process.env.CLINIKAPI_SECRET_KEY!, {
  retries: 3,      // max retry attempts
  timeout: 15000,  // request timeout in ms
});
Set retries: 0 to disable automatic retries entirely.

Rate limit headers

Rate limits are plan-based. Every response includes headers so you can track your usage and back off proactively:
HeaderDescription
X-RateLimit-LimitTotal requests allowed per window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetSeconds until the window resets
The SDK surfaces these values in the meta field of every response, so you do not need to parse headers directly:
const { data, meta } = await clinik.patients.search();
console.log(meta.rateLimitRemaining); // 498

PHI sanitization

Error responses never contain Protected Health Information (PHI). Field values are stripped from all validation error messages — only field names and constraint descriptions are included. For example, a validation error on birthDate will report "birthDate: Invalid date format", not the value you submitted.