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

# Referência da API

> Cada operação da API PMS Tatallo v1, gerada a partir do ficheiro OpenAPI.

Esta referência é gerada a partir do ficheiro OpenAPI 3.1 da API PMS Tatallo, o único contrato público da versão 1. [Descarregue o ficheiro OpenAPI](https://tatallo-docs.mintlify.site/openapi/tatallo-pms-v1.yaml), ou copie-o do fim desta página, para gerar um cliente ou importá-lo na sua ferramenta de API.

> [!NOTE]
>
> As páginas de cada operação são geradas a partir do ficheiro OpenAPI e permanecem em inglês. Encontra-as a partir da [introdução à referência da API](https://tatallo-docs.mintlify.site/api-reference/introduction.md).

| Servidor | Base URL |
| - | - |
| Produção | `https://api.tatallo.com` |
| Staging (apenas propriedades sintéticas) | `https://staging.api.tatallo.com` |

Cada operação, exceto `GET /v1/health`, precisa de uma credencial PMS, enviada como `Authorization: Bearer <key>`. As operações sobre propriedades também precisam do âmbito `properties:read`.

Cada resposta traz um cabeçalho `X-Request-Id` e cada erro tem a mesma forma: `{ "error": { "code", "message", "request_id" } }`.

> [accordion] O ficheiro OpenAPI
>
> ```yaml tatallo-pms-v1.yaml theme={"dark"}
> # GENERATED by scripts/build-openapi.ts from openapi/tatallo-pms-v1.yaml and
> # openapi/examples/*.json. Do not edit: change the source, then run `pnpm openapi:build`.
> openapi: 3.1.0
> info:
>   title: Tatallo PMS API
>   version: 1.0.0
>   summary: The server-to-server API a PMS uses to list and read the Tatallo properties its hosts have connected.
>   description: |
>     The Tatallo PMS API is a small, read-only, server-to-server API. A PMS calls it with a
>     Tatallo-issued PMS credential and sees exactly the properties its hosts have connected.
>
>     - Every response carries an `X-Request-Id` header, always a UUID. Send your own UUID in
>       `X-Request-Id` to have it echoed back.
>     - Every error has the shape `{ "error": { "code", "message", "request_id" } }`. Messages
>       are English and may change; codes never do.
>     - Each PMS credential may make 60 requests per minute (`GET /v1/health`: 60 per minute
>       per client IP). Over the limit you get `429` with `Retry-After`.
>     - Within `/v1` the contract changes only additively. A breaking change gets at least
>       6 months' notice on the changelog.
>   contact:
>     name: Tatallo developer support
>     email: hello@tatallo.com
> servers:
>   - url: https://api.tatallo.com
>     description: Production
>   - url: https://staging.api.tatallo.com
>     description: Staging (synthetic properties only)
> tags:
>   - name: System
>     description: Connectivity and the identity of your PMS credential.
>   - name: Properties
>     description: The Tatallo properties your hosts have connected to your PMS.
> security:
>   - PmsCredential: []
> paths:
>   /v1/health:
>     get:
>       operationId: getHealth
>       tags:
>         - System
>       summary: Check that Tatallo is reachable
>       description: |
>         Answers `200` whenever the Tatallo PMS API is up. Needs no key, so it tells a network
>         problem from an authentication problem. Rate-limited per client IP.
>       security: []
>       responses:
>         "200":
>           description: Tatallo is reachable.
>           headers:
>             X-Request-Id:
>               $ref: "#/components/headers/XRequestId"
>           content:
>             application/json:
>               schema:
>                 $ref: "#/components/schemas/Health"
>               examples:
>                 ok:
>                   summary: Tatallo is reachable
>                   value:
>                     status: ok
>         "429":
>           $ref: "#/components/responses/RateLimited"
>   /v1/me:
>     get:
>       operationId: getMe
>       tags:
>         - System
>       summary: See which PMS credential you are using
>       description: |
>         Names the PMS credential that made the call: its public ID, your PMS, the environment
>         it belongs to and its scopes. Any valid key may call it, whatever its scopes. It never
>         returns a secret, so logging the response is safe.
>       responses:
>         "200":
>           description: The calling PMS credential.
>           headers:
>             X-Request-Id:
>               $ref: "#/components/headers/XRequestId"
>           content:
>             application/json:
>               schema:
>                 $ref: "#/components/schemas/Me"
>               examples:
>                 staging:
>                   summary: The staging Test PMS credential
>                   value:
>                     credential_id: 5d4e040b-61c1-44a4-a4ca-9a751dc05133
>                     pms_name: Test PMS
>                     environment: staging
>                     scopes:
>                       - properties:read
>         "401":
>           $ref: "#/components/responses/Unauthorized"
>         "429":
>           $ref: "#/components/responses/RateLimited"
>   /v1/properties:
>     get:
>       operationId: listProperties
>       tags:
>         - Properties
>       summary: List the properties connected to your PMS
>       description: |
>         Lists every property your hosts have connected to your PMS, a page at a time, in a
>         stable order. Follow `page.next_cursor` until it is `null` to see them all; each
>         property appears exactly once. Needs the `properties:read` scope.
>       parameters:
>         - name: limit
>           in: query
>           required: false
>           description: How many properties per page, from 1 to 100.
>           schema:
>             type: integer
>             minimum: 1
>             maximum: 100
>             default: 25
>         - name: cursor
>           in: query
>           required: false
>           description: |
>             The `page.next_cursor` of the previous page, exactly as returned. It is opaque and
>             works only with the PMS credential and environment it was issued to. Don't store
>             it or build it by hand.
>           schema:
>             type: string
>       responses:
>         "200":
>           description: One page of properties.
>           headers:
>             X-Request-Id:
>               $ref: "#/components/headers/XRequestId"
>           content:
>             application/json:
>               schema:
>                 $ref: "#/components/schemas/PropertyList"
>               examples:
>                 allOnOnePage:
>                   summary: Every connected property on one page
>                   value:
>                     data:
>                       - id: 6cfa992d-1805-4de6-892c-23785031aba0
>                         name: Fixture Loft Kreuzberg
>                         timezone: Europe/Berlin
>                         status: active
>                         country: Germany
>                         city: Berlin
>                         max_guests: 2
>                         currency: EUR
>                         updated_at: 2026-10-01T09:00:00.000Z
>                       - id: 934f807c-39d6-45de-b107-d5c9e03cb041
>                         name: Fixture House Alfama
>                         timezone: Europe/Lisbon
>                         status: inactive
>                         country: Portugal
>                         city: Lisbon
>                         max_guests: 6
>                         currency: EUR
>                         updated_at: 2026-10-01T09:00:00.000Z
>                       - id: bef2859f-2444-47ec-b5f4-f1e6701f087f
>                         name: Fixture Apartment Trastevere
>                         timezone: Europe/Rome
>                         status: active
>                         country: Italy
>                         city: Rome
>                         max_guests: 4
>                         currency: EUR
>                         updated_at: 2026-10-01T09:00:00.000Z
>                     page:
>                       next_cursor: null
>                 firstOfSeveralPages:
>                   summary: "The first page at limit=1: follow page.next_cursor for the next"
>                   value:
>                     data:
>                       - id: 6cfa992d-1805-4de6-892c-23785031aba0
>                         name: Fixture Loft Kreuzberg
>                         timezone: Europe/Berlin
>                         status: active
>                         country: Germany
>                         city: Berlin
>                         max_guests: 2
>                         currency: EUR
>                         updated_at: 2026-10-01T09:00:00.000Z
>                     page:
>                       next_cursor: pKZAA9cXZioUAmmXQVzN4RBwg8cC3KXflLg_Ys2qB0vNw7TfJ1kq3m8cWl5yHh0eE4tR6uD1aPo
>         "400":
>           description: "`limit` is out of range (`invalid_limit`), or `cursor` is not a cursor this key was given (`invalid_cursor`)."
>           headers:
>             X-Request-Id:
>               $ref: "#/components/headers/XRequestId"
>           content:
>             application/json:
>               schema:
>                 $ref: "#/components/schemas/InvalidListQueryError"
>               examples:
>                 invalidLimit:
>                   summary: limit is not a whole number from 1 to 100
>                   value:
>                     error:
>                       code: invalid_limit
>                       message: limit must be a whole number from 1 to 100.
>                       request_id: 451fe2aa-a20b-4a92-b34f-3a27f5dd2f8b
>                 invalidCursor:
>                   summary: The cursor was edited, made by hand or issued to another key
>                   value:
>                     error:
>                       code: invalid_cursor
>                       message: The cursor is not valid. Use page.next_cursor exactly as returned, with the same key.
>                       request_id: 30c04c3a-c527-432c-8db3-f4943d4bcf57
>         "401":
>           $ref: "#/components/responses/Unauthorized"
>         "403":
>           $ref: "#/components/responses/InsufficientScope"
>         "429":
>           $ref: "#/components/responses/RateLimited"
>   /v1/properties/{propertyId}:
>     get:
>       operationId: getProperty
>       tags:
>         - Properties
>       summary: Read one property connected to your PMS
>       description: |
>         Reads one property your hosts have connected to your PMS. A property that is not
>         connected to your PMS, was removed, or never existed gets the same `404`, so the
>         answer reveals nothing about properties not connected to you. Needs the
>         `properties:read` scope.
>       parameters:
>         - name: propertyId
>           in: path
>           required: true
>           description: The property's `id`, as listed by `GET /v1/properties`.
>           schema:
>             type: string
>             format: uuid
>           example: bef2859f-2444-47ec-b5f4-f1e6701f087f
>       responses:
>         "200":
>           description: The property.
>           headers:
>             X-Request-Id:
>               $ref: "#/components/headers/XRequestId"
>           content:
>             application/json:
>               schema:
>                 $ref: "#/components/schemas/Property"
>               examples:
>                 active:
>                   summary: A connected, published property
>                   value:
>                     id: bef2859f-2444-47ec-b5f4-f1e6701f087f
>                     name: Fixture Apartment Trastevere
>                     timezone: Europe/Rome
>                     status: active
>                     country: Italy
>                     city: Rome
>                     max_guests: 4
>                     currency: EUR
>                     updated_at: 2026-10-01T09:00:00.000Z
>                 inactive:
>                   summary: A connected, suspended property
>                   value:
>                     id: 934f807c-39d6-45de-b107-d5c9e03cb041
>                     name: Fixture House Alfama
>                     timezone: Europe/Lisbon
>                     status: inactive
>                     country: Portugal
>                     city: Lisbon
>                     max_guests: 6
>                     currency: EUR
>                     updated_at: 2026-10-01T09:00:00.000Z
>         "401":
>           $ref: "#/components/responses/Unauthorized"
>         "403":
>           $ref: "#/components/responses/InsufficientScope"
>         "404":
>           description: The property is not connected to your PMS, or does not exist.
>           headers:
>             X-Request-Id:
>               $ref: "#/components/headers/XRequestId"
>           content:
>             application/json:
>               schema:
>                 $ref: "#/components/schemas/PropertyNotFoundError"
>               examples:
>                 notFound:
>                   summary: Not connected to your PMS, or does not exist
>                   value:
>                     error:
>                       code: property_not_found
>                       message: Property not found.
>                       request_id: 385c1118-7082-4e15-97a7-16703f74d58b
>         "429":
>           $ref: "#/components/responses/RateLimited"
> components:
>   securitySchemes:
>     PmsCredential:
>       type: http
>       scheme: bearer
>       description: |
>         A PMS credential issued by Tatallo: an opaque key of the form `tat_<env>_sk_…`, where
>         `<env>` is `stg` on staging and `live` on production. A key works only in its own
>         environment. Send it as `Authorization: Bearer <key>`, from your servers only.
>   headers:
>     XRequestId:
>       description: The request's ID, on every response. Your own UUID if you sent a well-formed one in `X-Request-Id`, otherwise one Tatallo generated. Quote it to support.
>       required: true
>       schema:
>         type: string
>         format: uuid
>     RetryAfter:
>       description: Seconds to wait before the next request.
>       required: true
>       schema:
>         type: integer
>         minimum: 1
>   responses:
>     Unauthorized:
>       description: The key is missing, malformed, for another environment, expired or revoked. All of these get the same answer.
>       headers:
>         X-Request-Id:
>           $ref: "#/components/headers/XRequestId"
>       content:
>         application/json:
>           schema:
>             $ref: "#/components/schemas/UnauthorizedError"
>           examples:
>             unauthorized:
>               summary: Missing, malformed, expired or revoked key
>               value:
>                 error:
>                   code: unauthorized
>                   message: Missing or invalid PMS credential.
>                   request_id: e867476c-9237-4ebd-af42-b93abc47d0ed
>     InsufficientScope:
>       description: The key is valid but lacks the `properties:read` scope.
>       headers:
>         X-Request-Id:
>           $ref: "#/components/headers/XRequestId"
>       content:
>         application/json:
>           schema:
>             $ref: "#/components/schemas/InsufficientScopeError"
>           examples:
>             insufficientScope:
>               summary: The key lacks properties:read
>               value:
>                 error:
>                   code: insufficient_scope
>                   message: This PMS credential lacks the properties:read scope.
>                   request_id: 0f3b8f8e-5f8c-4b84-9a8e-5d6c2a1e7b40
>     RateLimited:
>       description: Too many requests in the current minute. Wait for `Retry-After` seconds.
>       headers:
>         X-Request-Id:
>           $ref: "#/components/headers/XRequestId"
>         Retry-After:
>           $ref: "#/components/headers/RetryAfter"
>       content:
>         application/json:
>           schema:
>             $ref: "#/components/schemas/RateLimitedError"
>           examples:
>             rateLimited:
>               summary: More than 60 requests in a minute
>               value:
>                 error:
>                   code: rate_limited
>                   message: Too many requests. Retry after the number of seconds in Retry-After.
>                   request_id: c2b7e1d4-8a3f-4e6b-9d2c-7f1a5e9b3c08
>   schemas:
>     Health:
>       type: object
>       additionalProperties: false
>       required:
>         - status
>       properties:
>         status:
>           type: string
>           enum:
>             - ok
>     Me:
>       type: object
>       additionalProperties: false
>       required:
>         - credential_id
>         - pms_name
>         - environment
>         - scopes
>       properties:
>         credential_id:
>           type: string
>           format: uuid
>           description: The public ID of the PMS credential that made the call. Not a secret.
>         pms_name:
>           type: string
>           description: Your PMS, as Tatallo knows it.
>         environment:
>           type: string
>           enum:
>             - staging
>             - production
>             - development
>           description: The environment the key belongs to. `development` is Tatallo-internal.
>         scopes:
>           type: array
>           items:
>             type: string
>             enum:
>               - properties:read
>           description: What the key may do. `properties:read` lists and reads properties.
>     Property:
>       type: object
>       additionalProperties: false
>       required:
>         - id
>         - name
>         - timezone
>         - status
>         - country
>         - city
>         - max_guests
>         - currency
>         - updated_at
>       properties:
>         id:
>           type: string
>           format: uuid
>           description: |
>             The property's permanent, opaque identifier. Store it once in your mapping table: it
>             never changes meaning. It is an identifier, not a credential: knowing it grants
>             nothing.
>         name:
>           type: string
>           description: The property's name on Tatallo.
>         timezone:
>           type:
>             - string
>             - "null"
>           description: The IANA time zone of the property (for example `Europe/Rome`). Interpret stay dates and check-in times in it. May be `null` only while the property is `pending`.
>           example: Europe/Rome
>         status:
>           type: string
>           enum:
>             - active
>             - inactive
>             - pending
>           description: |
>             Whether the property can sell: `active` can; `inactive` was suspended and cannot;
>             `pending` is not live yet.
>         country:
>           type: string
>           description: The property's country, by name.
>         city:
>           type: string
>         max_guests:
>           type: integer
>           minimum: 1
>           description: The most guests the property sleeps.
>         currency:
>           type: string
>           pattern: ^[A-Z]{3}$
>           description: The property's currency, ISO 4217.
>         updated_at:
>           type: string
>           format: date-time
>           description: When the property last changed, ISO 8601 in UTC.
>     PageInfo:
>       type: object
>       additionalProperties: false
>       required:
>         - next_cursor
>       properties:
>         next_cursor:
>           type:
>             - string
>             - "null"
>           description: Pass it as `cursor` to get the next page. `null` on the last page.
>     PropertyList:
>       type: object
>       additionalProperties: false
>       required:
>         - data
>         - page
>       properties:
>         data:
>           type: array
>           items:
>             $ref: "#/components/schemas/Property"
>         page:
>           $ref: "#/components/schemas/PageInfo"
>     Error:
>       type: object
>       additionalProperties: false
>       required:
>         - error
>       description: |
>         The one error shape. Branch on `code`: `unauthorized` (401), `insufficient_scope` (403),
>         `property_not_found` (404), `invalid_cursor` (400), `invalid_limit` (400),
>         `rate_limited` (429). `message` is English and may change; codes never do.
>       properties:
>         error:
>           type: object
>           additionalProperties: false
>           required:
>             - code
>             - message
>             - request_id
>           properties:
>             code:
>               type: string
>               description: A stable, snake_case error code.
>             message:
>               type: string
>               description: An English explanation for people. May change; never branch on it.
>             request_id:
>               type: string
>               format: uuid
>               description: The same value as the `X-Request-Id` header.
>     UnauthorizedError:
>       allOf:
>         - $ref: "#/components/schemas/Error"
>         - type: object
>           properties:
>             error:
>               type: object
>               properties:
>                 code:
>                   const: unauthorized
>     InsufficientScopeError:
>       allOf:
>         - $ref: "#/components/schemas/Error"
>         - type: object
>           properties:
>             error:
>               type: object
>               properties:
>                 code:
>                   const: insufficient_scope
>     PropertyNotFoundError:
>       allOf:
>         - $ref: "#/components/schemas/Error"
>         - type: object
>           properties:
>             error:
>               type: object
>               properties:
>                 code:
>                   const: property_not_found
>     InvalidListQueryError:
>       allOf:
>         - $ref: "#/components/schemas/Error"
>         - type: object
>           properties:
>             error:
>               type: object
>               properties:
>                 code:
>                   enum:
>                     - invalid_limit
>                     - invalid_cursor
>     RateLimitedError:
>       allOf:
>         - $ref: "#/components/schemas/Error"
>         - type: object
>           properties:
>             error:
>               type: object
>               properties:
>                 code:
>                   const: rate_limited
> ```


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