API Reference

Connect your website or external tools to Check-in DOG

Overview

The Check-in DOG API lets you integrate your grooming salon with your own website or external applications. Whether you want to display real-time availability on your website, add an appointment booking form, or synchronize data with another tool, the API gives you full programmatic access to your salon data.

Key use cases:

  • Embed an appointment booking form on your website that shows real-time availability.
  • Build a custom customer-facing portal.
  • Export appointment and invoice data to your accounting software.
  • Automate workflows with other business tools.

Base URL

All API requests are made to:

https://checkindog.app/api/v1/

All responses are JSON. All dates and timestamps use the ISO 8601 format.


Authentication

Most API endpoints require authentication via a Bearer token. You generate tokens from the admin panel under Check-in DOG Account > API Tokens.

Include the token in the Authorization header of every authenticated request:

Authorization: Bearer your-api-token-here

Each token is scoped to a single salon. Multiple tokens can be created for the same salon (for example, one per integration).

Security best practices:

  • Treat API tokens like passwords. Never commit them to source code.
  • Use one token per integration so you can revoke individual tokens without affecting others.
  • Revoke tokens immediately when they are no longer needed.

Public Endpoints

These endpoints require no authentication. They are designed for embedding on public-facing websites.

GET /api/v1/shops/{slug}

Returns the public profile of a salon.

Parameters: {slug} is the salon's unique identifier (visible in your admin URL).

Response:

{
  "data": {
    "slug": "happy-paws",
    "name": "Happy Paws Grooming",
    "description": "Professional grooming for all breeds.",
    "phone": "+33 1 23 45 67 89",
    "mobile": null,
    "email": "contact@happypaws.fr",
    "website": "https://happypaws.fr",
    "address": "12 Rue des Fleurs",
    "zip_code": "75001",
    "city": "Paris",
    "country": "FR",
    "opening_hours": { "monday": "9:00-18:00" },
    "social": {
      "facebook": null,
      "instagram": "https://instagram.com/happypaws",
      "twitter": null,
      "youtube": null
    },
    "locale": "fr",
    "currency": "EUR",
    "timezone": "Europe/Paris"
  }
}

GET /api/v1/shops/{slug}/availability

Returns available appointment slots for a date range. Use this to power a booking widget on your website.

Query parameters:

Parameter Type Required Description
date string No Start date in YYYY-MM-DD format. Defaults to today.
days integer No Number of days to look ahead (1-30). Defaults to 7.

Response:

{
  "shop": "happy-paws",
  "from": "2026-03-15",
  "to": "2026-03-21",
  "availability": {
    "2026-03-15": {
      "available": true,
      "slots": [
        { "start": "2026-03-15T09:00:00+01:00", "end": "2026-03-15T10:00:00+01:00" },
        { "start": "2026-03-15T14:00:00+01:00", "end": "2026-03-15T15:00:00+01:00" }
      ]
    },
    "2026-03-16": {
      "available": false,
      "reason": "closed",
      "slots": []
    }
  }
}

Availability reasons when available is false:

  • closed: the salon has no time slots defined for that day.
  • holiday: the day is marked as a holiday in the salon calendar.

POST /api/v1/shops/{slug}/appointment-requests

Submit a public appointment request. This creates a Contact record in the salon's Contacts section for the owner to review and convert into a confirmed appointment.

Request body:

{
  "first_name": "Marie",
  "last_name": "Dupont",
  "email": "marie.dupont@example.com",
  "phone": "+33 6 12 34 56 78",
  "message": "I'd like to book a full grooming for my Golden Retriever.",
  "requested_at": "2026-03-20"
}
Field Type Required Description
first_name string Yes Customer's first name.
last_name string Yes Customer's last name.
email string No Customer's email address.
phone string No Customer's phone number.
message string No Free-text message or special requirements.
requested_at string No Preferred date in YYYY-MM-DD format.

Response (201):

{
  "message": "Your appointment request has been received. The salon will contact you to confirm.",
  "data": {
    "id": 42,
    "first_name": "Marie",
    "last_name": "Dupont",
    "email": "marie.dupont@example.com",
    "phone": "+33 6 12 34 56 78"
  }
}

Authenticated Endpoints

All endpoints below require a valid Bearer token in the Authorization header.


GET /api/v1/shop

Returns the full profile of the salon associated with the API token, including the current billing plan.

Response: same as the public shop endpoint, plus a "plan" field ("free", "solo", or "pro").


Customers

GET /api/v1/customers

List all customers for your salon.

Query parameters:

Parameter Type Description
search string Filter by name, email, or phone.
per_page integer Results per page (default: 25, max: 100).
page integer Page number (default: 1).

Response:

{
  "data": [
    {
      "id": 1,
      "first_name": "Marie",
      "last_name": "Dupont",
      "full_name": "Marie Dupont",
      "email": "marie@example.com",
      "phone": "+33 6 12 34 56 78",
      "city": "Paris",
      "created_at": "2026-01-15T10:30:00+01:00"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 25,
    "total": 72
  }
}

POST /api/v1/customers

Create a new customer.

Request body:

{
  "first_name": "Marie",
  "last_name": "Dupont",
  "email": "marie@example.com",
  "phone": "+33 6 12 34 56 78",
  "address": "12 Rue des Fleurs",
  "zip_code": "75001",
  "city": "Paris",
  "country": "FR",
  "send_sms": true
}

GET /api/v1/customers/{id}

Retrieve a single customer including their animals.

PUT /api/v1/customers/{id}

Update a customer. Send only the fields you want to change.

DELETE /api/v1/customers/{id}

Delete a customer. Returns 204 No Content.


Animals

GET /api/v1/animals

List all animals for your salon.

Query parameters:

Parameter Type Description
customer_id integer Filter by customer ID.
per_page integer Results per page (default: 25, max: 100).
page integer Page number (default: 1).

POST /api/v1/animals

Create a new animal record.

Required fields: customer_id, name.

Optional fields: animal_type_id, color, sex (m or f), birth_date, weight, chip_number, notes.

GET /api/v1/animals/{id}

Retrieve a single animal including customer and type details.

PUT /api/v1/animals/{id}

Update an animal. Send only the fields you want to change.

DELETE /api/v1/animals/{id}

Delete an animal record. Returns 204 No Content.


Appointments

GET /api/v1/appointments

List appointments for your salon.

Query parameters:

Parameter Type Description
from string Start date filter (YYYY-MM-DD).
to string End date filter (YYYY-MM-DD).
customer_id integer Filter by customer ID.
animal_id integer Filter by animal ID.
waiting_list boolean Filter waiting list entries.
per_page integer Results per page (default: 25, max: 100).
page integer Page number.

POST /api/v1/appointments

Create a new appointment.

Required fields: animal_id, start, end.

Optional fields: comments, comment_for_customer, waiting_list, leash.

GET /api/v1/appointments/{id}

Retrieve a single appointment with animal and customer details.

PUT /api/v1/appointments/{id}

Update an appointment. Send only the fields you want to change.

DELETE /api/v1/appointments/{id}

Delete an appointment. Returns 204 No Content.


Invoices

Invoices use an immutable sequential numbering system. For audit integrity, invoices cannot be updated or deleted via the API.

GET /api/v1/invoices

List invoices for your salon.

Query parameters:

Parameter Type Description
from string Invoice date start (YYYY-MM-DD).
to string Invoice date end (YYYY-MM-DD).
customer_id integer Filter by customer ID.
paid boolean Filter by paid status.
per_page integer Results per page (default: 25, max: 100).
page integer Page number.

GET /api/v1/invoices/{id}

Retrieve a single invoice with its line items and customer details.

POST /api/v1/invoices

Create a new invoice. The invoice number is assigned automatically.

Request body:

{
  "customer_id": 1,
  "paid": true,
  "notes": "Thank you for your loyalty!",
  "lines": [
    {
      "item_id": 5,
      "description": "Full grooming - Labrador",
      "quantity": 1,
      "price_with_tax": 55.00,
      "discount": 0
    }
  ]
}

Error Responses

The API returns standard HTTP status codes. Error responses include a JSON body with an error field and an optional messages field for validation errors.

Code Meaning
400 Bad request.
401 Unauthenticated. Token is missing or invalid.
404 Resource not found.
422 Validation error. Check the messages field.
500 Internal server error.

Example validation error:

{
  "error": "Validation failed.",
  "messages": {
    "first_name": ["The first name field is required."],
    "email": ["The email must be a valid email address."]
  }
}

Rate Limiting

The API enforces rate limiting to ensure fair use and system stability. Requests are limited to 60 per minute per API token. If you exceed this limit, you will receive a 429 Too Many Requests response.


Pagination

All list endpoints return paginated results. The response includes a meta object:

{
  "meta": {
    "current_page": 1,
    "last_page": 5,
    "per_page": 25,
    "total": 118
  }
}

Use the page and per_page query parameters to navigate through results.


Getting Started

  1. Log in to your Check-in DOG admin panel.
  2. Go to Check-in DOG Account > API Tokens.
  3. Click Generate token, give it a name, and copy the token displayed.
  4. Use the token in the Authorization: Bearer header for all authenticated requests.
  5. Test with a simple request to /api/v1/shop to verify your token works.

Support

If you need help integrating the API, contact us through the Contact page or consult the full documentation.