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

# List properties

> Lists the active properties within the brand that your API key can access.
**Brand-wide discovery — no `Kyc-Property-Id` header** (this is how you discover property IDs).
Results are scoped by your key's authorized properties.




## OpenAPI

````yaml get /properties
openapi: 3.1.0
info:
  title: KYC Hospitality Public API
  version: 1.0.0
  summary: Public REST API for hotel tech partners.
  description: >
    The KYC Hospitality public API for hotel technology partners.


    Key conventions (full detail in the design docs):

    - **Brand is the host/subdomain**; the path is brand-agnostic and identical
    across brands.

    - **Property scope** via the `Kyc-Property-Id` header — required on
    property-scoped resources,
      omitted on brand-wide ones (e.g. guests).
    - **Auth**: `Authorization: Bearer <key>` (prefixed `kyc_live_` /
    `kyc_test_`).

    - **Success** responses use a `{ data, meta }` envelope; every resource
    carries an `object` discriminator.

    - **Errors** are RFC 9457 `application/problem+json`, enriched with a stable
    machine `code`.

    - **Casing**: `camelCase` for all fields/params/variables; `kebab-case` for
    URL path segments.

    - **Strict** input validation; **lenient** output contract (clients must
    ignore unknown fields).
  contact:
    name: KYC API Support
    email: api-support@kychospitality.com
    url: https://docs.kychospitality.com
  license:
    name: Proprietary — © KYC Hospitality
  termsOfService: https://docs.kychospitality.com/terms
servers:
  - url: https://{service}.{brand}.kych.co/v1
    description: Production. Brand is the host; the path is brand-agnostic.
    variables:
      service:
        default: public-api
        description: API service label (not yet finalized — `public-api` or `api`).
      brand:
        default: hilton
        description: Brand subdomain, e.g. `hilton`.
security:
  - bearerAuth: []
tags:
  - name: System
    description: Utility endpoints for API information and health checks.
  - name: Properties
    description: >-
      Hotel properties within the brand. Discovery endpoints — scoped by the API
      key, not the property header.
