Skip to content

Error Handling

OpenProspect returns JSON errors with a stable machine-readable code, a human-readable message, and optional details.

{
  "code": "AUTHORIZATION_ERROR",
  "message": "Missing required scopes: orders:write",
  "details": {
    "required_scopes": ["orders:write"],
    "user_scopes": ["orders:read"]
  }
}

Status Codes

Status Category Cause Resolution
400 Bad request The request is syntactically valid but not acceptable for the operation Correct the request fields
401 Authentication Missing, malformed, expired, or revoked API key Send an active API key as a bearer token
403 Authorization The API key lacks a required scope or resource access Add the required scope or use a different key
404 Not found The resource does not exist or is not visible to the key owner Check the identifier and organization context
409 Conflict The request conflicts with current resource state Refresh state and retry with current data
422 Validation Request body, path, or query parameters failed validation Use the schema from the interactive API
429 Rate limit Too many requests in a short time window Back off and retry later
500 Server Unexpected server error Retry with backoff and contact support if it persists

Error Codes

Code Status Description Cause Resolution
UNAUTHORIZED 401 The API key could not be authenticated Missing or invalid bearer token Set Authorization: Bearer lnc_live_...
AUTHORIZATION_ERROR 403 The key lacks a required scope Scope mismatch Request the missing scope
VALIDATION_ERROR 422 Input failed schema validation Missing or invalid field Compare the request with openapi-public.json
ORDER_NOT_FOUND 404 The order is unavailable Wrong ID or inaccessible organization Use GET /api/v1/orders to confirm visible orders
PROSPECT_SEARCH_NOT_FOUND 404 The prospect search is unavailable Wrong ID or inaccessible organization Use GET /api/v1/prospect-searches
BLACKLIST_NOT_FOUND 404 The blacklist is unavailable Wrong ID or inaccessible organization Use GET /api/v1/blacklists

Retry Rules

Status Retry
400, 401, 403, 404, 422 Do not retry without changing the request
409 Retry only after refreshing resource state
429 Retry with exponential backoff
500 Retry with exponential backoff and alert on repeated failures

Error Handling Examples

status="$(
  curl -sS -o /tmp/openprospect-response.json -w "%{http_code}" \
    https://api.openprospect.io/api/v1/orders \
    -H "Authorization: Bearer ${OPENPROSPECT_API_KEY}"
)"

if [ "$status" -ge 400 ]; then
  cat /tmp/openprospect-response.json
  exit 1
fi

cat /tmp/openprospect-response.json
import os
import time
from typing import Any

import httpx

api_key = os.environ["OPENPROSPECT_API_KEY"]

def request_with_backoff(url: str) -> dict[str, Any]:
    for attempt in range(3):
        response = httpx.get(
            url,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30.0,
        )
        if response.status_code < 400:
            return response.json()
        if response.status_code not in {429, 500, 502, 503, 504}:
            raise RuntimeError(response.text)
        time.sleep(2**attempt)
    raise RuntimeError("OpenProspect request failed after retries")

print(request_with_backoff("https://api.openprospect.io/api/v1/orders"))
async function requestWithBackoff(url) {
  for (let attempt = 0; attempt < 3; attempt += 1) {
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.OPENPROSPECT_API_KEY}` },
    });

    if (response.ok) {
      return response.json();
    }

    if (![429, 500, 502, 503, 504].includes(response.status)) {
      throw new Error(await response.text());
    }

    await new Promise((resolve) => setTimeout(resolve, 1000 * 2 ** attempt));
  }

  throw new Error("OpenProspect request failed after retries");
}

console.log(await requestWithBackoff("https://api.openprospect.io/api/v1/orders"));
interface ApiError {
  code: string;
  message: string;
  details?: Record<string, unknown>;
}

async function requestWithBackoff<T>(url: string): Promise<T> {
  for (let attempt = 0; attempt < 3; attempt += 1) {
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.OPENPROSPECT_API_KEY}` },
    });

    if (response.ok) {
      return (await response.json()) as T;
    }

    if (![429, 500, 502, 503, 504].includes(response.status)) {
      const error = (await response.json()) as ApiError;
      throw new Error(`${error.code}: ${error.message}`);
    }

    await new Promise((resolve) => setTimeout(resolve, 1000 * 2 ** attempt));
  }

  throw new Error("OpenProspect request failed after retries");
}
using System.Net;
using System.Net.Http.Headers;

var apiKey = Environment.GetEnvironmentVariable("OPENPROSPECT_API_KEY")
    ?? throw new InvalidOperationException("OPENPROSPECT_API_KEY is not set.");

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);

for (var attempt = 0; attempt < 3; attempt++)
{
    var response = await client.GetAsync("https://api.openprospect.io/api/v1/orders");

    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine(await response.Content.ReadAsStringAsync());
        break;
    }

    if (response.StatusCode is not HttpStatusCode.TooManyRequests and < HttpStatusCode.InternalServerError)
    {
        throw new InvalidOperationException(await response.Content.ReadAsStringAsync());
    }

    await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}