Read and write your salon data from your own code: a REST API with scoped keys and per-key rate limits over appointments, clients, services and salons, and signed webhooks when something changes.
API keys
The HairDora REST API lets your own backend work with the same records the dashboard shows: the appointments in your calendar, the clients who book them, the services you offer and the salons they belong to.
An administrator of your organization creates an API key in the HairDora dashboard. The secret is shown once, when the key is created, and never again — store it somewhere safe. A key belongs to a single organization, so the organization is implied by the key and never has to be sent; a key can additionally be locked to one salon.
Authenticate every request with HTTP Basic auth carrying only the key secret, base64-encoded, in the Authorization header.
# The Authorization header is HTTP Basic auth carrying only the key secret,
# with no username and no colon.
Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)Every endpoint lives under https://api.hairdora.com. Requests made with a key are rate limited per key; going over the limit returns 429.
Quick start
Find your salon, read the week ahead in its calendar, then add a client to it.
# List the salons the key can reach
curl https://api.hairdora.com/api/salons \
-H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"
# List next week's appointments for one salon.
# startTime and endTime are ISO 8601 instants.
curl -G https://api.hairdora.com/api/appointments \
--data-urlencode "salonId=SALON_ID" \
--data-urlencode "startTime=2026-01-06T00:00:00.000Z" \
--data-urlencode "endTime=2026-01-13T00:00:00.000Z" \
--data-urlencode "sortField=startTime" \
--data-urlencode "sortDirection=ASC" \
-H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"
# Create a client in that salon
curl -X POST https://api.hairdora.com/api/clients \
-H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)" \
-H "Content-Type: application/json" \
-d '{
"salonId": "SALON_ID",
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com"
}'Browse the full API reference — every endpoint with its parameters, request body, responses and required scope.
CLI
The same salons, clients, services and appointments are available from your terminal through the hairdora CLI. Install it globally with npm, or run it ad hoc with npx.
You do not even need an account first: hairdora signup creates one, with your organization and first salon, and logs you in. For an existing account, hairdora login opens your browser and stores a session, or pastes an API key secret with --with-key. Headless scripts and agents can skip login entirely by exporting HAIRDORA_API_KEY.
# Install once, globally
npm install -g hairdora
# or run it ad hoc without installing
npx hairdora --help
# Create an account from the terminal — no browser needed
hairdora signup --email owner@example.com
# Or log in to an existing account: opens your browser, stores a session
hairdora login
# The salons this account can reach
hairdora salons list
# Next week in one salon's calendar
hairdora appointments list --salonId SALON_ID \
--startTime 2026-01-06T00:00:00.000Z \
--endTime 2026-01-13T00:00:00.000Z --sortField startTime --sortDirection ASC
# Add a client to that salon
hairdora clients add --salonId SALON_ID --name "Ada Lovelace" --email ada@example.comEvery command takes --json for parseable output, and hairdora schema prints the whole command tree as JSON so a script never has to scrape help text. The CLI is open source at github.com/hairdora/cli and published as hairdora on npm. Run any command with --help to see its options.
AI connector
Connect HairDora to Claude, ChatGPT, Codex, VS Code or another compatible MCP client to review the salons, schedules, availability, clients, appointments, services, quote status and payment status in your organization. The same remote URL works for every user; your signed-in HairDora account determines which organization is available.
Add the Streamable HTTP URL below to your client. It sends you to HairDora to sign in and approve the read-only hairdora:read scope. You can revoke the connection from HairDora account settings or disconnect it in the client.
# Add this remote MCP URL in Claude, ChatGPT, Codex, VS Code,
# or another Streamable HTTP MCP client:
https://mcp.hairdora.com/mcp
# Sign in to HairDora when your client opens the OAuth flow and approve the
# read-only hairdora:read scope.
# Example: "Show my salon overview and explain the next two weeks of availability."The connector has thirteen read-only tools and two compact cross-host cards: a bounded salon overview and an appointment detail. It cannot book, reschedule, cancel or delete an appointment; edit a client; create a quote; charge or refund a payment; or otherwise move funds.
Client display names and pseudonymous client, appointment, salon, service, quote and payment identifiers are returned only where needed to find and chain records. Client email, phone and address, free-text notes, private calendar reasons, staff identifiers, payment-card or processor data, organization identifiers and unbounded raw records are excluded. Only connect accounts and conversations authorized to handle your salon data.
Agent Skills
HairDora ships Agent Skills — guides following the agentskills.io standard that teach coding agents how to run salon workflows with the hairdora CLI and the MCP connector, instead of guessing at commands and tools.
# Install the HairDora skills into your coding agent
npx skills add hairdora/skillsOne command installs the skills into Claude Code, Cursor, Codex, Gemini CLI and any other agent that follows the Skills standard. The CLI also bundles the same guides, version-matched to the commands it ships: hairdora skills get <name> prints one on demand.
The skills are open source at github.com/hairdora/skills. Claude users can also install the HairDora Claude plugin, which bundles the connector together with the skills: github.com/hairdora/claude-plugin.
Scopes
Each key carries a list of scopes, so an integration that only needs to read your calendar never gets the ability to change it. New keys start read-only; widen them explicitly in the dashboard. A request whose key is missing the scope an endpoint requires is refused with 403.
There is no salons:write scope: a salon is the container your data lives in, created when you sign up, not something an integration creates.
Webhooks
Add a webhook subscription to your salon and HairDora POSTs the events you picked to your server as they happen. An empty event list subscribes to all of them.
POST https://your-server.com/hairdora-webhook
X-Hairdora-Event: appointment.created
X-Hairdora-Signature: t=1719000000,v1=<hmac-sha256 hex>
Content-Type: application/json
{
"event": "appointment.created",
"timestamp": 1719000000,
"data": { "...": "..." }
}Every delivery carries an X-Hairdora-Signature header of the form t=timestamp,v1=signature, where the signature is an HMAC-SHA256 of timestamp.body keyed by the subscription secret shown to you once when the subscription was created. Recompute it over the raw body and compare before trusting the payload.
import crypto from 'node:crypto'
// body must be the RAW request body, byte for byte
function verify(header, body, secret) {
const [t, v1] = (header || '').split(',').map(part => part.split('=')[1])
if (!t || !v1) return false
const expected = crypto
.createHmac('sha256', secret)
.update(`${t}.${body}`)
.digest('hex')
// timingSafeEqual throws on a length mismatch, so a malformed signature
// has to be rejected before the comparison rather than by it.
if (v1.length !== expected.length) return false
return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
}Delivery is one best-effort attempt with a five second timeout and no retries, so respond 2xx quickly and do the work asynchronously. An endpoint that fails twenty times in a row is disabled automatically and has to be re-enabled in the dashboard.
Start building