Skip to content

API request/response shape catalog from a two-week integration (6 items, one PR offer) #321

Description

@modernitconsultants

We've spent two weeks integrating a companion service against the API (client-credentials service account, migration tooling, a scheduler) and hit a series of request-shape asymmetries, each costing a failed run before the shape was clear. Cataloguing them in one place — partly as a docs suggestion, partly because a couple look unintentional. All measured against current main on a live deployment.

  1. propertyId: query on reads, body on writes. GETs accept ?propertyId=; POST /rooms/types, POST /rate-plans, POST /reservations/:id/notes validate it in the body and answer 400 propertyId must be a UUID when it's only in the query — which reads as "your UUID is malformed" rather than "wrong location". A dry run of reads proves nothing about the writes.
  2. PATCH /reservations/:id/cancel rejects a body (property reason should not exist). A cancellation reason feels like the natural payload; if it's deliberately unsupported, a hint in the 400 would save the round-trip.
  3. PATCH /reservations/:id rejects source — probably deliberate (provenance shouldn't be editable?) but undocumented.
  4. Read envelopes differ per resource: lists unwrap under data, GET /reservations/:id under reservation, GET /reservations/:id/notes under notes (+ activeCount). A client has to know each key; a consistent envelope (or documenting the exceptions) would remove a silent-failure class — we shipped a bug where iterating the notes dict's keys silently emptied a dedup check.
  5. List endpoints default to limit=20 with no indication of truncation in the payload shape a naive client reads. Fine with pagination docs front-and-centre; painful when a "list all" consumer silently gets page 1 (our fault, but a total surfaced more prominently would have caught it sooner).
  6. No native home for an external reservation reference on direct create/import. bookings.external_confirmation exists and the channel-inbound path populates it, but CreateReservationDto silently drops unknown fields, so migration tooling has nowhere to store the source system's reference — we ended up carrying it in notes text. Accepting externalConfirmation on direct create/import would give integrators id-based idempotency. Happy to PR this one if you'd take it.

Related PRs already open from us: #317 (azp allow-list), #318 (ical roles), #319 (room-type move), #320 (rate-plan deactivate).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions