Skip to content
NogPets

For AI assistants and developers

NogPets REST API

The same prices, areas and bookings as the app, over HTTPS and JSON.

Available now Developers

Base URL

https://api.nogpets.com/v1

Sign-in

  • Services, coverage, quotes, open times, the shop's prices and the directory need no sign-in.
  • Anything about a person (profile, pets, addresses, bookings, orders) needs a token with the right scope, sent as Authorization: Bearer.
  • Money moves only when the person opens the Payfast pay link.

OAuth 2.1, for apps and assistants

  • Authorization code with PKCE (S256 only). Public clients, no secret.
  • Register once at POST /oauth/register (dynamic client registration). Metadata: /.well-known/oauth-authorization-server.
  • Send the person to /oauth/authorize. They sign in to NogPets and say yes. Swap the code at /oauth/token.
  • Access tokens last an hour. Refresh tokens last 30 days and change each time you use one.
  • The person sees each assistant in the app (Profile, then Connected assistants) and can remove it there.
curl -s https://api.nogpets.com/oauth/register -H 'Content-Type: application/json' \
  -d '{"client_name":"My assistant","redirect_uris":["http://127.0.0.1:8765/callback"]}'

# then send the person to:
https://api.nogpets.com/oauth/authorize?response_type=code&client_id=npcl_…
  &redirect_uri=http://127.0.0.1:8765/callback&code_challenge=<S256>&code_challenge_method=S256
  &state=…&scope=bookings:write%20pets%20addresses

curl -s https://api.nogpets.com/oauth/token -d grant_type=authorization_code \
  -d code=npc_… -d redirect_uri=http://127.0.0.1:8765/callback -d client_id=npcl_… -d code_verifier=…

A personal API key, for your own scripts

  • In the app: Profile, then Connected assistants, then New API key. Pick the scopes and how long it lasts (up to a year).
  • The key starts with npk_ and is shown once. Use it like a token.
TOKEN=npk_…
curl -s https://api.nogpets.com/v1/me -H "Authorization: Bearer $TOKEN"

Scopes

Scope What the person agrees to
profile See your name, email and phone
pets See and add your pets
addresses See and add your addresses
bookings:read See your bookings
bookings:write Book, move, cancel and get payment links for your bookings
orders:write Place shop orders for you to pay
business:write Set up and manage your pet business on NogPets

The person approves money

  • A card booking or a shop order comes back with a payUrl. Give it to the person. They open it and pay on Payfast. Nothing here takes a card.
  • A cash booking, and cancelling, need "confirm": true. Without it the answer is 409 CONFIRM_REQUIRED with a summary to show the person first.
  • Money is in cents of South African rand: 38000 is R380. Times are ISO; local time is Africa/Johannesburg (UTC+2).

Operations

Public

No sign-in. Cached for 5 minutes.

GET /v1/services

Service lines, services and prices

Every service line (grooming, walks, pet sitting), its services with prices by pet size and coat, the card fee, and the areas we cover.

Scope: No sign-in MCP tool: list_services

Example
curl -s "https://api.nogpets.com/v1/services"

Response · 200

{
  "currency": "ZAR",
  "serviceFeeCents": 1000,
  "acceptsCash": true,
  "areas": [
    "Stellenbosch Central",
    "Die Boord",
    "Paradyskloof"
  ],
  "lines": [
    {
      "id": "grooming",
      "label": "Grooming",
      "blurb": "Our van at your door. Bath, cut and nails.",
      "durationMode": "SUM",
      "repeats": false,
      "services": [
        {
          "id": "full-groom",
          "name": "Full groom",
          "kind": "PRIMARY",
          "blurb": "Bath, cut, blow-dry, nails and ears.",
          "petTypes": [
            "DOG"
          ],
          "priceCents": 38000,
          "durationMin": 60,
          "fromCents": 38000,
          "toCents": 68000,
          "groupSize": 1,
          "tiers": [
            {
              "coat": "LONG",
              "maxKg": 10,
              "priceCents": 46000,
              "durationMin": 75
            },
            {
              "maxKg": 10,
              "priceCents": 38000,
              "durationMin": 60
            }
          ]
        }
      ]
    }
  ]
}

