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

# Errors

> The format of errors, stable codes to branch on, and what each HTTP status means.

The API immediately informs you, synchronously, what is wrong: there are no validations that take hours or responses that arrive later. Each validation error has a **stable code** that you can use in your program and a sentence for humans.

## Format

Validation errors and refusals with a reason use RFC 9457 (*Problem Details*), with `Content-Type: application/problem+json`.

### Validation (`422`)

```json theme={null}
{
  "type": "https://housera.ro/problems/validation",
  "title": "Datele trimise nu sunt valide.",
  "status": 422,
  "errors": [
    { "pointer": "/title", "code": "min", "detail": "Titlul e prea scurt — minim 10 caractere." },
    { "pointer": "/floor", "code": "floor_above_total", "detail": "Etajul 5 nu poate fi mai mare decât numărul total de etaje (4)." },
    { "pointer": "/heating_types", "code": "heating_none_exclusive", "detail": "…" }
  ]
}
```

Each item in `errors[]` has:

<ResponseField name="pointer" type="string">
  The field with the issue, as JSON Pointer: `/title`, `/features/2` (the third element from `features`), `/photos/0/key`.
</ResponseField>

<ResponseField name="code" type="string">
  The error code. **It's stable**: from it, you branch in your code. The list is below.
</ResponseField>

<ResponseField name="detail" type="string">
  An explanation for humans, in the request language. The text may change at any time; do not compare it in the program.
</ResponseField>

A field can have multiple errors, each with its own element in `errors[]`.

### Refusals with a reason (`409`, `412`)

```json theme={null}
{
  "type": "https://housera.ro/problems/listing_busy",
  "title": "Anunțul e procesat chiar acum — reîncearcă în câteva momente.",
  "status": 409,
  "code": "listing_busy",
  "detail": "Anunțul e procesat chiar acum — reîncearcă în câteva momente."
}
```

Here the code is directly in `code`, at the first level.

### Other refusals

All have the same form, with `code` at the first level:

| Status | `code` | When |
| - | - | - |
| `401` | `unauthenticated` | The key is missing, incorrect, expired, or revoked, or the account is no longer active. |
| `403` | `missing_ability` | The key does not have the required permission (e.g., `media:write` for images). |
| `403` | `forbidden` | You do not have access to the resource. |
| `404` | `not_found` | The resource does not exist or is not yours (a listing from someone else responds the same as a non-existent one). |
| `409` | `listing_busy` | The listing is currently being processed by another writing. Retry in a few seconds. |
| `409` | `listing_action_refused` | The operation is refused with a reason, stated in `detail` (for example, a listing with open reports cannot be deleted). |
| `412` | `listing_changed_meanwhile` | `If-Match` no longer matches: the listing has changed in the meantime. |
| `429` | `too_many_requests` | You have exceeded the request limit. Wait as many seconds as `Retry-After` states. |

## Message language

`detail` and `title` come in Romanian or English. You choose the language with the `locale` parameter in the address (`?locale=en`). Without it, the preferred language of the account is used, then the header `Accept-Language`, then Romanian. Codes are never translated.

## Validation codes per field

When a field, taken alone, does not respect its rule, the code is the name of the rule:

| Code | What it means |
| - | - |
| `required` | The field is required and missing (or empty). |
| `required_if`, `required_unless` | The field is required for the sent property type (e.g., `floor` for an apartment). |
| `required_with`, `required_without` | The field is required alongside another (e.g., `label` in a row from `unit_types`; `url` or `key` in an image). |
| `present` | The field must exist in the body, even if empty (e.g., `photos`). |
| `string`, `integer`, `numeric`, `boolean`, `array` | The value does not have the expected type. |
| `decimal` | The number has too many decimals (areas must have at most two). |
| `min`, `max`, `between` | The value (or text length, or number of elements in the list) is out of bounds. |
| `gt`, `gte` | The value must be greater than a threshold or another field (e.g., `max_nights` compared to `min_nights`). |
| `size` | The length is not what's required. |
| `enum`, `in` | The code is not in the list of allowed values. The values are in [vocabulary](/en/vocabulary). |
| `distinct` | The list contains the same value twice. |
| `regex` | The format is not as required (e.g., `price_currency` does not have three uppercase letters). |
| `date_format` | The date or time does not have the required format (`AAAA-LL-ZZ`, `HH:MM`). |
| `url` | The address is not a valid URL or does not have the required schema (images require `https`). |
| `email` | The email address is not valid. |
| `prohibits` | The field cannot be sent together with another (e.g., `upfront_percent` with `upfront_cost`). |
| `iso_country` | `country` is not an ISO 3166-1 alpha-2 country code. |
| `meaningful_text` | The title or description has no real content (e.g., a group of repeated letters). |
| `phone_number_valid` | `contact_phone` is not a valid phone number. |
| `valid_parcel_ring` | The parcel's outline (`parcel`) does not form a valid polygon. |
| `invalid_value` | A specific field check has failed: an unknown level code in `floor`, an upload key that is not yours, an unknown photo tag, or an attempt to change `type` or `transaction` during editing. The explanation is in `detail`. |
| `invalid` | An error without its own code. The explanation is in `detail`. |

