---
title: "Book a visit"
method: POST
path: "/v1/bookings"
tags: ["Booking"]
---

# Book a visit

`POST /v1/bookings`

## Request

- Base URL: `https://api.nogpets.com`
- URL: `https://api.nogpets.com/v1/bookings`
- Auth: one of:
  - OAuth 2 (authorization code, authorization URL `https://api.nogpets.com/oauth/authorize`, token URL `https://api.nogpets.com/oauth/token`, scopes: `bookings:write`)
  - HTTP bearer

Books a slot from `find_times`. The server reprices and rechecks the slot. CARD →
PENDING with a `payUrl` for the person to open (Payfast). CASH → needs `confirm: true`
(else 409 `CONFIRM_REQUIRED` with the summary) and is PENDING with CASH_DUE.

## Request body

- BookRequest: One visit: start and resourceId from find_times. An overnight stay: `stay`. Visits over several days: `visits`.
  - `category` string, required: A service line id: grooming, walking or sitting.
  - `addressId` string, required
  - `pets` object[], required
    - `petId` string, required
    - `serviceIds` string[], required: Service ids from list_services; exactly one PRIMARY plus any EXTRAs of the same line. A package id (a line's `packages`) stands for its main service and extras.
    - `packageId` string
  - `start` string, date-time: A slot's start from find_times, unchanged.
  - `resourceId` string: The slot's resourceId, unchanged.
  - `paymentMethod` 'CARD' | 'CASH', required
  - `notes` string
  - `repeat` object: Walks only. Books the weeks up to 4 weeks out now; the rest follow.
    - `freq` 'WEEKLY', required
    - `days` string[], required
    - `until` string: A local date, YYYY-MM-DD.
  - `confirm` boolean: Cash only: true once the person said yes to the summary.
  - `stay` Stay: An overnight stay. One booking a night, from the evening visit to the next morning's check.
    - `startDate` string, required: A local date, YYYY-MM-DD.
    - `nights` integer, required
    - `eveningWindow` string: A window id from `windows.evening` (or "17:00-19:00"). Default the first.
    - `morningWindow` string: A window id from `windows.morning`. Default the first.
    - `notes` string: Keys, feeding, meds.
  - `visits` Visits: Visits over several days. One booking a visit, at the first free time in its window.
    - `startDate` string, required: A local date, YYYY-MM-DD.
    - `days` integer, required
    - `perDay` integer
    - `windows` string[]: A window id from `windows.visit` per visit of the day, in order.
    - `notes` string
  - `promoCode` string: The code from the quote. A code that no longer applies is a 409 PROMO (details.reason). Left out, a claimed offer is applied if it fits.

## Response `201`

Booked

- BookResult
  - `bookingId` string, required
  - `bookingIds` string[], required: Every week booked (repeats).
  - `seriesId` string, nullable
  - `status` 'PENDING' | 'ACCEPTED' | 'REJECTED' | 'CANCELLED' | 'COMPLETED', required
  - `paymentMethod` 'CARD' | 'CASH', required
  - `paymentStatus` 'PENDING' | 'PAID' | 'CASH_DUE' | 'CASH_RECEIVED' | 'REFUND_REQUESTED' | 'REFUNDED' | 'FAILED', required
  - `totalCents` integer, required
  - `total` string, required
  - `discount` Discount
    - `code` string, required
    - `amountCents` integer, required: What came off the price (never the card fee).
    - `auto` boolean
  - `plan` object, nullable: A stay or visits over days: {mode, label, count}.
  - `start` string, date-time, required
  - `when` string, required
  - `skipped` string[]: Repeat weeks that were full.
  - `payUrl` string, uri, nullable, required: Card: the link the person opens to pay (48 hours).
  - `next` string, required: What to tell the person.

## Other responses

- `400`: The input is wrong (`INVALID_ARGUMENT`, or a pricing code such as `ONE_PRIMARY`, `PET_TYPE`, `UNKNOWN_SERVICE`).
- `401`: No token, or it's expired or revoked. The `WWW-Authenticate` header points at the resource metadata.
- `403`: The token lacks a scope (`INSUFFICIENT_SCOPE`, with `details.scope`).
- `409`: A rule said no: `NO_COVERAGE`, `NO_AVAILABILITY`, `SLOT_TAKEN`, `TOO_LATE`, `CONFIRM_REQUIRED` (with `details.summary`), `NOTHING_TO_PAY`, `SHOP_OFF`, `STOCK`, `SHIPPING`, `DISCOUNT`, `CASH`, `FAILED_PRECONDITION`; business sign-up: `UNDER_REVIEW`, `APPROVED`, `NOT_READY`, `TOO_MANY`, `LISTING_TAKEN`, `PAYFAST_ZA_ONLY`. `NO_COVERAGE` carries `details.leadId`, `details.message` (tell the person) and `details.next`.
- `429`: Too many requests (`RATE_LIMIT`). `Retry-After` says when to try again.

---

[API](https://skmtc.dev/nogpets/apis/nogpets-api.md) · [All operations](https://skmtc.dev/nogpets/apis/nogpets-api/llms.txt) · [OpenAPI document](https://skmtc.dev/nogpets/apis/nogpets-api/revisions/a202c1012173?raw)
