> ## Documentation Index
> Fetch the complete documentation index at: https://docs.makelocalads.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and retries

> Understand and handle LocalAds API errors.

LocalAds returns errors as
[RFC 9457 problem details](https://www.rfc-editor.org/rfc/rfc9457) with the
`application/problem+json` content type.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "https://docs.makelocalads.com/errors/product-not-found",
  "title": "Product not found",
  "status": 404,
  "detail": "The product does not exist.",
  "code": "product_not_found",
  "request_id": "63f24a02-d278-4e7a-9da7-73c9ae649e32"
}
```

Use `code` for program logic and `request_id` when contacting support. Do not
write integrations that depend on the human-readable `detail`.

## Status codes

| Status | Meaning | What to do |
| - | - | - |
| `400` | The request is malformed or contains unsupported fields | Correct the request before retrying |
| `401` | The API key is missing or invalid | Check the bearer header or replace the key |
| `403` | The key lacks the required permission (`insufficient_permission`), the organization's plan does not include API access (`plan_upgrade_required`), or the organization is suspended (`org_suspended`) | Use a key with the required permission, upgrade to Pro or Enterprise, or contact support |
| `404` | The resource does not exist in the key's organization, or no endpoint exists at the path (`route_not_found`) | Check the resource ID and path |
| `422` | A product rule, plan limit or credit limit blocked the request (see the codes below) | Resolve the condition before retrying |
| `429` | The API key exceeded its rate limit | Wait for `Retry-After`, then retry |
| `500` | LocalAds could not complete the request | Retry with backoff and contact support if it persists |

## Common codes

| Status | Code | Meaning |
| - | - | - |
| `400` | `invalid_request` | A field is missing, unknown, or outside the values the app offers. `detail` names the field |
| `404` | `product_not_found`, `campaign_not_found`, `blueprint_not_found`, `audience_not_found`, `moodboard_not_found`, `ad_group_not_found`, `idea_not_found`, `concept_not_found`, `voice_not_found`, `video_not_found` | The resource does not exist in the key's organization |
| `409` | `idempotency_conflict` | The `Idempotency-Key` was reused with a different body |
| `409` | `idempotency_in_progress` | The first request with this `Idempotency-Key` is still running. Retry shortly |
| `422` | `insufficient_credits` | Not enough credits. Nothing was charged |
| `422` | `credit_limit_exceeded` | The request would cost more than its `max_credits`. Nothing was charged |
| `422` | `key_budget_exceeded` | The API key has used its monthly credit budget |
| `422` | `plan_required` | The organization's plan does not include this feature, such as Video Ads |
| `422` | `moodboard_not_ready` | The moodboard is not finished, or was made for an unrelated product |
| `422` | `request_rejected` | A product rule the app also enforces blocked the request. `detail` says which |

A `400 invalid_request` on a campaign or UGC video usually means `audience_id`
is missing. It is required on those requests: send a saved audience, or `null`
for a deliberately broad one.

## Retry safely

Retry `429` and transient `500` responses with exponential backoff. Do not
automatically retry `400`, `401`, `403`, `404`, or `422` responses without
changing the request or configuration.