GET /v1/coverage

Do you come to this address?

Places a typed address, a postal code or a map point in our territories and says which service lines reach it. When nothing does, nearest names our closest area.

Scope: No sign-in MCP tool: check_coverage

Example
curl -s "https://api.nogpets.com/v1/coverage?address=14%20Kromrivier%20Street%2C%20Die%20Boord%2C%20Stellenbosch%207613"

Response · 200

{
  "covered": true,
  "place": {
    "suburb": "Die Boord",
    "postalCode": "7613",
    "lat": -33.9467,
    "lng": 18.848
  },
  "lines": [
    {
      "id": "grooming",
      "label": "Grooming",
      "covered": true
    },
    {
      "id": "walking",
      "label": "Walks",
      "covered": true
    },
    {
      "id": "sitting",
      "label": "Pet sitting",
      "covered": true
    }
  ],
  "nearest": null
}

POST /v1/quote

Price for these pets at this address

The server's price and duration for one visit. Pets and address by value (no account needed), or saved ones (addressId, petId) with a token.

Scope: No sign-in MCP tool: get_quote

Example
curl -s -X POST "https://api.nogpets.com/v1/quote" \
  -H "Content-Type: application/json" \
  -d '{"category":"grooming","address":"14 Kromrivier Street, Die Boord 7613","pets":[{"name":"Biscuit","type":"DOG","weightKg":8,"coat":"SHORT","serviceIds":["full-groom","nails"]}]}'

Response · 200

{
  "category": "grooming",
  "durationMin": 70,
  "pets": [
    {
      "name": "Biscuit",
      "items": [
        {
          "serviceId": "full-groom",
          "name": "Full groom",
          "kind": "PRIMARY",
          "priceCents": 38000,
          "durationMin": 60
        },
        {
          "serviceId": "nails",
          "name": "Nails",
          "kind": "EXTRA",
          "priceCents": 6000,
          "durationMin": 10
        }
      ]
    }
  ],
  "subtotalCents": 44000,
  "cardFeeCents": 1000,
  "cardTotalCents": 45000,
  "cashTotalCents": 44000,
  "acceptsCash": true,
  "summary": "R440 cash, or R450 by card. About 70 minutes."
}

POST /v1/availability

Open times

Open start times over a date range (at most 31 days; default the next 7), from the same engine as the app. Same inputs as the quote.

Scope: No sign-in MCP tool: find_times

Example
curl -s -X POST "https://api.nogpets.com/v1/availability" \
  -H "Content-Type: application/json" \
  -d '{"category":"grooming","postalCode":"7613","pets":[{"name":"Biscuit","type":"DOG","weightKg":8,"coat":"SHORT","serviceIds":["full-groom"]}],"from":"2026-09-29","to":"2026-09-29","windowStart":"08:00","windowEnd":"12:00"}'

Response · 200

{
  "durationMin": 60,
  "quote": {
    "category": "grooming",
    "durationMin": 60,
    "pets": [
      {
        "name": "Biscuit",
        "items": [
          {
            "serviceId": "full-groom",
            "name": "Full groom",
            "kind": "PRIMARY",
            "priceCents": 38000,
            "durationMin": 60
          }
        ]
      }
    ],
    "subtotalCents": 38000,
    "cardFeeCents": 1000,
    "cardTotalCents": 39000,
    "cashTotalCents": 38000,
    "acceptsCash": true,
    "summary": "R380 cash, or R390 by card. About 60 minutes."
  },
  "days": [
    {
      "date": "2026-09-29",
      "label": "Tue 29 Sep",
      "slots": [
        {
          "start": "2026-09-29T06:00:00.000Z",
          "time": "08:00",
          "resourceId": "van-1"
        },
        {
          "start": "2026-09-29T06:30:00.000Z",
          "time": "08:30",
          "resourceId": "van-1"
        }
      ]
    }
  ]
}

