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

# AgriBackup API Error Codes and HTTP Status Reference

> Decode every HTTP status code and error object the AgriBackup API returns, with handling guidance for each failure category.

Every error the AgriBackup API returns follows a single, predictable schema — no matter which endpoint triggered it. Standardising on one error envelope means you can write a single error-handling layer in your client and branch on the machine-readable `code` field for any custom logic you need.

## Error Response Schema

All error responses return a JSON object with three fields:

```json theme={null}
{
  "code": "VALIDATION_FAILED",
  "message": "Invalid polygon coordinates — the ring is not closed.",
  "details": [
    {
      "code": "INVALID_COORDINATE_CLOSURE",
      "field": "features[0].geometry.coordinates",
      "issue": "The first and last coordinate of the ring must be identical to form a closed polygon."
    }
  ]
}
```

| Field     | Type     | Description                                                                       |
| --------- | -------- | --------------------------------------------------------------------------------- |
| `code`    | `string` | Machine-readable error code for programmatic branching (e.g. `VALIDATION_FAILED`) |
| `message` | `string` | Human-readable summary of what went wrong                                         |
| `details` | `array`  | Zero or more `ApiErrorDetail` objects pinpointing the specific field and issue    |

Each object in `details` contains:

| Sub-field | Type     | Description                                                                         |
| --------- | -------- | ----------------------------------------------------------------------------------- |
| `code`    | `string` | Granular error code scoped to the failing field (e.g. `INVALID_COORDINATE_CLOSURE`) |
| `field`   | `string` | JSON path to the field that caused the error (e.g. `features[0].properties.area`)   |
| `issue`   | `string` | Plain-language description of the problem with that field                           |

<Note>
  The `details` array is empty for errors that are not caused by field-level validation — for example, `401 Unauthorized` or `500 Internal Server Error`. Always check for an empty array before iterating.
</Note>

## HTTP Status Code Reference

| Status | Name                  | When you'll see it                                                                                                                                |
| ------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | OK                    | The request succeeded and the response body contains the requested resource                                                                       |
| `202`  | Accepted              | An asynchronous operation (satellite screening, DLT anchoring) has been queued — listen for the corresponding webhook event                       |
| `400`  | Bad Request           | Request body or query parameters failed structural or schema validation                                                                           |
| `401`  | Unauthorized          | The `X-API-Key` header is missing, malformed, or the key has been revoked                                                                         |
| `403`  | Forbidden             | The key is valid but does not have permission to perform this action on this resource                                                             |
| `404`  | Not Found             | The requested resource (polygon, batch, declaration, etc.) does not exist for your organisation                                                   |
| `409`  | Conflict              | A duplicate `Idempotency-Key` was submitted for a different payload, or a Hedera EVM state violation occurred (e.g. a shipment is already linked) |
| `422`  | Unprocessable Entity  | The request was well-formed but was rejected by business logic — typically a cryptographic or EUDR compliance rule violation                      |
| `429`  | Too Many Requests     | You have exceeded the 100 requests/second rate limit for your key                                                                                 |
| `500`  | Internal Server Error | An unexpected error occurred on AgriBackup's infrastructure — retry with backoff and contact support if it persists                               |

## Handling Each Category

<Accordion title="200 OK — Success">
  A `200` response means the operation completed synchronously and the result is in the body. No action required beyond consuming the response. Use the data immediately or persist it to your data store.
</Accordion>

<Accordion title="202 Accepted — Async Operations">
  A `202` means your request was accepted and queued for asynchronous processing. Satellite deforestation screening and Hedera DLT anchoring cannot return results inline — they take seconds to minutes depending on network conditions.

  **What to do:** Register a webhook endpoint via `POST /webhooks` before you start submitting polygons or batches. The API will `POST` the result to your URL when the job completes. You can also poll the job status endpoint using the `jobId` returned in the `202` response body.

  Do not treat a `202` as a final success — it is a receipt, not a confirmation.
</Accordion>

<Accordion title="400 Bad Request — Validation Failures">
  A `400` means the API rejected your request before any processing occurred because the payload did not conform to the expected schema.

  **What to do:** Read the `details` array — each entry identifies the exact `field` and `issue`. Fix the offending fields and resubmit. Common causes include:

  * Missing required fields
  * Incorrect GeoJSON geometry type
  * Invalid date format (use ISO 8601)
  * Missing `Idempotency-Key` header on write endpoints

  Never retry a `400` without modifying the request. It will fail identically.
</Accordion>

<Accordion title="401 Unauthorized — Authentication Failure">
  A `401` means no valid API key was found. The `X-API-Key` header is either absent, contains a typo, or the key has been revoked.

  **What to do:** Check that you are passing the header correctly:

  ```http theme={null}
  X-API-Key: sk_live_YOUR_API_KEY
  ```

  Regenerate the key from the AgriBackup dashboard if you suspect it has been compromised. Never embed keys directly in client-side code or version control.
</Accordion>

<Accordion title="403 Forbidden — Insufficient Permissions">
  A `403` means the authenticated key is valid, but your organisation does not have the required permission scope for this operation. For example, attempting to revoke another organisation's DDS or accessing a sub-organisation resource without the correct scope.

  **What to do:** Review which permissions are attached to the key in the dashboard. If you believe the restriction is incorrect, contact your account administrator or AgriBackup support.
</Accordion>

<Accordion title="404 Not Found — Resource Missing">
  A `404` means the resource identifier you provided does not exist within your organisation's scope. This can happen when the resource was never created, has been deleted, or belongs to a different organisation.

  **What to do:** Verify the ID you are passing (polygon ID, batch ID, declaration reference ID, etc.). If you expect the resource to exist, check that you are using the correct environment — a sandbox resource ID will not resolve against the production environment.
</Accordion>

<Accordion title="409 Conflict — Duplicate Idempotency Key or State Violation">
  A `409` has two distinct causes:

  1. **Duplicate Idempotency-Key:** You submitted a write request with an `Idempotency-Key` that was already used for a *different* payload within the 24-hour TTL window. Idempotency keys are safe to reuse only for identical payloads.
  2. **Hedera EVM State Violation:** A smart-contract-level rule was broken — for example, attempting to link a shipment that is already linked to another batch, or a double-spend attempt on the compliance ledger.

  **What to do:** For duplicate key conflicts, generate a new UUID as your idempotency key and resubmit. For EVM state violations, retrieve the current state of the resource first and check whether the operation you intend is valid given that state.
</Accordion>

<Accordion title="422 Unprocessable Entity — Business Logic Rejection">
  A `422` means the request was structurally valid but was rejected by a compliance or cryptographic business rule. The most common causes are:

  * A polygon's satellite screening returned a deforestation risk score above the permitted threshold
  * A DDS is being submitted for a batch that has not yet passed all verification stages
  * A cryptographic proof could not be reproduced from the submitted evidence

  **What to do:** Read the `code` and `message` fields for the specific rule that was violated. A `422` cannot be fixed by reformatting the request — it requires addressing the underlying compliance issue (for example, providing additional evidence or correcting the land tenure record).
</Accordion>

<Accordion title="429 Too Many Requests — Rate Limit Exceeded">
  You have exceeded the 100 requests/second limit for your key. See the [Rate Limits](/reference/rate-limits) page for a full explanation and backoff code samples.

  **What to do:** Wait for the number of seconds specified in the `Retry-After` response header, then retry with exponential backoff and jitter.
</Accordion>

<Accordion title="500 Internal Server Error — Server Fault">
  A `500` indicates an unexpected fault on AgriBackup's infrastructure. These are rare and are monitored by the platform team automatically.

  **What to do:** Retry the request after a short delay (start with 2 seconds, back off exponentially). If the error persists for more than 5 minutes, check the [AgriBackup status page](https://agribackup.com) and open a support ticket with the request ID from the response body if one is present.

  Do not assume data was written when a `500` is returned — use idempotency keys on all write operations so you can safely retry without risk of duplication.
</Accordion>

<Tip>
  Log the full error response body — including `code` and `details` — in your application's error tracking system. The machine-readable `code` field lets you set up targeted alerts (for example, page on-call if `HEDERA_CONSENSUS_TIMEOUT` appears) without parsing free-text messages.
</Tip>
