
# Error Handling

This guide explains how integrators should read and react to errors returned by the TTDbooking OpenAPI.

## HTTP Status Code vs Business Error Code

Errors are reported on **two separate layers**:

1. **HTTP Status Code** — the transport-level result of the request (200, 400, 401, etc.)
2. **Business Error Code** — an application-level code carried in the response body

**Important**: Treat the body's `code` field as authoritative. Reading the HTTP status alone is not enough.

## HTTP Status Code Specification

| HTTP Status | Meaning               | Description                         |
| ----------- | --------------------- | ----------------------------------- |
| **200**     | Success               | Request processed successfully      |
| **400**     | Bad Request           | Request parameter validation failed |
| **401**     | Unauthorized          | Invalid or expired token            |
| **403**     | Forbidden             | No access to resource               |
| **404**     | Not Found             | Requested resource not found        |
| **429**     | Too Many Requests     | Exceeded request frequency limit    |
| **500**     | Internal Server Error | Internal server error               |
| **504**     | Gateway Timeout       | Request processing timeout          |

## Business Error Code Specification

Business error codes are structured as: `[x][xx][xx][xxxx]`

| Error Code    | HTTP Status | Meaning               | Description                                       |
| ------------- | ----------- | --------------------- | ------------------------------------------------- |
| **0**         | 200         | Success               | Request successful                                |
| **100000400** | 400         | Parameter Error       | Request parameter validation failed               |
| **100000401** | 401         | Authentication Failed | Invalid or expired token                          |
| **100000403** | 403         | Permission Denied     | No access to resource                             |
| **100000404** | 404         | Not Found             | Requested resource not found                      |
| **100000429** | 429         | Rate Limited          | Exceeded request frequency limit                  |
| **100000500** | 500         | System Error          | Internal server error                             |
| **100000504** | 504         | Timeout               | Request processing timeout                        |
| **100001003** | 500         | Duplicate Error       | Duplicate resource or operation                   |
| **100001004** | 500         | Dependency Error      | External dependency failure                       |
| **100001005** | 400         | Page Size Exceeded    | Page size exceeds maximum limit                   |
| **100001006** | 400         | Not Implemented       | Feature not implemented                           |
| **100001007** | 400         | Expired               | Resource or token expired                         |
| **100001008** | 400         | Not Matched           | Data does not match expected format               |
| **100001111** | 200         | ARI Changed           | Availability/rate information changed             |
| **100001112** | 200         | Credit Limit          | Reserved — not currently emitted (see note below) |

> **`100001112` (Credit Limit) is reserved and not currently emitted.** No code
> path returns it today, so do not branch on it. A booking that would exceed a
> credit limit is currently refused as a `100000400` parameter error.

## Error Response Format

Every error is returned in the same envelope:

```json
{
  "code": 100000400,
  "msg": "param error"
}
```

## Success Response Format

A successful call adds a `data` payload to that same envelope:

```json
{
  "code": 0,
  "msg": "Success",
  "data": {
    // your response data
  }
}
```

## Error Handling Best Practices

1. Branch your logic on `body.code`; reserve HTTP status codes for transport-level failures.
2. Expect application-level failures to arrive as HTTP 200 carrying a non-zero `code`.
3. Failures at the transport layer are signalled with the matching 4xx or 5xx HTTP status.
4. Drive retry decisions from the business error code rather than from the HTTP status alone.

## Handling Non-Final Booking Status (Book API)

A common integration question: if a booking comes back with `status` of `1` (Confirming) or `0` (Unknown), should the request be rejected?

Short answer: **do not reject immediately**.

When a Book call returns `HTTP 200`, `code=0`, and `data.hotelOrder.status` is `1` or `0`, proceed as follows.

1. Treat the response as valid and persist the identifiers:

- `customerReferenceNo`
- `supplierReferenceNo` (if present)

2. Resolve the outcome by calling `QueryOrders` — use `customerReferenceNo` where possible.

3. Interpret the status values with this rule:

- `1 (Confirming)`: still processing; not a final state.
- `0 (Unknown)`: indeterminate; must be verified.
- `2 (Confirmed)`: success.
- `3 (Cancelled)`, `4 (Failed)`, `5 (CancelFailed)`: final, unsuccessful.

4. Poll for up to roughly 10 minutes — for example immediately, then at 30s, 1m, 2m, and backing off from there.

5. Never re-submit a second booking for the same business intent while verification is still running.

6. If the status has not reached a final value once the polling window closes, leave the order pending and reach out to support with the stored references.

## Support

For unresolved orders or questions about a specific error code, contact **integrations@ttdbooking.com**.

Full API reference: **developer.ttdbooking.com/hotel-api/docs**

Environments:

- Production: `api.ttdbooking.com`
- Test: `api-test.ttdbooking.com`