GET /v1/directory

Pet businesses near Stellenbosch

Published listings of groomers, pet stores, vets, boarding, daycare, walkers and trainers, from public sources. NogPets is listed like everyone else (isNogPets).

Scope: No sign-in MCP tool: find_pet_businesses

Example
curl -s "https://api.nogpets.com/v1/directory"

Response shape · 200

{
  "listings": [
    {
      "id": "…",
      "name": "…",
      "town": "…",
      "suburb": "…",
      "address": "…",
      "categories": [
        "GROOMER_SALON"
      ],
      "services": [
        {}
      ],
      "petTypes": [
        "…"
      ],
      "phone": "…",
      "website": "…",
      "hoursText": "…",
      "blurb": "…",
      "isNogPets": true,
      "verified": true,
      "lastChecked": "2026-09-29",
      "url": "https://…"
    }
  ]
}

Your account and bookings

A token with the scope shown.

GET /v1/me

Who am I

Scope: profile MCP tool: my_profile

Example
curl -s "https://api.nogpets.com/v1/me" \
  -H "Authorization: Bearer $TOKEN"

Response · 200

{
  "uid": "u-client",
  "name": "Sam Test",
  "email": "client@nogpets.test",
  "phone": "+27820000001",
  "pets": 2,
  "addresses": 2,
  "client": {
    "id": "c_1",
    "name": "Claude"
  },
  "scopes": [
    "profile",
    "pets",
    "addresses",
    "bookings:read",
    "bookings:write"
  ]
}

GET /v1/pets

The person's pets

Scope: pets MCP tool: list_pets

Example
curl -s "https://api.nogpets.com/v1/pets" \
  -H "Authorization: Bearer $TOKEN"

Response · 200

{
  "pets": [
    {
      "id": "biscuit",
      "name": "Biscuit",
      "type": "DOG",
      "breed": "Boston terrier",
      "weightKg": 8,
      "coat": "SHORT",
      "birthYear": 2021,
      "notes": "Pulls on the lead."
    }
  ]
}

POST /v1/pets

Add a pet

Scope: pets MCP tool: add_pet

Example
curl -s -X POST "https://api.nogpets.com/v1/pets" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Rex","type":"DOG","weightKg":30,"coat":"LONG","breed":"Golden retriever"}'

Response shape · 201

{
  "id": "…",
  "name": "…",
  "type": "DOG",
  "breed": "…",
  "weightKg": 0,
  "coat": "SHORT",
  "birthYear": 0,
  "notes": "…"
}

GET /v1/addresses

The person's addresses

Scope: addresses MCP tool: list_addresses

Example
curl -s "https://api.nogpets.com/v1/addresses" \
  -H "Authorization: Bearer $TOKEN"

Response shape · 200

{
  "addresses": [
    {
      "id": "…",
      "label": "…",
      "line1": "…",
      "suburb": "…",
      "city": "…",
      "postalCode": "…",
      "notes": "…",
      "isDefault": true
    }
  ]
}

POST /v1/addresses

Add an address

Scope: addresses MCP tool: add_address

Example
curl -s -X POST "https://api.nogpets.com/v1/addresses" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"label":"Home","line1":"14 Kromrivier Street","suburb":"Die Boord","postalCode":"7613","notes":"Gate code 1234"}'

GET /v1/bookings

The person's upcoming bookings

Scope: bookings:read MCP tool: list_bookings

Example
curl -s "https://api.nogpets.com/v1/bookings" \
  -H "Authorization: Bearer $TOKEN"

Response shape · 200

{
  "bookings": [
    {
      "id": "…",
      "category": "…",
      "what": "…",
      "start": "2026-09-29T07:00:00.000Z",
      "end": "2026-09-29T07:00:00.000Z",
      "when": "…",
      "address": {
        "label": "…",
        "line1": "…",
        "suburb": "…"
      },
      "status": "PENDING",
      "paymentMethod": "CARD",
      "paymentStatus": "PENDING",
      "totalCents": 0,
      "total": "…",
      "crew": [
        "…"
      ],
      "seriesId": "…",
      "canPay": true,
      "source": "…"
    }
  ]
}

POST /v1/bookings

Book a visit

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.

Scope: bookings:write MCP tool: book

Example
curl -s -X POST "https://api.nogpets.com/v1/bookings" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"category":"grooming","addressId":"home","pets":[{"petId":"biscuit","serviceIds":["full-groom","nails"]}],"start":"2026-09-29T07:00:00.000Z","resourceId":"van-1","paymentMethod":"CARD"}'

Response · 201

{
  "bookingId": "bk_123",
  "bookingIds": [
    "bk_123"
  ],
  "status": "PENDING",
  "paymentMethod": "CARD",
  "paymentStatus": "PENDING",
  "totalCents": 45000,
  "total": "R450",
  "start": "2026-09-29T07:00:00.000Z",
  "when": "Tue 29 Sep at 09:00",
  "skipped": [],
  "payUrl": "https://api.nogpets.com/pay/b/bk_123?t=abc.def",
  "next": "Open the payment link to pay R450 on Payfast. The time is held; it's confirmed once paid."
}

GET /v1/bookings/{bookingId}

One booking

Scope: bookings:read MCP tool: get_booking

Example
curl -s "https://api.nogpets.com/v1/bookings/<bookingId>" \
  -H "Authorization: Bearer $TOKEN"

Response shape · 200

{
  "id": "…",
  "category": "…",
  "what": "…",
  "start": "2026-09-29T07:00:00.000Z",
  "end": "2026-09-29T07:00:00.000Z",
  "when": "…",
  "address": {
    "label": "…",
    "line1": "…",
    "suburb": "…"
  },
  "status": "PENDING",
  "paymentMethod": "CARD",
  "paymentStatus": "PENDING",
  "totalCents": 0,
  "total": "…",
  "crew": [
    "…"
  ],
  "seriesId": "…",
  "canPay": true,
  "source": "…"
}

POST /v1/bookings/{bookingId}/times

Open times to move a booking to

Scope: bookings:read MCP tool: find_reschedule_times

Example
curl -s -X POST "https://api.nogpets.com/v1/bookings/<bookingId>/times" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'

Response shape · 200

{
  "bookingId": "…",
  "durationMin": 0,
  "days": [
    {
      "date": "…",
      "label": "…",
      "slots": [
        {}
      ]
    }
  ]
}

POST /v1/bookings/{bookingId}/reschedule

Move a booking

Same price and payment, until 12 hours before. The booking goes back to PENDING for the business to accept the new time.

Scope: bookings:write MCP tool: reschedule_booking

Example
curl -s -X POST "https://api.nogpets.com/v1/bookings/<bookingId>/reschedule" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"start":"2026-09-29T07:00:00.000Z"}'

Response shape · 200

{
  "bookingId": "…",
  "start": "2026-09-29T07:00:00.000Z",
  "when": "…",
  "resourceId": "…",
  "status": "PENDING",
  "paymentStatus": "PENDING"
}

POST /v1/bookings/{bookingId}/cancel

Cancel a booking

Before it starts. A paid booking goes to REFUND_REQUESTED and NogPets refunds it. Needs confirm: true.

Scope: bookings:write MCP tool: cancel_booking

Example
curl -s -X POST "https://api.nogpets.com/v1/bookings/<bookingId>/cancel" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"confirm":true}'

Response shape · 200

{
  "cancelled": [
    "…"
  ]
}

POST /v1/bookings/{bookingId}/pay

A payment link

A fresh Payfast link (48 hours) for an unpaid card booking, for the person to open. No card data passes through here.

Scope: bookings:write MCP tool: pay_booking

Example
curl -s -X POST "https://api.nogpets.com/v1/bookings/<bookingId>/pay" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'

Response shape · 200

{
  "bookingId": "…",
  "totalCents": 0,
  "total": "…",
  "payUrl": "https://…",
  "expiresAt": "2026-09-29T07:00:00.000Z",
  "next": "…"
}

Shop

Only while the shop is open. Else 409 SHOP_OFF.

GET /v1/products

Shop products

Active products with variants and stock, and the delivery options. SHOP_OFF (409) while the shop is closed.

Scope: No sign-in MCP tool: browse_shop

Example
curl -s "https://api.nogpets.com/v1/products"

Response shape · 200

{
  "products": [
    {
      "id": "…",
      "name": "…",
      "slug": "…",
      "category": "…",
      "blurb": "…",
      "petTypes": [
        "…"
      ],
      "priceCents": 0,
      "compareAtCents": 0,
      "variants": [
        {}
      ],
      "inStock": true,
      "deliverWithVisit": true,
      "image": "https://…"
    }
  ],
  "shipping": [
    {
      "id": "…",
      "label": "…",
      "feeCents": 0,
      "eta": "…",
      "postalCodes": [
        "…"
      ]
    }
  ],
  "freeShippingOverCents": 0,
  "note": "…"
}

POST /v1/orders/quote

Price a shop order

The server's prices, delivery, discount and total. Never fails on stock or a bad code; it reports them in problems, discountError, shippingError.

Scope: No sign-in MCP tool: quote_order

Example
curl -s -X POST "https://api.nogpets.com/v1/orders/quote" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"productId":"kibble-lamb","variantId":"2kg","qty":1}],"shippingMethod":"courier"}'

Response shape · 200

{
  "items": [
    {}
  ],
  "subtotalCents": 0,
  "discount": {},
  "discountError": "…",
  "shippingMethod": "…",
  "shipping": {},
  "shippingCents": 0,
  "shippingError": "…",
  "totalCents": 0,
  "problems": [
    {}
  ],
  "ok": true
}

POST /v1/orders

Place a shop order

Reprices, checks stock, and places the order. Card → PENDING_PAYMENT with a payUrl (the order's page with a Pay button). Cash (only add-ons to the person's own cash booking, visit) needs confirm: true.

Scope: orders:write MCP tool: buy

Example
curl -s -X POST "https://api.nogpets.com/v1/orders" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"productId":"…","qty":1}],"shippingMethod":"…"}'

Response shape · 201

{
  "orderId": "…",
  "number": "…",
  "status": "…",
  "totalCents": 0,
  "total": "…",
  "payUrl": "https://…",
  "next": "…"
}

Business sign-up

For groomers, walkers and sitters joining NogPets. Scope business:write. Nothing goes live until we approve it.

GET /v1/business/applications

A business sign-up's checklist and status

The person's business application (the one named, else the newest) with its checklist, what's missing and the signed status page link; plus a list of all their applications.

Scope: business:write MCP tool: get_signup_status

Example
curl -s "https://api.nogpets.com/v1/business/applications" \
  -H "Authorization: Bearer $TOKEN"

Response shape · 200

{
  "applications": [
    {
      "applicationId": "…",
      "name": "…",
      "status": "DRAFT"
    }
  ],
  "next": "…",
  "welcomeUrl": "https://…"
}

POST /v1/business/applications

Start (or update) a pet business's sign-up

Step 1 of registering a pet-care business on NogPets. Creates a DRAFT application owned by the signed-in person, or updates its details when applicationId is given. Nothing is public until NogPets approves it. The order: startBusinessSignup → addBusinessServices → setServiceArea → addResources → inviteStaff (optional) → connectPayfast (optional) → getSignupStatus → submitBusinessForReview.

Scope: business:write MCP tool: start_business_signup

Example
curl -s -X POST "https://api.nogpets.com/v1/business/applications" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"businessName":"Happy Paws Grooming (Pty) Ltd","tradingName":"Happy Paws Mobile Grooming","contactName":"Anna Botha","phone":"082 555 0101","email":"anna@happypaws.example","website":"happypaws.example","town":"Somerset West","suburbs":["Heldervue","Helderberg Estate"],"categories":["grooming"],"mode":"MOBILE","vans":1,"staff":2,"whatsappOptIn":true}'

