The Glasshound REST API lets you automate bookings, check availability, and receive real-time webhook events. It integrates directly with n8n, Zapier, or any HTTP client.
https://yoursalon.glasshound.app/api/v1All API requests require a Bearer token. Generate keys from Settings โ API Keys in your dashboard.
curl -H "Authorization: Bearer gh_live_abc123..." \
https://yoursalon.glasshound.app/api/v1/me
// Response
{ "tenantId": "ten_...", "salonName": "Nina's Pet Salon", "scopes": ["appointments:read", "appointments:write"] }Available scopes: appointments:read appointments:write clients:read clients:write animals:read animals:write webhooks:read webhooks:write
/api/v1/availabilityReturns open time slots for a service on a given date. Always call this before booking.
GET /api/v1/availability?serviceId=svc_abc&date=2025-06-15
{
"data": {
"date": "2025-06-15",
"serviceId": "svc_abc",
"slots": [
{ "startsAt": "2025-06-15T09:00:00Z", "endsAt": "2025-06-15T10:30:00Z" },
{ "startsAt": "2025-06-15T11:00:00Z", "endsAt": "2025-06-15T12:30:00Z" },
{ "startsAt": "2025-06-15T14:00:00Z", "endsAt": "2025-06-15T15:30:00Z" }
]
}
}/api/v1/appointmentsPOST /api/v1/appointments
Authorization: Bearer gh_live_...
{
"serviceId": "svc_abc123",
"animalId": "ani_xyz789",
"clientId": "cli_def456",
"startsAt": "2025-06-15T09:00:00Z"
}
// 201 Response
{
"data": {
"id": "apt_...", "status": "CONFIRMED",
"startsAt": "2025-06-15T09:00:00Z",
"endsAt": "2025-06-15T10:30:00Z",
"priceCents": 7500
}
}/api/v1/appointments/{id}/cancelPOST /api/v1/appointments/apt_abc/cancel
{ "reason": "Client requested cancellation" }
// Response
{ "data": { "id": "apt_abc", "status": "CANCELLED" } }/api/v1/appointments/{id}/reschedulePOST /api/v1/appointments/apt_abc/reschedule
{ "newStartsAt": "2025-06-20T10:00:00Z", "reason": "Client requested new time" }
// Response
{ "data": { "id": "apt_abc", "status": "CONFIRMED", "startsAt": "2025-06-20T10:00:00Z" } }/api/v1/appointments/{id}/statusPATCH /api/v1/appointments/apt_abc/status
{ "status": "CHECKED_IN" }
// Flow: CONFIRMED โ CHECKED_IN โ IN_PROGRESS โ READY โ COMPLETED/api/v1/clientsGET /api/v1/clients?q=nina&page=1&pageSize=20
{
"data": [{ "id": "cli_...", "name": "Nina Reyes", "email": "nina@example.com", "tier": "VIP" }],
"meta": { "page": 1, "pageSize": 20, "total": 42, "pages": 3 }
}/api/v1/clientsPOST /api/v1/clients
{ "name": "Jane Smith", "email": "jane@example.com", "phone": "555-0100", "tier": "New" }/api/v1/clients/{id}PATCH /api/v1/clients/cli_abc
{ "tier": "VIP", "notes": "Prefers morning appointments." }/api/v1/animalsGET /api/v1/animals?clientId=cli_abc&species=dog
{
"data": [{
"id": "ani_...", "name": "Biscuit", "species": "dog",
"breed": "Golden Retriever", "weightLbs": "34.5",
"allergies": ["lavender"], "behaviorFlags": ["anxious"],
"preferredCadenceDays": 42, "lastVisitAt": "2025-04-30T00:00:00Z"
}]
}/api/v1/animalsPOST /api/v1/animals
{
"clientId": "cli_abc",
"name": "Biscuit",
"species": "dog",
"breed": "Golden Retriever",
"allergies": ["lavender"],
"preferredCadenceDays": 42
}/api/v1/servicesGET /api/v1/services?species=dog
{
"data": [
{ "id": "svc_abc", "name": "Full Groom", "durationMinutes": 90, "priceCents": 7500, "species": "Dog" },
{ "id": "svc_def", "name": "Bath & Brush", "durationMinutes": 60, "priceCents": 5500, "species": null }
]
}/api/v1/notesPOST /api/v1/notes
{
"animalId": "ani_abc",
"appointmentId": "apt_xyz",
"tag": "behavior",
"body": "Biscuit was anxious near clippers. Used slow approach. Completed successfully.",
"visibility": "INTERNAL"
}
// Tags: general ยท allergy ยท behavior ยท grooming ยท medical ยท followupReceive real-time push notifications when appointments change. Payloads are signed with HMAC-SHA256.
/api/v1/webhook-endpointsPOST /api/v1/webhook-endpoints
{
"url": "https://your-n8n.example.com/webhook/glasshound",
"events": ["appointment.created", "appointment.completed", "rebooking.due"],
"description": "n8n booking automation"
}
// Response โ save signingSecret, shown only once!
{
"data": { "id": "whe_...", "url": "...", "events": [...] },
"signingSecret": "whsec_abc123...",
"warning": "Save this signing secret โ it will not be shown again."
}// In a Code node before processing the webhook:
const crypto = require("crypto");
const ts = $input.first().headers["x-glasshound-timestamp"];
const sig = $input.first().headers["x-glasshound-signature"];
const body = JSON.stringify($input.first().body);
const expected = "sha256=" + crypto
.createHmac("sha256", $env.GLASSHOUND_WEBHOOK_SECRET)
.update(`${ts}.${body}`)
.digest("hex");
if (sig !== expected) throw new Error("Invalid webhook signature");
return $input.all();// appointment.created / appointment.completed / appointment.cancelled
{
"event": "appointment.created",
"tenantId": "ten_...",
"timestamp": "2025-06-15T09:00:00Z",
"data": {
"appointmentId": "apt_...", "animalId": "ani_...",
"clientId": "cli_...", "serviceId": "svc_...",
"startsAt": "2025-06-20T10:00:00Z", "status": "CONFIRMED"
}
}
// rebooking.due
{
"event": "rebooking.due",
"tenantId": "ten_...",
"data": {
"animalId": "ani_...", "animalName": "Biscuit",
"clientId": "cli_...", "clientName": "Jane Smith",
"clientEmail": "jane@example.com",
"daysSinceLastVisit": 45, "preferredCadenceDays": 42
}
}Webhook trigger โ HTTP Request (check availability) โ Set node (pick slot) โ HTTP Request (create booking). No code required โ just configure the HTTP Request nodes with your API key.
// 1. Webhook trigger receives form data:
{ "petName": "Biscuit", "clientEmail": "jane@example.com", "serviceId": "svc_abc", "preferredDate": "2025-06-20" }
// 2. HTTP Request โ GET /api/v1/availability
// URL: https://yoursalon.glasshound.app/api/v1/availability?serviceId={{ $json.serviceId }}&date={{ $json.preferredDate }}
// Auth: Header Auth โ Authorization: Bearer {{ $env.GLASSHOUND_KEY }}
// 3. Set node โ pick first slot
// startsAt: {{ $json.data.slots[0].startsAt }}
// 4. HTTP Request โ POST /api/v1/appointments
{
"serviceId": "{{ $('Webhook').item.json.serviceId }}",
"animalId": "{{ $('Lookup Animal').item.json.data[0].id }}",
"clientId": "{{ $('Lookup Client').item.json.data[0].id }}",
"startsAt": "{{ $('Pick Slot').item.json.startsAt }}"
}// 1. Glasshound fires "rebooking.due" webhook to your n8n URL
// 2. Webhook trigger node receives it
// 3. Code node verifies the HMAC signature (see above)
// 4. Send Email node โ "Time to book {{ $json.data.animalName }}'s next groom!"
// 5. Optional: HTTP Request โ POST /api/v1/appointments (auto-book next open slot)Authorization, value: Bearer gh_live_โฆPOST /api/v1/webhook-endpoints with your n8n webhook URLsigningSecret as an n8n env var: GLASSHOUND_WEBHOOK_SECRET// All errors share this envelope:
{
"error": "Validation error",
"status": 422,
"details": {
"fieldErrors": { "startsAt": ["Required"] },
"formErrors": []
}
}