# Errors

Errors use HTTP status codes and a body that tells you what to do next. This is a complete error
response, exactly as the API returns it:

```json title="503 Service Unavailable"
{
  "error": {
    "type": "upstream_error",
    "code": "blocked",
    "message": "The data couldn't be fetched right now. Refunded automatically; retry after Retry-After.",
    "retryable": true,
    "doc_url": "https://happyfetch.net/docs/errors#blocked",
    "retry_after_seconds": 60
  },
  "meta": {
    "request_id": "9a80ddb0-0aed-41bc-9e48-a035c9388751",
    "credits_charged": 0,
    "credits_remaining": 198
  }
}
```

- `code` is stable; build on it. `message` is for humans and may change.
- `retryable` says whether the same request can succeed later. Honor `retry_after_seconds` (also the
  `Retry-After` header).
- `details` lists each problem field when the request body was invalid.
- `meta.credits_charged` is what the call cost, usually `0`.

## All codes

| Code | HTTP | Retryable | Billing |
|---|---|---|---|
| [`invalid_request`](#invalid_request) | 400 | no | Never charged |
| [`invalid_person_reference`](#invalid_person_reference) | 400 | no | Never charged |
| [`invalid_domain`](#invalid_domain) | 400 | no | Never charged |
| [`invalid_company_reference`](#invalid_company_reference) | 400 | no | Never charged |
| [`unauthorized`](#unauthorized) | 401 | no | Never charged |
| [`insufficient_credits`](#insufficient_credits) | 402 | no | Never charged |
| [`not_found`](#not_found) | 404 | no | Charged 1 credit by LinkedIn company URL, 4 by website domain; free from our cache |
| [`unresolvable_id`](#unresolvable_id) | 404 | no | Charged 1 credit by LinkedIn company URL, 4 by website domain; free from our cache |
| [`route_not_found`](#route_not_found) | 404 | no | Never charged |
| [`idempotency_key_in_use`](#idempotency_key_in_use) | 409 | yes | Never charged |
| [`idempotency_key_reused`](#idempotency_key_reused) | 422 | no | Never charged |
| [`rate_limited`](#rate_limited) | 429 | yes | Never charged |
| [`concurrency_limited`](#concurrency_limited) | 429 | yes | Never charged |
| [`upstream_error`](#upstream_error) | 502 | yes | Refunded automatically |
| [`parse_error`](#parse_error) | 502 | no | Refunded automatically |
| [`blocked`](#blocked) | 503 | yes | Refunded automatically |
| [`source_rate_limited`](#source_rate_limited) | 503 | yes | Refunded automatically |
| [`no_capacity`](#no_capacity) | 503 | yes | Never charged |
| [`timeout`](#timeout) | 504 | yes | Refunded automatically |
| [`internal_error`](#internal_error) | 500 | yes | Refunded automatically |

## Code reference

### `invalid_request`

HTTP 400, type `invalid_request_error`. Not retryable. Never charged.

The body isn't valid JSON or doesn't match the schema. `details` names each field.

### `invalid_person_reference`

HTTP 400, type `invalid_request_error`. Not retryable. Never charged.

`url` isn't a LinkedIn profile: send its URL (linkedin.com/in/<name>) or the name. Member ids (ACoAA…) aren't accepted.

### `invalid_domain`

HTTP 400, type `invalid_request_error`. Not retryable. Never charged.

`domain` isn't a website on a public domain. Company page URLs and slugs go to POST /v1/company.

### `invalid_company_reference`

HTTP 400, type `invalid_request_error`. Not retryable. Never charged.

`url` isn't a LinkedIn company reference (for example a /in/ profile, a school page, or free text).

### `unauthorized`

HTTP 401, type `authentication_error`. Not retryable. Never charged.

The API key is missing, malformed or revoked. Send it as `Authorization: Bearer <key>` or `X-Api-Key`.

### `insufficient_credits`

HTTP 402, type `billing_error`. Not retryable. Never charged.

The workspace balance doesn't cover this call. Top up in the console; nothing was charged.

### `not_found`

HTTP 404, type `not_found_error`. Not retryable. Charged 1 credit by LinkedIn company URL, 4 by website domain; free from our cache.

Nothing exists for this lookup: no company behind the reference or the domain, or no profile at that name. A definitive answer, charged at the lookup's not-found price (see GET /v1/pricing); free when it comes from the cache. `error.reason` says which answer it is where there's more than one.

### `unresolvable_id`

HTTP 404, type `not_found_error`. Not retryable. Charged 1 credit by LinkedIn company URL, 4 by website domain; free from our cache.

No public company page could be found for this numeric id. Charged at the not-found price (see GET /v1/pricing); free when the answer comes from the cache.

### `route_not_found`

HTTP 404, type `invalid_request_error`. Not retryable. Never charged.

There is no endpoint at this method and path.

### `idempotency_key_in_use`

HTTP 409, type `idempotency_error`. Retryable. Never charged.

A request with this Idempotency-Key is still running. Retry shortly to get its stored response.

### `idempotency_key_reused`

HTTP 422, type `idempotency_error`. Not retryable. Never charged.

This Idempotency-Key was already used with a different endpoint or body.

### `rate_limited`

HTTP 429, type `rate_limit_error`. Retryable. Never charged.

Too many requests for this API key. Wait for Retry-After; RateLimit-* headers show the budget.

### `concurrency_limited`

HTTP 429, type `rate_limit_error`. Retryable. Never charged.

Too many of this workspace's lookups are in flight. Retry after Retry-After.

### `upstream_error`

HTTP 502, type `upstream_error`. Retryable. Refunded automatically.

The data couldn't be fetched because of an unexpected error. Refunded automatically.

### `parse_error`

HTTP 502, type `upstream_error`. Not retryable. Refunded automatically.

The data was fetched but couldn't be read. We're alerted; refunded automatically.

### `blocked`

HTTP 503, type `upstream_error`. Retryable. Refunded automatically.

The data couldn't be fetched right now. Refunded automatically; retry after Retry-After.

### `source_rate_limited`

HTTP 503, type `upstream_error`. Retryable. Refunded automatically.

Fetching is being slowed down right now. Refunded automatically; retry after Retry-After.

### `no_capacity`

HTTP 503, type `upstream_error`. Retryable. Never charged.

We can't take new lookups right now. Rejected before charging.

### `timeout`

HTTP 504, type `upstream_error`. Retryable. Refunded automatically.

No definitive answer arrived in time. Refunded automatically.

### `internal_error`

HTTP 500, type `api_error`. Retryable. Refunded automatically.

Something failed on our side. Any charge was refunded; the request id helps us find it.