## Cross-field check codes

Some rules apply to multiple fields at once. Their code is specific to the rule, and `pointer` indicates the field to correct.

| Code | Field | What it means |
| - | - | - |
| `transaction_invalid_for_type` | `/transaction` | The transaction does not exist for the property type (e.g., hotel regime for a land) or is not currently open on the platform. |
| `floor_above_total` | `/floor` | The floor (for duplex or triplex, the last level of the dwelling) is greater than the total number of floors. |
| `upfront_above_price` | `/upfront_cost` | The requested deposit is greater than the price. |
| `below_type_minimum` | numeric field | The value is below the minimum for the property type (area, floors, rooms, year). |
| `above_type_maximum` | numeric field | The value is above the maximum for the property type. |
| `bedrooms_above_rooms` | `/bedrooms` | There are more bedrooms than rooms. |
| `built_above_land` | `/built_area_sqm` | The constructed area of the house exceeds the area of the land multiplied by the number of levels. |
| `unfurnished_with_appliances` | `/furnished` | The property is declared unfurnished, but the amenities include appliances. |
| `required` | `/partitioning` | Partitioning is mandatory for an apartment that is not a studio and has more than one room. |
| `heating_none_exclusive` | `/heating_types` | “No heating” (`none`) cannot be combined with other heating sources. |
| `delivery_in_past` | `/delivery_quarter` | The delivery term of an unfinished ansamblu is already past. |
| `complex_needs_complete_type` | `/unit_types` | An ansamblu needs at least one complete unit type (name, area, number of units, price). |
| `area_to_below_from` | `/unit_types/N/area_sqm_to` | The maximum area of a unit type is less than the minimum. |
| `floor_range_invalid` | `/unit_types/N/floors` | The floor range of a unit type does not fit within the height regulation of the ansamblu. |
| `price_currency_not_offered` | `/price_currency` | The currency is not one of the accepted ones (see `currencies` in vocabulary). |
| `price_currency_unavailable` | `/price_currency` | There is currently no exchange rate for the submitted currency, so the price cannot be converted. Retry later or submit the price in another currency. |
| `price_above_cap` | `/price` | The price, converted to euros, exceeds the platform ceiling. |

## Rejection codes

| Status | Code | What it means | What to do |
| - | - | - | - |
| `409` | `listing_busy` | Another writing is currently working on the same listing. Nothing has been written. | Retry after a second or two. |
| `409` | `listing_action_refused` | The action is not allowed for a reason explained in `detail` (for example, deleting a listing with open reports). | Read `detail`; immediate retry does not help. |
| `412` | `listing_changed_meanwhile` | `If-Match` contains an old version: the listing has changed in the meantime. | Read the listing again and resend with the new `ETag`. See [Editing](/en/concepts/editing). |

## HTTP statuses

| Status | When |
| - | - |
| `200 OK` | Successful read or write. |
| `201 Created` | New listing created (`POST /listings`, `PUT /listings/ref/{ref}` with new id). |
| `202 Accepted` | Received, processing later: an edit on a published listing (goes to moderation) or a list of images. |
| `204 No Content` | Listing deleted. |
| `304 Not Modified` | The vocabulary has not changed since `If-None-Match`. |
| `401 Unauthorized` | Missing, incorrect, expired, or revoked key. See [Authentication](/en/authentication). |
| `403 Forbidden` | The key does not have the required permission for the endpoint, or the listing cannot be modified by the account. |
| `404 Not Found` | The listing does not exist, is not yours, or the action is not possible due to its state (for example, reactivating a listing that is not paused). A listing from someone else responds the same as a non-existent one. |
| `409 Conflict` | `listing_busy` or `listing_action_refused`. |
| `412 Precondition Failed` | `listing_changed_meanwhile`. |
| `422 Unprocessable Content` | Invalid data. See `errors[]`. |
| `429 Too Many Requests` | You have exceeded the request limit. Wait as many seconds as the header `Retry-After` states. See [Limits](/en/limits). |
| `5xx` | A problem on Housera's side. Retry with increasingly larger pauses; requests with `Idempotency-Key` or on `PUT /listings/ref/{ref}` are safe to repeat. |

<Tip>
  When asking for help for an error, send us the value of the header `X-Request-Id` from the response. With it, we find the exact request. You can also see it in the [API log](/en/log).
</Tip>


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