> For the complete documentation index, see [llms.txt](https://partner-docs.covergenius.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://partner-docs.covergenius.com/offers/api/responses/error-versioning.md).

# Error Versioning

Opting into the versioned error response shape

## Error Versioning

Error responses from the Offers API can be returned in a consistent, versioned shape by sending the `X-API-Error-Version` header. This is opt-in: the header changes the shape of error response bodies only and has no effect on successful responses or on any business logic.

Without the header, the structure of an error body varies between endpoints and between failure modes, which makes error handling difficult to implement generically. Sending `X-API-Error-Version: v2` guarantees a single shape with a fixed set of top-level fields on every error response, so a single error handler can parse all of them.

We recommend all new integrations send `X-API-Error-Version: v2`.

#### Supported endpoints

| Endpoint          | Method and path                                          |
| ----------------- | -------------------------------------------------------- |
| **Create Offer**  | `POST /partners/{partner_id}/offers/`                    |
| **Confirm Offer** | `POST /partners/{partner_id}/offers/{offer_id}/confirm/` |
| **Opt-out Offer** | `POST /partners/{partner_id}/offers/{offer_id}/opt_out/` |

On these endpoints the header applies to **every** error response, that is, every response with a status code of 400 or above.

#### The `v2` error shape

Every `v2` error response body contains the following top-level fields.

| Field      | Type   | Description                                                                                                       |
| ---------- | ------ | ----------------------------------------------------------------------------------------------------------------- |
| `type`     | string | Broad error category: `validation_error`, `invalid_request_error`, `auth_error` or `api_error`.                   |
| `message`  | string | Human-readable summary of the failure. Intended for logs and diagnostics, not for display to customers.           |
| `code`     | string | Machine-readable code for the failure as a whole. See Error codes.                                                |
| `error_id` | string | Identifier for this failure, for use when raising a support request.                                              |
| `errors`   | array  | Per-item detail of what failed. An empty array when the failure is not attributable to specific items. See below. |
| `metadata` | object | Supplementary context. An empty object when there is none.                                                        |

**The `errors` array**

Each entry in `errors` is an object with these four fields:

| Field               | Type           | Description                                                                                                                                |
| ------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `product_config_id` | string \| null | The product configuration the failed item belongs to. `null` when the failure is not specific to one product.                              |
| `quote_id`          | string \| null | The quote the failed item relates to. `null` when no quote had been created at the point of failure, or when the failure is request-level. |
| `code`              | string         | Machine-readable code for this specific item. See Error codes.                                                                             |
| `details`           | array          | Array of strings describing this item's failure.                                                                                           |

#### Examples

Create Offer, where every quote failed to price (`422 Unprocessable Entity`):

```json
{
  "type": "validation_error",
  "message": "Offer could not be created due to quote generation errors",
  "code": "offer_quote_generation_failed",
  "error_id": "b9c1f0d2-3a4e-4c6b-9f21-7d8e5a0b1c34",
  "errors": [
    {
      "product_config_id": "8f2b41c9-6d7e-4a15-b3c8-1e9f0a2d5b76",
      "quote_id": "3c7d9e21-5b48-4f0a-8d16-2a9c4e7b0f53",
      "code": "offer_quote_pricing_error",
      "details": ["No rate available for the supplied parameters"]
    },
    {
      "product_config_id": "a41e9c72-8b05-4d63-9f18-6c2a7e0d4b95",
      "quote_id": null,
      "code": "quote_creation_failure",
      "details": ["Upstream pricing service unavailable"]
    }
  ],
  "metadata": {
    "selected_offer_id": "5d8a2f61-9c04-4e73-b1a8-3f6e7c0d9b42"
  }
}
```

Confirm Offer, where none of the requested quotes could be booked (`422 Unprocessable Entity`). Note that `error_id` is the Offer ID:

```json
{
  "type": "validation_error",
  "message": "None of the requested quotes were successful.",
  "code": "booking_quotes_unsuccessful",
  "error_id": "5d8a2f61-9c04-4e73-b1a8-3f6e7c0d9b42",
  "errors": [
    {
      "product_config_id": "8f2b41c9-6d7e-4a15-b3c8-1e9f0a2d5b76",
      "quote_id": "3c7d9e21-5b48-4f0a-8d16-2a9c4e7b0f53",
      "code": "booking_quote_failed",
      "details": ["Policyholder country is not eligible for this product"]
    }
  ],
  "metadata": {}
}
```

A request-level validation failure, where the failure cannot be attributed to a product or quote. Note that `message` here is generic and that the field-keyed detail is preserved under `metadata.field_errors`:

```json
{
  "type": "validation_error",
  "message": "An API error occurred.",
  "code": "offer_validation_request_invalid",
  "error_id": "7e4c1a80-2f39-4b6d-95e1-8a0c3d7b6f14",
  "errors": [
    {
      "product_config_id": null,
      "quote_id": null,
      "code": "offer_validation_request_invalid",
      "details": ["Quote does not exist"]
    }
  ],
  "metadata": {
    "field_errors": {
      "quotes": ["Quote does not exist"]
    }
  }
}
```

#### Error codes

Codes appear in the top-level `code` and in each `errors[].code`. Treat the list as open-ended: new codes may be added, so always handle an unrecognised code by falling back to the HTTP status.

| Code                                       | Typical status | Meaning                                                                           |
| ------------------------------------------ | -------------- | --------------------------------------------------------------------------------- |
| `offer_partner_not_found`                  | 404            | The partner in the request path does not exist.                                   |
| `offer_not_found_no_offers`                | 404            | No Offers are configured for this partner.                                        |
| `offer_no_products`                        | 404            | The selected Offer has no products available.                                     |
| `offer_not_found_no_match_context`         | 422            | No Offer matches the supplied request context.                                    |
| `offer_quote_generation_failed`            | 422            | Package level: no quote in the Offer could be generated.                          |
| `offer_quote_pricing_error`                | 422            | Item level: a quote was created but could not be priced.                          |
| `quote_creation_failure`                   | 422            | Item level: the quote could not be created at all.                                |
| `offer_quote_multiple_per_product`         | 422            | More than one quote was produced for a product that permits one.                  |
| `offer_validation_request_invalid`         | 422            | The request body failed validation.                                               |
| `offer_validation_schema_required`         | 422            | No schema was supplied and the partner has no default schema.                     |
| `offer_validation_schema_invalid`          | 422            | The supplied schema identifier is not valid for this partner.                     |
| `offer_schema_validation_failed`           | 422            | The request did not validate against the partner's Offer Schema.                  |
| `offer_enrichment_failed`                  | 422            | Enrichment of the request data failed.                                            |
| `expression_evaluation_failed`             | 422            | An Offer configuration expression could not be evaluated.                         |
| `too_many_instances`                       | 422            | The resolved quantity exceeds the permitted number of instances.                  |
| `quantity_expression_invalid_output`       | 422            | A quantity expression returned an unusable value.                                 |
| `too_many_variants`                        | 422            | The resolved variants exceed the permitted number.                                |
| `variant_expression_invalid_output`        | 422            | A variant expression returned an unusable value.                                  |
| `variant_config_expression_failed`         | 422            | A variant configuration expression could not be evaluated.                        |
| `variant_config_expression_invalid_output` | 422            | A variant configuration expression returned an unusable value.                    |
| `booking_quotes_unsuccessful`              | 422            | Package level: none of the requested quotes could be booked.                      |
| `booking_quote_failed`                     | 422            | Item level: the per-quote reason inside a `booking_quotes_unsuccessful` response. |
| `booking_quote_not_found`                  | 404            | A quote ID in the confirm request does not belong to this Offer.                  |
| `offer_request_failed`                     | any            | Generic fallback where no more specific code applies.                             |
| `offer_unexpected_error`                   | 500            | Unexpected server-side failure.                                                   |

#### Limitations

Two cases are not covered by the versioned shape and should be handled defensively:

1. **Unhandled server errors.** An unexpected failure that produces no structured API response rendered as a generic `500`  is returned as-is and will not carry the `v2` fields.
2. **Partial successes.** A response that carries a success payload alongside a non-2xx status is left unchanged, because its body is not an error body. Continue to inspect the `errors` field of the payload in these cases, as described in Error Types.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://partner-docs.covergenius.com/offers/api/responses/error-versioning.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