Response shape · 200

{
  "applicationId": "…",
  "status": "DRAFT",
  "business": {},
  "listing": {
    "id": "…",
    "name": "…",
    "town": "…"
  },
  "services": [
    {}
  ],
  "areas": [
    {}
  ],
  "overlaps": [
    {
      "area": "…",
      "territory": "…",
      "grantedTo": "…"
    }
  ],
  "resources": [
    {}
  ],
  "invites": [
    {}
  ],
  "payfast": {
    "merchantId": "…",
    "split": true,
    "status": "…"
  },
  "whatsappOptIn": true,
  "checklist": [
    {
      "id": "details",
      "label": "…",
      "done": true,
      "required": true,
      "detail": "…"
    }
  ],
  "readyToSubmit": true,
  "reviewNote": "…",
  "bizId": "…",
  "possibleListings": [
    {}
  ],
  "payfastInfo": "…",
  "summary": "…",
  "statusUrl": "https://…",
  "welcomeUrl": "https://…",
  "next": "…"
}

POST /v1/business/applications/{applicationId}/services

Add services and prices to a sign-up

Step 2. Adds or replaces the business's services (the NogPets service model: one PRIMARY per booking per pet plus EXTRAs, prices by weight and coat tiers, durations), or starts from NogPets' own menu with useTemplate.

Scope: business:write MCP tool: add_business_services

Example
curl -s -X POST "https://api.nogpets.com/v1/business/applications/<applicationId>/services" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"services":[{"category":"grooming","kind":"PRIMARY","name":"Full groom","blurb":"Bath, cut, blow-dry, nails and ears.","petTypes":["DOG"],"priceCents":40000,"durationMin":60,"tiers":[{"maxKg":10,"priceCents":40000,"durationMin":60},{"minKg":10,"maxKg":25,"priceCents":52000,"durationMin":75},{"minKg":25,"priceCents":68000,"durationMin":90}]},{"category":"grooming","kind":"EXTRA","name":"Nail clip","priceCents":8000,"durationMin":10}]}'

Response shape · 200

{
  "applicationId": "…",
  "status": "DRAFT",
  "business": {},
  "listing": {
    "id": "…",
    "name": "…",
    "town": "…"
  },
  "services": [
    {}
  ],
  "areas": [
    {}
  ],
  "overlaps": [
    {
      "area": "…",
      "territory": "…",
      "grantedTo": "…"
    }
  ],
  "resources": [
    {}
  ],
  "invites": [
    {}
  ],
  "payfast": {
    "merchantId": "…",
    "split": true,
    "status": "…"
  },
  "whatsappOptIn": true,
  "checklist": [
    {
      "id": "details",
      "label": "…",
      "done": true,
      "required": true,
      "detail": "…"
    }
  ],
  "readyToSubmit": true,
  "reviewNote": "…",
  "bizId": "…",
  "possibleListings": [
    {}
  ],
  "payfastInfo": "…",
  "summary": "…",
  "statusUrl": "https://…",
  "welcomeUrl": "https://…",
  "next": "…"
}

POST /v1/business/applications/{applicationId}/area

Set where the business works

Step 3. Sets the whole service area (each call replaces it) as proposed territories, PENDING until NogPets approves them.

Scope: business:write MCP tool: set_service_area

Example
curl -s -X POST "https://api.nogpets.com/v1/business/applications/<applicationId>/area" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"suburbs":[{"name":"Heldervue","postalCode":"7130"},{"name":"Helderberg Estate","postalCode":"7130"}],"center":{"lat":-34.0766,"lng":18.8433},"radiusKm":8,"centerName":"Somerset West"}'

Response shape · 200

