adaptlive
← API Reference

Error Handling

The API uses standard HTTP status codes with structured JSON error responses. Every error includes a code for programmatic handling and a human-readable message.

Error Response Format

All error responses follow this structure:

{
  "error": {
    "code": "not_found",
    "message": "Party with ID 'party_invalid' not found.",
    "details": {
      // Optional additional context
    }
  },
  "meta": {
    "requestId": "req_abc123xyz"
  }
}

Always include the requestId when contacting support—it lets us trace the exact request through our systems.

Error Codes

400bad_request

Request body or query is malformed. `error.details` includes Zod issues when validation failed.

Resolution: Check the request shape against the OpenAPI spec (/openapi.json). Fix the offending field.

401unauthorized

Missing, malformed, or revoked Authorization header.

Resolution: Send `Authorization: Bearer ak_live_…` (or `ak_test_…`). Mint a fresh key if yours was revoked.

401unsupported_auth_scheme

Authorization header used a scheme we don't accept (e.g. Basic).

Resolution: Use Bearer with an adaptlive API key.

403forbidden

Valid credentials, but either your org isn't enabled for /api/v1 or your key's scope is too narrow for this operation.

Resolution: Confirm the key's scope (READ ⊂ WRITE ⊂ ADMIN). For dev-portal enablement, email developers@adaptlive.app.

404not_found

No record matches the given identifier — either it doesn't exist or it belongs to a different organization.

Resolution: Verify the id and that the key has access to its parent org.

409idempotency_conflict

An idempotency key was reused with a different request body. The API refuses to replay because the inputs disagree.

Resolution: Drop the idempotency key, or replay with the exact original body.

429rate_limited

Throttled. Honor the Retry-After header on the first retry; back off with jitter after that.

Resolution: See the Authentication → Rate limits section for headers + recommended retry strategy.

500internal_error

Unexpected server error. Always logged with the requestId.

Resolution: Retry once. If it persists, email developers@adaptlive.app with the `meta.requestId` from the response.

HTTP Status Codes

RangeMeaningAction
2xxSuccessRequest completed successfully.
4xxClient errorFix the request before retrying.
5xxServer errorSafe to retry with exponential backoff.

Retry Strategy

For transient errors (429, 5xx), implement exponential backoff with jitter:

async function fetchWithRetry(url, options, maxRetries = 3) {
  let lastError;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const res = await fetch(url, options);

      if (res.status === 429) {
        // Out of retries — surface the throttle to the caller instead
        // of falling out of the loop with no return value.
        if (attempt === maxRetries) {
          throw new Error(`Rate limited after ${maxRetries + 1} attempts`);
        }
        const retryAfter = res.headers.get("Retry-After") || "1";
        await sleep(parseInt(retryAfter, 10) * 1000);
        continue;
      }

      if (res.status >= 500) {
        throw new Error(`Server error: ${res.status}`);
      }

      return res;
    } catch (err) {
      lastError = err;
      if (attempt === maxRetries) throw err;

      // Exponential backoff with jitter
      const baseDelay = Math.pow(2, attempt) * 1000;
      const jitter = Math.random() * 1000;
      await sleep(baseDelay + jitter);
    }
  }

  // Belt-and-suspenders: the loop above always exits via return or
  // throw, but keep this so the function's contract ("returns a
  // Response or throws") holds even if someone tweaks the loop later.
  throw lastError ?? new Error("fetchWithRetry exhausted without a response");
}

Validation Errors

When request validation fails, the error includes field-level details:

{
  "error": {
    "code": "bad_request",
    "message": "Validation failed.",
    "details": {
      "fields": [
        {
          "field": "email",
          "message": "Must be a valid email address."
        },
        {
          "field": "scheduledEnd",
          "message": "Must be after scheduledStart."
        }
      ]
    }
  },
  "meta": {
    "requestId": "req_abc123"
  }
}

Common Issues

"unauthorized" even with a valid-looking key
Check the key hasn't been revoked. Keys are organization-scoped—ensure you're using a key from the correct organization.
"forbidden" on write operations
Your API key may have READ-only scope. Mint a new key with WRITE scope from /portal/api-keys.
"not_found" for a record you just created
Records are organization-scoped. Verify the API key belongs to the same organization that owns the record.
Unexpected 500 errors
Include the requestId when contacting developers@adaptlive.app.
Zapier Integration →← Back to API Reference

We use essential cookies to keep the app secure. Optional cookies help us improve reliability and measure campaigns. Cookie policy