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
- Log in to your Check-in DOG admin panel.
- Go to Check-in DOG Account > API Tokens.
- Click Generate token, give it a name, and copy the token displayed.
- Use the token in the
Authorization: Bearerheader for all authenticated requests. - Test with a simple request to
/api/v1/shopto verify your token works.
Support
If you need help integrating the API, contact us through the Contact page or consult the full documentation.