{
  "applicationId": "…",
  "status": "DRAFT",
  "business": {},
  "listing": {
    "id": "…",
    "name": "…",
    "town": "…"
  },
  "services": [
    {}
  ],
  "areas": [
    {}
  ],
  "overlaps": [
    {
      "area": "…",
      "territory": "…",
      "grantedTo": "…"
    }
  ],
  "resources": [
    {}
  ],
  "invites": [
    {}
  ],
  "payfast": {
    "merchantId": "…",
    "split": true,
    "status": "…"
  },
  "whatsappOptIn": true,
  "checklist": [
    {
      "id": "details",
      "label": "…",
      "done": true,
      "required": true,
      "detail": "…"
    }
  ],
  "readyToSubmit": true,
  "reviewNote": "…",
  "bizId": "…",
  "possibleListings": [
    {}
  ],
  "payfastInfo": "…",
  "summary": "…",
  "statusUrl": "https://…",
  "welcomeUrl": "https://…",
  "next": "…"
}

POST /v1/business/applications/{applicationId}/resources

Add vans, walkers and sitters with working hours

Step 4. The things clients book a time on (a grooming van, a walker, a sitter), each with its working week.

Scope: business:write MCP tool: add_resources

Example
curl -s -X POST "https://api.nogpets.com/v1/business/applications/<applicationId>/resources" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"resources":[{"kind":"VAN","name":"Van 1","week":{"mon":[{"start":"08:00","end":"16:00"}],"tue":[{"start":"08:00","end":"16:00"}],"wed":[{"start":"08:00","end":"16:00"}],"thu":[{"start":"08:00","end":"16:00"}],"fri":[{"start":"08:00","end":"14:00"}]}}]}'

Response shape · 200

{
  "applicationId": "…",
  "status": "DRAFT",
  "business": {},
  "listing": {
    "id": "…",
    "name": "…",
    "town": "…"
  },
  "services": [
    {}
  ],
  "areas": [
    {}
  ],
  "overlaps": [
    {
      "area": "…",
      "territory": "…",
      "grantedTo": "…"
    }
  ],
  "resources": [
    {}
  ],
  "invites": [
    {}
  ],
  "payfast": {
    "merchantId": "…",
    "split": true,
    "status": "…"
  },
  "whatsappOptIn": true,
  "checklist": [
    {
      "id": "details",
      "label": "…",
      "done": true,
      "required": true,
      "detail": "…"
    }
  ],
  "readyToSubmit": true,
  "reviewNote": "…",
  "bizId": "…",
  "possibleListings": [
    {}
  ],
  "payfastInfo": "…",
  "summary": "…",
  "statusUrl": "https://…",
  "welcomeUrl": "https://…",
  "next": "…"
}

POST /v1/business/applications/{applicationId}/staff

Invite staff

Step 5 (optional). Staff to invite once the business is approved, by email or phone, as manager or crew.

Scope: business:write MCP tool: invite_staff

Example
curl -s -X POST "https://api.nogpets.com/v1/business/applications/<applicationId>/staff" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"invites":[{"name":"Thandi","phone":"071 555 0199","role":"crew"},{"name":"Pieter","email":"pieter@example.com","role":"manager"}]}'

Response shape · 200

{
  "applicationId": "…",
  "status": "DRAFT",
  "business": {},
  "listing": {
    "id": "…",
    "name": "…",
    "town": "…"
  },
  "services": [
    {}
  ],
  "areas": [
    {}
  ],
  "overlaps": [
    {
      "area": "…",
      "territory": "…",
      "grantedTo": "…"
    }
  ],
  "resources": [
    {}
  ],
  "invites": [
    {}
  ],
  "payfast": {
    "merchantId": "…",
    "split": true,
    "status": "…"
  },
  "whatsappOptIn": true,
  "checklist": [
    {
      "id": "details",
      "label": "…",
      "done": true,
      "required": true,
      "detail": "…"
    }
  ],
  "readyToSubmit": true,
  "reviewNote": "…",
  "bizId": "…",
  "possibleListings": [
    {}
  ],
  "payfastInfo": "…",
  "summary": "…",
  "statusUrl": "https://…",
  "welcomeUrl": "https://…",
  "next": "…"
}

POST /v1/business/applications/{applicationId}/payfast

Connect a Payfast merchant (id only)

