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

# Errors

> Possible errors and their meaning

## Error Response Format

The Taxwire API returns errors in a standardized format, inspired by the [JSON:API](https://jsonapi.org/format/#errors) spec:

```json theme={null}
{
  "errors": [
    {
      "status": "422",
      "code": "validation_required_field",
      "title": "Missing quantity",
      "detail": "Please provide a value for the required quantity field",
      "source": {
        "pointer": "/data/attributes/line_items/0/quantity"
      }
    }
  ]
}
```

Each error object contains:

| Field            | Required | Description                                                                             |
| ---------------- | -------- | --------------------------------------------------------------------------------------- |
| `status`         | Yes      | HTTP status code as a string                                                            |
| `code`           | Yes      | Application-specific error code                                                         |
| `title`          | Yes      | A short, human-readable summary of the problem                                          |
| `detail`         | Yes      | A human-readable explanation of the error                                               |
| `source.pointer` | No       | A pointer to the associated entity in the request document (only for validation errors) |

## Error Codes

The Taxwire API uses the following standardized error codes:

| Category                  | Error Code                   | Description                            |
| ------------------------- | ---------------------------- | -------------------------------------- |
| **System Errors**         | `system_internal_error`      | An unexpected server error occurred    |
|                           | `system_service_unavailable` | The service is temporarily unavailable |
| **Validation Errors**     | `validation_error`           | General validation error               |
|                           | `validation_required_field`  | A required field is missing            |
|                           | `validation_invalid_format`  | A field has an invalid format          |
| **Authentication Errors** | `auth_error`                 | General authentication error           |
|                           | `auth_api_key_not_found`     | The provided API key was not found     |
|                           | `auth_api_key_expired`       | The provided API key has expired       |
| **Other Errors**          | `rate_limit_error`           | Rate limit exceeded                    |
|                           | `conflict`                   | Resource conflict                      |

## HTTP Status Codes

### 400 Bad Request

The request is invalid. The error response will include specific validation errors.

**Common error codes**: `validation_error`

**Action**: Check your request parameters and ensure they match the API specifications.

### 401 Unauthorized

The request is unauthorized. This can happen when the API key provided is
invalid or expired.

**Common error codes**: `auth_error`, `auth_api_key_not_found`, `auth_api_key_expired`

**Action**: Verify your API key is valid and active.

### 403 Forbidden

The request is forbidden. This can happen for a number of reasons:

* The API key header is missing
* The API key does not have access to the resource

**Common error codes**: `auth_error`

**Action**: Ensure you're using the correct API key with appropriate permissions.

### 404 Not Found

The requested resource was not found. This can happen for a number of reasons:

* The resource does not exist
* The resource is not accessible by the API key

**Action**: Check that the resource identifier is correct.

### 409 Conflict

The request could not be processed due to a conflict with the current state of
the resource. This could happen if
you have sent the same transaction more than once.

**Common error codes**: `conflict`

**Action**: Resolve the conflict and try again.

### 422 Unprocessable Entity

The request contains valid data but the server cannot process it. This typically
happens when:

* The request is missing a required parameter
* Some data in the request is invalid

**Common error codes**: `validation_error`, `validation_required_field`,
`validation_invalid_format`

**Action**: Check the error details for specific information about what needs
be corrected.

### 429 Too Many Requests

The request was rate limited. This means you have made too many requests in a
short period of time.

**Common error codes**: `rate_limit_error`

**Action**: The response will include a `Retry-After` header with the number of
seconds to wait before making the next
request. Implement exponential backoff in your client.

For example, a rate-limited response would include this header:

```
Retry-After: 30
```

This indicates you should wait at least 30 seconds before making another request.
Your client should respect this
header and implement proper backoff strategies.

### 500 Internal Server Error

The server encountered an error while processing the request.

**Common error codes**: `system_internal_error`

**Action**: This is likely a bug and should be reported to support if it persists.

## Error Examples

### Internal Server Error

```json theme={null}
{
    "errors": [
        {
            "status": "500",
            "code": "system_internal_error",
            "title": "Internal Error",
            "detail": "An unexpected error occurred. Our team has been notified."
        }
    ]
}
```

### Rate Limit Error

```json theme={null}
{
    "errors": [
        {
            "status": "429",
            "code": "rate_limit_error",
            "title": "Too Many Requests",
            "detail": "Rate limit exceeded"
        }
    ]
}
```

### Validation Errors

```json theme={null}
{
    "errors": [
        {
            "status": "422",
            "code": "validation_required_field",
            "title": "Missing quantity",
            "detail": "Please provide a value for the required quantity field",
            "source": {
                "pointer": "/data/attributes/line_items/0/quantity"
            }
        },
        {
            "status": "422",
            "code": "validation_invalid_format",
            "title": "Invalid quantity format",
            "detail": "Input should be a valid string",
            "source": {
                "pointer": "/data/attributes/line_items/1/quantity"
            }
        }
    ]
}
```

### API Key Error

```json theme={null}
{
    "errors": [
        {
            "status": "401",
            "code": "auth_api_key_not_found",
            "title": "API key not found.",
            "detail": "The provided API key was not found. Please check your credentials."
        }
    ]
}
```

## Sample Error Handling

Here is a simple example of how to handle errors in Python:

```python Python theme={null}
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

url = "https://api.taxwire.com/calculations"
headers = {
    "X-API-Key": "REPLACE_WITH_YOUR_API_KEY",
    "Taxwire-Version": "hydrogen.2025-04-15",
    "Content-Type": "application/json",
}
payload = {
    "line_items": [
        {
            "quantity": "1",
            "unit_price": "10000",
            "customer": {
                "address": {
                    "country": "US",
                    "state": "CA",
                    "postal_code": "94104",
                    "city": "San Francisco",
                }
            }
        }
    ]
}

retry_strategy = Retry(
    total=5,  # Maximum number of retries
    backoff_factor=2,  # Exponential backoff (2s, 4s, 8s, etc.)
    status_forcelist=[429, 500, 502, 503, 504],  # Retries for rate limiting & transient errors
    allowed_methods={"POST"},
    respect_retry_after_header=True,  # Uses `Retry-After` if provided
)

# Create a session and mount the retry adapter
session = requests.Session()
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)

# Make the request using the session
response = session.post(url, json=payload, headers=headers)
response.json()
```
