Forlena CRM API

Error Handling

Use error codes for machine branching, and retry only when it is safe.

HTTPCodeMeaningAction
400VALIDATION_ERRORRequest shape or field values are invalid.Fix payload and retry.
401INVALID_KEYAPI key is missing, malformed, or unknown.Use valid Authorization header.
401KEY_REVOKEDAPI key was revoked by admin.Generate a new key.
401SUBSCRIPTION_INACTIVEOrganization subscription/trial is inactive.Reactivate plan, then retry.
404NOT_FOUNDResource does not exist in your org scope.Verify ID and org ownership.
429RATE_LIMITEDPer-endpoint per-minute limit exceeded.Use exponential backoff + jitter.
429ORG_RATE_LIMITEDOrganization minute rate limit exceeded.Reduce parallel fan-out and retry with backoff.
429API_QUOTA_EXCEEDEDMonthly total API quota reached for your org.Wait until reset or increase monthly quota.
429QUOTA_EXCEEDEDMonthly AI quota reached for your org.Wait until reset or increase quota.
500INTERNAL_ERRORUnexpected server-side failure.Retry idempotent requests with limits.

429 Rate Limit Example

json
{
  "error": "Rate limit exceeded",
  "code": "RATE_LIMITED",
  "retry_after_seconds": 60
}

429 Total API Quota Example

json
{
  "error": "Monthly API quota exceeded",
  "code": "API_QUOTA_EXCEEDED",
  "limit": 50000,
  "used": 50000,
  "remaining": 0,
  "reset_at": "2026-04-01T00:00:00.000Z"
}

429 AI Quota Example

json
{
  "error": "Monthly AI API quota exceeded",
  "code": "QUOTA_EXCEEDED",
  "limit": 5000,
  "used": 5000,
  "remaining": 0,
  "reset_at": "2026-04-01T00:00:00.000Z"
}

Retry Strategy (JavaScript)

Retry only for 429 or 5xx. Do not retry 400/401/404 until request or credentials are corrected.

javascript
async function fetchWithRetry(url, options, maxRetries = 4) {
  for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
    const res = await fetch(url, options);
    if (res.status !== 429 && res.status < 500) return res;

    if (attempt === maxRetries) return res;

    const jitter = Math.floor(Math.random() * 250);
    const delayMs = Math.min(1000 * 2 ** attempt + jitter, 15000);
    await new Promise((resolve) => setTimeout(resolve, delayMs));
  }
}