Step 6 (optional, needed for card payments). Stores the business's Payfast merchant id for split payments, pending NogPets' verification. Never send a merchant key or passphrase; the schema refuses any field but the id.

Scope: business:write MCP tool: connect_payfast

Example
curl -s -X POST "https://api.nogpets.com/v1/business/applications/<applicationId>/payfast" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"merchantId":"10012345"}'

Response shape · 200

{
  "applicationId": "…",
  "status": "DRAFT",
  "business": {},
  "listing": {
    "id": "…",
    "name": "…",
    "town": "…"
  },
  "services": [
    {}
  ],
  "areas": [
    {}
  ],
  "overlaps": [
    {
      "area": "…",
      "territory": "…",
      "grantedTo": "…"
    }
  ],
  "resources": [
    {}
  ],
  "invites": [
    {}
  ],
  "payfast": {
    "merchantId": "…",
    "split": true,
    "status": "…"
  },
  "whatsappOptIn": true,
  "checklist": [
    {
      "id": "details",
      "label": "…",
      "done": true,
      "required": true,
      "detail": "…"
    }
  ],
  "readyToSubmit": true,
  "reviewNote": "…",
  "bizId": "…",
  "possibleListings": [
    {}
  ],
  "payfastInfo": "…",
  "summary": "…",
  "statusUrl": "https://…",
  "welcomeUrl": "https://…",
  "next": "…"
}

POST /v1/business/applications/{applicationId}/submit

Submit a sign-up for NogPets' review

The last step. Without confirm it answers 409 CONFIRM_REQUIRED with details.summary to show the person; with confirm: true the application goes to NogPets (SUBMITTED) and can't change until they answer. NOT_READY lists what's missing.

Scope: business:write MCP tool: submit_business_for_review

Example
curl -s -X POST "https://api.nogpets.com/v1/business/applications/<applicationId>/submit" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"confirm":true}'

Response shape · 200

{
  "applicationId": "…",
  "status": "DRAFT",
  "business": {},
  "listing": {
    "id": "…",
    "name": "…",
    "town": "…"
  },
  "services": [
    {}
  ],
  "areas": [
    {}
  ],
  "overlaps": [
    {
      "area": "…",
      "territory": "…",
      "grantedTo": "…"
    }
  ],
  "resources": [
    {}
  ],
  "invites": [
    {}
  ],
  "payfast": {
    "merchantId": "…",
    "split": true,
    "status": "…"
  },
  "whatsappOptIn": true,
  "checklist": [
    {
      "id": "details",
      "label": "…",
      "done": true,
      "required": true,
      "detail": "…"
    }
  ],
  "readyToSubmit": true,
  "reviewNote": "…",
  "bizId": "…",
  "possibleListings": [
    {}
  ],
  "payfastInfo": "…",
  "summary": "…",
  "statusUrl": "https://…",
  "welcomeUrl": "https://…",
  "next": "…"
}

Errors

Errors look like {"error": {"code", "message", "details"}}. The code is stable; the message is short and safe to show.

HTTP/1.1 409
{"error": {"code": "CONFIRM_REQUIRED",
  "message": "Show the person this summary and send confirm true once they say yes.",
  "details": {"summary": "Full groom for Biscuit, Tue 29 Sep at 09:00, 14 Kromrivier Street. R440 cash on the day."}}}

Codes

INVALID_ARGUMENTONE_PRIMARYPET_TYPEUNKNOWN_SERVICEINSUFFICIENT_SCOPENO_COVERAGENO_AVAILABILITYSLOT_TAKENTOO_LATECONFIRM_REQUIREDNOTHING_TO_PAYSHOP_OFFSTOCKSHIPPINGDISCOUNTCASHFAILED_PRECONDITIONUNKNOWN_PLACERATE_LIMIT

Rate limits

  • 120 requests a minute per token. 60 a minute per IP without one.
  • Over the limit: 429 RATE_LIMIT with Retry-After.
  • 20 client registrations an hour and 30 OAuth calls a minute per IP.

Spec

Building something?

Tell us what you want to connect. A person reads every email.

hello@nogpets.com