paths:
  /properties:
    get:
      tags:
        - Properties
      summary: List properties
      description: >
        Lists the active properties within the brand that your API key can
        access.

        **Brand-wide discovery — no `Kyc-Property-Id` header** (this is how you
        discover property IDs).

        Results are scoped by your key's authorized properties.
      operationId: listProperties
      parameters:
        - $ref: '#/components/parameters/UserAgent'
        - $ref: '#/components/parameters/CorrelationId'
        - $ref: '#/components/parameters/Traceparent'
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PerPage'
      responses:
        '200':
          description: A page of properties.
          headers:
            Kyc-Request-Id:
              $ref: '#/components/headers/KycRequestId'
            Kyc-Correlation-Id:
              $ref: '#/components/headers/KycCorrelationId'
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                  - meta
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Property'
                  meta:
                    $ref: '#/components/schemas/Meta'
              examples:
                ok:
                  value:
                    data:
                      - object: property
                        id: 4a2f0c10-2e7a-4b9d-9b3a-1f0c9e8d7a6b
                        name: Hilton Austin Downtown
                        code: ATXDT
                        status: active
                        timezone: America/Chicago
                        createdAt: '2025-01-15T09:00:00.000Z'
                        updatedAt: '2026-05-02T14:30:00.000Z'
                    meta:
                      requestId: req_01J9Z3K8Q2X7C5N0
                      timestamp: '2026-06-26T22:01:01.010Z'
                      pagination:
                        page: 1
                        perPage: 50
                        total: 1
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '406':
          $ref: '#/components/responses/NotAcceptable'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    UserAgent:
      name: User-Agent
      in: header
      required: true
      description: Identifies the calling application. 3–255 printable ASCII characters.
      schema:
        type: string
        minLength: 3
        maxLength: 255
        pattern: ^[\x20-\x7E]+$
      example: AcmePMS/2.3 (+https://acme.example.com)
    CorrelationId:
      name: Kyc-Correlation-Id
      in: header
      required: false
      description: >
        Optional caller-supplied opaque ID for log correlation. Echoed back and
        logged.

        Treated opaquely (never decoded). Must match the pattern below.
      schema:
        type: string
        pattern: ^[A-Za-z0-9._=+/-]{1,128}$
      example: 6f1c2a9e-4d3b-4c8a-9e2f-7b1a0d5c3e21
    Traceparent:
      name: traceparent
      in: header
      required: false
      description: >
        Optional W3C Trace Context header for distributed tracing. A malformed
        value is ignored

        and a fresh trace is started (per the W3C spec) — it never causes a 4xx.
      schema:
        type: string
      example: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
    Page:
      name: page
      in: query
      required: false
      description: Page number (1-based).
      schema:
        type: integer
        minimum: 1
        default: 1
    PerPage:
      name: perPage
      in: query
      required: false
      description: Items per page.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 50
  headers:
    KycRequestId:
      description: >-
        Server-generated request ID. Present on every response. Mirrors
        `meta.requestId`.
      schema:
        type: string
      example: req_01J9Z3K8Q2X7C5N0
    KycCorrelationId:
      description: >-
        Echo of the caller's `Kyc-Correlation-Id`, present only when one was
        sent.
      schema:
        type: string
    RetryAfter:
      description: Seconds to wait before retrying. Sent on 429 and 503.
      schema:
        type: integer
        minimum: 0
      example: 30
    RateLimitLimit:
      description: >-
        Request quota for the window. (Documented now; enforcement later —
        Decision 13.)
      schema:
        type: integer
    RateLimitRemaining:
      description: Requests remaining in the current window.
      schema:
        type: integer
    RateLimitReset:
      description: Seconds until the quota resets.
      schema:
        type: integer
  schemas:
    Property:
      type: object
      description: >
        A hotel property within the brand.

        **STUB — minimal starting field set; expand additively** (adding fields
        is non-breaking, Decision 3).

        Fields are a deliberately-curated public subset of the internal model,
        not the whole object.
      required:
        - object
        - id
        - name
        - code
        - status
        - timezone
        - createdAt
        - updatedAt
      properties:
        object:
          type: string
          const: property
          description: Resource type discriminator.
        id:
          type: string
          format: uuid
          description: Property UUID (stable, never changes).
        name:
          type: string
          description: Property display name.
          examples:
            - Hilton Austin Downtown
        code:
          type:
            - string
            - 'null'
          description: >
            Short, human-friendly property code. **Public,
            implementation-agnostic alias** — maps from an

            internal field via the API Resource. **TBD: confirm the source and
            semantics** (the internal

            `elasticsearch_id` is currently used as a code). NEVER expose
            internal field names (e.g.

            `elasticsearch_id`) to partners. Nullable until source/semantics
            confirmed.
          examples:
            - ATXDT
        status:
          type: string
          enum:
            - active
            - inactive
          description: Whether the property is active.
        timezone:
          type: string
          description: >-
            IANA timezone name. Always present — required for correct date/time
            handling.
          examples:
            - America/Chicago
        createdAt:
          type: string
          format: date-time
          description: When the property record was created (UTC).
        updatedAt:
          type: string
          format: date-time
          description: When the property record was last updated (UTC).
    Meta:
      type: object
      description: Metadata present on every success response.
      required:
        - requestId
        - timestamp
      properties:
        requestId:
          type: string
          description: >-
            Server-generated ID for this request (mirrors the `Kyc-Request-Id`
            header).
          examples:
            - req_01J9Z3K8Q2X7C5N0
        timestamp:
          type: string
          format: date-time
          description: UTC timestamp, ISO 8601 with milliseconds.
          examples:
            - '2026-06-25T22:01:01.010Z'
        pagination:
          $ref: '#/components/schemas/Pagination'
          description: Present only on list responses.
    Pagination:
      type: object
      description: Offset/page pagination metadata (Decision 11).
      required:
        - page
        - perPage
        - total
      properties:
        page:
          type: integer
          minimum: 1
          description: Current page number (1-based).
        perPage:
          type: integer
          minimum: 1
          description: Items per page.
        total:
          type: integer
          minimum: 0
          description: Total items across all pages.
    ProblemDetails:
      type: object
      description: >
        RFC 9457 problem+json, enriched. **Every field is always present** —
        empty scalars are `""`,

        empty arrays are `[]`. Clients branch on `code`, never on
        `title`/`detail` text.
      required:
        - type
        - title
        - status
        - detail
        - moreInfo
        - instance
        - code
        - errors
        - requestId
        - timestamp
      properties:
        type:
          type: string
          format: uri
          description: >-
            URL to the docs page for this error code (this IS the documentation
            reference).
          examples:
            - https://docs.kychospitality.com/errors/guest-not-found
        title:
          type: string
          description: Short, human-readable summary of the error class (stable).
        status:
          type: integer
          description: HTTP status code, repeated for convenience.
          examples:
            - 404
        detail:
          type: string
          description: >-
            Human-readable detail specific to this occurrence. May change; do
            not parse.
        moreInfo:
          type: string
          description: >-
            Optional inline troubleshooting tips beyond `detail`. `""` when
            none.
        instance:
          type: string
          description: Path of the request that produced the error.
          examples:
            - /v1/guests/9c8e1f20-1a2b-3c4d-5e6f-708192a3b4c5
        code:
          type: string
          description: Stable, machine-readable error code. Clients branch on this.
          examples:
            - GUEST_NOT_FOUND
        errors:
          type: array
          description: Field-level problems (populated for 422 validation; `[]` otherwise).
          items:
            $ref: '#/components/schemas/FieldError'
        requestId:
          type: string
          description: Server request ID (mirrors the `Kyc-Request-Id` header).
        timestamp:
          type: string
          format: date-time
          description: UTC timestamp of the error.
    FieldError:
      type: object
      description: One field-level validation problem inside `ProblemDetails.errors`.
      required:
        - field
        - code
        - detail
      properties:
        field:
          type: string
          description: Dotted/array path to the offending field.
          examples:
            - email
            - phones[0].number
        code:
          type: string
          description: Stable field-error code.
          examples:
            - INVALID_FORMAT
            - INVALID_ENUM_VALUE
            - REQUIRED
            - OUT_OF_RANGE
        detail:
          type: string
          description: Human-readable explanation for this field.
  responses:
    BadRequest:
      description: >-
        Malformed or protocol-level error (bad JSON, unknown param/field, wrong
        casing, trailing slash, missing required header).
      headers:
        Kyc-Request-Id:
          $ref: '#/components/headers/KycRequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            unknownParameter:
              value:
                type: https://docs.kychospitality.com/errors/unknown-query-parameter
                title: Unknown query parameter
                status: 400
                detail: >-
                  The query parameter 'firstname' is not recognized. Did you
                  mean 'firstName'?
                moreInfo: >-
                  This endpoint only accepts documented, allow-listed
                  parameters.
                instance: /v1/guests
                code: UNKNOWN_QUERY_PARAMETER
                errors: []
                requestId: req_01J9Z3K8Q2X7C5N0
                timestamp: '2026-06-25T22:01:01.010Z'
    Unauthorized:
      description: Authentication failed (missing/invalid/expired/unknown key).
      headers:
        Kyc-Request-Id:
          $ref: '#/components/headers/KycRequestId'
        WWW-Authenticate:
          description: Authentication scheme.
          schema:
            type: string
          example: Bearer
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            missingAuth:
              value:
                type: https://docs.kychospitality.com/errors/missing-auth-header
                title: Missing Authorization header
                status: 401
                detail: >-
                  No Authorization header was provided. Send 'Authorization:
                  Bearer <key>'.
                moreInfo: ''
                instance: /v1/
                code: MISSING_AUTH_HEADER
                errors: []
                requestId: req_01J9Z3K8Q2X7C5N0
                timestamp: '2026-06-25T22:01:01.010Z'
    Forbidden:
      description: >-
        Authenticated, but not allowed (brand/property access, scope,
        suspended).
      headers:
        Kyc-Request-Id:
          $ref: '#/components/headers/KycRequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            propertyAccessDenied:
              value:
                type: https://docs.kychospitality.com/errors/property-access-denied
                title: Property access denied
                status: 403
                detail: Your key is not authorized for the requested property.
                moreInfo: ''
                instance: /v1/rooms/1b2c3d4e-0000-0000-0000-000000000000
                code: PROPERTY_ACCESS_DENIED
                errors: []
                requestId: req_01J9Z3K8Q2X7C5N0
                timestamp: '2026-06-25T22:01:01.010Z'
    NotAcceptable:
      description: The requested representation (Accept header) cannot be produced.
      headers:
        Kyc-Request-Id:
          $ref: '#/components/headers/KycRequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            notAcceptable:
              value:
                type: https://docs.kychospitality.com/errors/not-acceptable
                title: Not acceptable
                status: 406
                detail: >-
                  This endpoint only produces application/json. Requested Accept
                  could not be satisfied.
                moreInfo: ''
                instance: /v1/properties
                code: NOT_ACCEPTABLE
                errors: []
                requestId: req_01J9Z3K8Q2X7C5N0
                timestamp: '2026-06-25T22:01:01.010Z'
    TooManyRequests:
      description: Rate limit exceeded.
      headers:
        Kyc-Request-Id:
          $ref: '#/components/headers/KycRequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            rateLimited:
              value:
                type: https://docs.kychospitality.com/errors/rate-limited
                title: Too many requests
                status: 429
                detail: Rate limit exceeded. Retry after 30 seconds.
                moreInfo: ''
                instance: /v1/guests
                code: RATE_LIMITED
                errors: []
                requestId: req_01J9Z3K8Q2X7C5N0
                timestamp: '2026-06-25T22:01:01.010Z'
    InternalError:
      description: >
        Unexpected server fault. No internals are leaked; quote the requestId to
        support.

        **Body is best-effort:** this `problem+json` is produced only when the
        application's exception

        handler is reached. A true crash, or an infra-level failure (e.g. AWS
        ALB returning 502/504

        before the request reaches the app), bypasses this handler — callers
        MUST tolerate a non-JSON

        5xx response and not assume this shape on any 5xx.
      headers:
        Kyc-Request-Id:
          $ref: '#/components/headers/KycRequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            internal:
              value:
                type: https://docs.kychospitality.com/errors/internal-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred. Contact support with the
                  requestId.
                moreInfo: ''
                instance: /v1/guests
                code: INTERNAL_ERROR
                errors: []
                requestId: req_01J9Z3K8Q2X7C5N0
                timestamp: '2026-06-25T22:01:01.010Z'
    ServiceUnavailable:
      description: Temporarily unavailable (maintenance/overload). Retry per Retry-After.
      headers:
        Kyc-Request-Id:
          $ref: '#/components/headers/KycRequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            unavailable:
              value:
                type: https://docs.kychospitality.com/errors/service-unavailable
                title: Service unavailable
                status: 503
                detail: >-
                  The service is temporarily unavailable. Retry after 30
                  seconds.
                moreInfo: ''
                instance: /v1/properties
                code: SERVICE_UNAVAILABLE
                errors: []
                requestId: req_01J9Z3K8Q2X7C5N0
                timestamp: '2026-06-25T22:01:01.010Z'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        API key sent as a bearer token: `Authorization: Bearer kyc_live_...`.

        Keys are prefixed `kyc_live_` (production) or `kyc_test_` (test mode).

        OAuth2 access tokens (also `Bearer`) may be supported later — the header
        never changes.

````