DocsAPI ReferenceAPI Response Codes & Rate Limits

API Response Codes & Rate Limits

Complete list of Lead Distro AI API HTTP status codes, error response shapes, rate limits, and exponential backoff recipe for ingest and ping endpoints.

Last updated:

HTTP Status Codes

StatusMeaningBody
201 CreatedLead accepted and distributedLead object with `id`, `status: ACCEPTED`, `buyer_id`
200 OKLead accepted but no buyer availableLead object with `status: UNMATCHED`
400 Bad RequestValidation failure (missing required field, wrong type, format)Error object with `field_errors` array
401 UnauthorizedAPI key missing or invalidError object with `error: unauthorized`
403 ForbiddenSupplier not attached to the campaignError object with `error: forbidden`
404 Not FoundCampaign ID doesn't existError object with `error: campaign_not_found`
422 Unprocessable EntityLead failed inbound filters or suppressionError with `filter_errors` array naming the rules that caught the lead
429 Too Many RequestsRate limit exceededError with `retry_after` (seconds)
500 Internal Server ErrorLead Distro AI bug — retry with backoffGeneric error message
503 Service UnavailableTemporary maintenance — retry with backoffGeneric error message

Error Response Shape

{
  "error": "validation_failed",
  "message": "One or more fields failed validation",
  "field_errors": [
    { "field": "phone", "code": "invalid_format", "message": "Phone must be 10-15 digits" },
    { "field": "case_type", "code": "required", "message": "case_type is required for this campaign" }
  ]
}

Rate Limits

EndpointDefault limitBurst
POST /api/v1/ingest100 RPS per supplier200 RPS for 10 seconds
POST /api/v1/ping500 RPS per supplier1,000 RPS for 10 seconds
GET /api/v1/leads/lookup10 RPS per supplier20 RPS for 5 seconds

When you hit the limit, Lead Distro AI returns 429 with a `retry_after` header (seconds) and a `Retry-After` HTTP header per RFC 7231. Implement exponential backoff in your integration.

Exponential Backoff Recipe (Node.js)

async function postLeadWithBackoff(payload, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const res = await fetch('https://app.leaddistro.ai/api/v1/ingest', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.LEADDISTRO_API_KEY,
      },
      body: JSON.stringify(payload),
    });
    if (res.status !== 429 && res.status !== 503) return res;
    const retryAfter = Number(res.headers.get('retry-after')) || 2 ** attempt;
    await new Promise(r => setTimeout(r, retryAfter * 1000));
  }
  throw new Error('Max retries exceeded');
}

Frequently Asked Questions

What HTTP status code does Lead Distro AI return when a lead is accepted?
201 Created when the lead is accepted and distributed to a buyer. 200 OK with `status: UNMATCHED` when validation passes but no buyer is available (all caps hit, no matching filters). Both are 'success' from an API standpoint — your integration should handle both as successful posts.
What's the default rate limit on the ingest endpoint?
100 requests per second per supplier API key, with burst allowance up to 200 RPS for 10 seconds. The ping endpoint has a higher limit (500 RPS, burst 1,000) since pings are lighter than full posts. High-volume agencies can request elevated limits — contact support with your expected RPS.
How do I handle a 429 Too Many Requests response?
Wait the number of seconds in the `retry_after` field (or the `Retry-After` HTTP header), then retry with exponential backoff if subsequent requests also 429. Recommended: max 5 retry attempts with backoff of `2^attempt` seconds. After max retries, queue the lead for delayed retry rather than dropping it.
What's the difference between 400 and 422?
400 Bad Request = validation failed on a structural level (missing required field, wrong data type, malformed JSON). 422 Unprocessable Entity = data was valid but business logic rejected it (failed inbound filters, on a suppression list, campaign-level duplicate detection). 400 = fix the integration; 422 = the lead doesn't match the campaign's criteria.
Does Lead Distro AI return a Retry-After header on 429?
Yes — both as a custom JSON field (`retry_after` in seconds) and as the standard `Retry-After` HTTP header. Use whichever your HTTP client surfaces more easily. The values are equivalent.
Should I retry on 500 errors?
Yes — 500 indicates a transient Lead Distro AI server issue. Retry with exponential backoff (same recipe as 429). 5xx errors typically resolve within 1-2 retries. If a single lead keeps 500-ing across 5 attempts, log it and queue for delayed retry — Lead Distro AI's error tracking will surface the issue on our side.

If you have any questions, send us an email at support@leaddistro.ai