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

# Errors

> The error envelope, what each type means, and the typed errors every SDK raises.

Errors are Stripe-shaped: a machine-readable `code`, a human-readable `message`, and a `request_id` to quote when asking for help.

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_document_class",
    "message": "Invalid document_class 'bank_statment'. Did you mean 'bank_statement'?",
    "param": "document_class",
    "doc_url": "https://docs.moneyline.co/errors#invalid-document-class",
    "request_id": "req_abc123"
  }
}
```

**type** `string` *required*

The broad class of failure. Branch on this when you need coarse handling.

**code** `string` *required*

The specific error. This is the stable identifier — branch on it, not on the message.

**message** `string` *required*

Human-readable, and safe to log. Not stable across releases; never parse it.

**param** `string`

Present on validation failures: the request field that was rejected.

**request\_id** `string` *required*

Quote this in support tickets. It identifies the exact request in our logs.

## Status codes

| Status | Type | Meaning |
| - | - | - |
| `400` | `invalid_request_error` | Malformed request, or a field failed validation |
| `401` | `authentication_error` | Missing, malformed, or revoked API key |
| `403` | `permission_error` | The key is valid but not allowed to do this |
| `404` | `not_found_error` | No such resource, or it belongs to another tenant |
| `409` | `conflict_error` | The resource changed underneath you |
| `422` | `invalid_request_error` | Well-formed but semantically rejected |
| `429` | `rate_limit_error` | Too many requests — see [rate limits](https://docs.moneyline.co/guides/rate-limits.md) |
| `5xx` | `api_error` | Something broke on our side. Safe to retry with backoff |

> [!NOTE]
>
> A `404` is returned rather than a `403` when a resource exists but belongs to a
> different organization. This is deliberate: it avoids confirming that an ID is
> real to a caller who cannot see it.

## Typed errors in the SDKs

Each SDK maps status codes onto typed errors, so you branch on a class rather than an integer.

```ts TypeScript icon="https://mintcdn.com/paragon-f28ba471/UuDHN4B1J-v_DThS/images/lang/typescript.svg?fit=max&auto=format&n=UuDHN4B1J-v_DThS&q=85&s=cba1e12257cdbf42b6c7a23031def04f" theme={null}
import { NotFoundError, RateLimitError, ValidationError } from '@moneyline/sdk';

try {
  await client.submissions.retrieve('does-not-exist');
} catch (err) {
  if (err instanceof NotFoundError) console.error('no such submission');
  else if (err instanceof ValidationError) console.error(err.message);
  else if (err instanceof RateLimitError) console.error('slow down');
  else throw err;
}
```

```python Python icon="https://mintcdn.com/paragon-f28ba471/UuDHN4B1J-v_DThS/images/lang/python.svg?fit=max&auto=format&n=UuDHN4B1J-v_DThS&q=85&s=a9a026d5d8b16735c0cea1b7dd0ac6e5" theme={null}
from moneyline.errors import NotFoundError, RateLimitError, ValidationError

try:
    client.submissions.retrieve("does-not-exist")
except NotFoundError:
    print("no such submission")
except ValidationError as err:
    print(err)
except RateLimitError:
    print("slow down")
```

```go Go icon="https://mintcdn.com/paragon-f28ba471/UuDHN4B1J-v_DThS/images/lang/go.svg?fit=max&auto=format&n=UuDHN4B1J-v_DThS&q=85&s=338b141516fd81c7c6c2302fdf1e318b" theme={null}
_, err = client.Submissions.Get(ctx, "does-not-exist")
var apiErr *moneyline.Error
if errors.As(err, &apiErr) {
	switch {
	case apiErr.IsNotFound():
		log.Println("no such submission")
	case apiErr.IsRateLimit():
		log.Println("slow down")
	case apiErr.IsValidation():
		log.Println(apiErr.Message)
	}
}
```

## Retrying

The TypeScript, Python, and Go clients retry up to three times by default, with exponential backoff, on `429` and `5xx`. They do **not** retry `4xx` errors other than `429` — those will fail again.

> [!TIP]
>
> Give every `POST` an [idempotency key](https://docs.moneyline.co/guides/idempotency.md). Then a retry after a
> timeout is free: you get the original result back instead of a duplicate
> submission.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.