REST API reference
Meevo API
14 endpoints for Meevo. Each one is a POST with a JSON body, called with your API key.
- Base URL
- https://cotlet.dev/api/v1/meevo
- Connects with
- Your Meevo staff login, with security access to the areas you use
- Integration page
- Meevo
| Endpoint | Access | Description |
|---|---|---|
| list_locations | read | Locations your login can reach, with address and time zone. |
| list_services | read | Service menu of a location by category, with duration, price and add-ons. |
| list_staff | read | Employees of a location with title and the services each one performs. |
| list_appointments | read | Appointments in the Appointment Book for a date range, with client, services, employee and confirmation status. |
| find_open_slots | read | Open times for a service in a date range, with the employees who can perform it. |
| find_client | read | Search clients by name, email or phone; returns contact details and client type. |
| get_client | read | Client profile with upcoming appointments, visit notes, memberships, packages, gift cards and points. |
| list_packages | read | Package and membership definitions of a location with price and included services. |
| get_register_summary | read | The end-of-day Register Summary: sales by type, payment methods, membership sales, returns and deposits. |
| add_visit_note | write | Add an internal visit note to a client profile. |
| book_appointment | write | Book one or more services for a client with an employee; Meevo sends your usual confirmation. |
| reschedule_appointment | write | Move an appointment to a new time or employee. |
| cancel_appointment | write | Cancel an appointment with one of your cancellation reasons. |
| sell_package | write | Ring up a package for a client in the Register and record the payment. |
List locations
readPOST https://cotlet.dev/api/v1/meevo/list_locations
Returns every Meevo location your staff login can reach. Use location_id from each item as the location_id parameter of the other tools. Time zone is the one set on the location.
Parameters
No parameters.
Request
curl -X POST https://cotlet.dev/api/v1/meevo/list_locations \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("meevo", "list_locations") const result = await cotlet.call('meevo', 'list_locations'); cotlet call meevo list_locations Example response
{
"locations": [
{
"location_id": "201",
"name": "Maple Street Salon",
"address": "12 Maple St, Hoboken, NJ",
"time_zone": "America/New_York"
},
{
"location_id": "202",
"name": "Harbor Spa",
"address": "88 Harbor Rd, Jersey City, NJ",
"time_zone": "America/New_York"
}
]
} List services
readPOST https://cotlet.dev/api/v1/meevo/list_services
Lists the service menu of one location grouped by category. Each service has its duration, price and add-ons. Use service_id with find_open_slots and book_appointment.
Parameters
| Name | Type | Description |
|---|---|---|
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
| category | string | Only this service category. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/list_services \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("meevo", "list_services") const result = await cotlet.call('meevo', 'list_services'); cotlet call meevo list_services Example response
{
"categories": [
{
"category": "Color",
"services": [
{
"service_id": "9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
"name": "Balayage",
"duration_minutes": 150,
"price": 220,
"add_ons": [
"Toner"
]
}
]
}
]
} List staff
readPOST https://cotlet.dev/api/v1/meevo/list_staff
Lists the employees of one location with their title and the services each performs. Use staff_id to narrow list_appointments and find_open_slots, or to book with a specific employee.
Parameters
| Name | Type | Description |
|---|---|---|
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/list_staff \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("meevo", "list_staff") const result = await cotlet.call('meevo', 'list_staff'); cotlet call meevo list_staff Example response
{
"staff": [
{
"staff_id": "e1d2c3b4-a5f6-4e7d-9c8b-7a6f5e4d3c2b",
"name": "Alex Rivera",
"title": "Senior Stylist",
"services": [
"Balayage",
"Haircut"
]
},
{
"staff_id": "a7b8c9d0-e1f2-4a3b-8c4d-9e0f1a2b3c4d",
"name": "Sam Patel",
"title": "Stylist",
"services": [
"Balayage",
"Blowout"
]
}
]
} List appointments
readPOST https://cotlet.dev/api/v1/meevo/list_appointments
Returns appointments from the Appointment Book for one location, oldest start first. Canceled appointments are left out unless include_canceled is true. Confirmation status is the one Meevo shows on the appointment. Use appointment_id with reschedule_appointment and cancel_appointment.
Parameters
| Name | Type | Description |
|---|---|---|
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
| from required | date | First day, inclusive. |
| to | date | Last day, inclusive. Default: same as from. |
| staff_id | string | Only this employee. |
| include_canceled | boolean | Also return canceled appointments. Default: false. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/list_appointments \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-10-01"}' result = client.call("meevo", "list_appointments", {"from":"2026-10-01"}) const result = await cotlet.call('meevo', 'list_appointments', {"from":"2026-10-01"}); cotlet call meevo list_appointments --data '{"from":"2026-10-01"}' Example response
{
"appointments": [
{
"appointment_id": "4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9",
"start": "2026-10-12T09:00:00-04:00",
"end": "2026-10-12T11:30:00-04:00",
"client": {
"id": "c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60",
"name": "Jamie Doe"
},
"services": [
"Balayage"
],
"staff": "Alex Rivera",
"confirmation_status": "confirmed"
},
{
"appointment_id": "7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
"start": "2026-10-12T14:00:00-04:00",
"end": "2026-10-12T14:45:00-04:00",
"client": {
"id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f7a",
"name": "Sam Lee"
},
"services": [
"Haircut"
],
"staff": "Alex Rivera",
"confirmation_status": "unconfirmed"
}
]
} Find open slots
readPOST https://cotlet.dev/api/v1/meevo/find_open_slots
Returns open start times for one service in a date range, earliest first, each with the employees free at that time. Without staff_id it searches every employee who performs the service. Use a start and staff_id from the result with book_appointment.
Parameters
| Name | Type | Description |
|---|---|---|
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
| service_id required | string | Service ID from list_services. |
| from required | date | First day to search. |
| to required | date | Last day to search. |
| staff_id | string | Only this employee. Default: anyone who performs the service. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/find_open_slots \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"location_id":"201","service_id":"9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d","from":"2026-10-18","to":"2026-10-19"}' result = client.call("meevo", "find_open_slots", {"location_id":"201","service_id":"9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d","from":"2026-10-18","to":"2026-10-19"}) const result = await cotlet.call('meevo', 'find_open_slots', {"location_id":"201","service_id":"9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d","from":"2026-10-18","to":"2026-10-19"}); cotlet call meevo find_open_slots --data '{"location_id":"201","service_id":"9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d","from":"2026-10-18","to":"2026-10-19"}' Example response
{
"slots": [
{
"start": "2026-10-17T10:00:00-04:00",
"staff": [
{
"staff_id": "e1d2c3b4-a5f6-4e7d-9c8b-7a6f5e4d3c2b",
"name": "Alex Rivera"
}
]
},
{
"start": "2026-10-17T11:30:00-04:00",
"staff": [
{
"staff_id": "a7b8c9d0-e1f2-4a3b-8c4d-9e0f1a2b3c4d",
"name": "Sam Patel"
}
]
}
]
} Find client
readPOST https://cotlet.dev/api/v1/meevo/find_client
Searches client profiles by name, email or phone and returns the matches with contact details and client type. Use client_id with get_client, book_appointment and sell_package. If several clients match, your agent should ask which one before it books.
Parameters
| Name | Type | Description |
|---|---|---|
| query required | string | Name, email or phone number. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/find_client \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"query"}' result = client.call("meevo", "find_client", {"query":"query"}) const result = await cotlet.call('meevo', 'find_client', {"query":"query"}); cotlet call meevo find_client --data '{"query":"query"}' Example response
{
"clients": [
{
"client_id": "c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60",
"name": "Jamie Doe",
"email": "client@example.com",
"phone": "+15555550123",
"client_type": "Regular"
}
]
} Get client
readPOST https://cotlet.dev/api/v1/meevo/get_client
Returns one client profile with upcoming appointments, visit notes, memberships, packages, gift cards and points. Use it before booking or selling, so your agent sees what the client already owns.
Parameters
| Name | Type | Description |
|---|---|---|
| client_id required | string | Client ID from find_client. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/get_client \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"client_id":"client_8c41d2"}' result = client.call("meevo", "get_client", {"client_id":"client_8c41d2"}) const result = await cotlet.call('meevo', 'get_client', {"client_id":"client_8c41d2"}); cotlet call meevo get_client --data '{"client_id":"client_8c41d2"}' Example response
{
"client_id": "c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60",
"name": "Jamie Doe",
"upcoming_appointments": [
{
"appointment_id": "4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9",
"start": "2026-10-12T09:00:00-04:00",
"services": [
"Balayage"
]
}
],
"visit_notes": [
{
"note_type": "Color formula",
"text": "Formula 7N plus 20 vol.",
"created_at": "2026-09-14T16:20:00-04:00"
}
],
"packages": [
{
"name": "5 Blowouts",
"visits_left": 2
}
],
"memberships": [],
"gift_cards": [],
"points": 120
} List packages
readPOST https://cotlet.dev/api/v1/meevo/list_packages
Lists the packages and memberships you sell at one location, with price and included services. kind narrows the list. Use package_id with sell_package.
Parameters
| Name | Type | Description |
|---|---|---|
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
| kind | enum | packages, memberships or all. Default: all. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/list_packages \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("meevo", "list_packages") const result = await cotlet.call('meevo', 'list_packages'); cotlet call meevo list_packages Example response
{
"packages": [
{
"package_id": "5f6a7b8c-9d0e-4f1a-8b2c-3d4e5f6a7b8c",
"kind": "package",
"name": "5 Blowouts",
"price": 200,
"includes": [
"Blowout x5"
]
}
]
} Get Register Summary
readPOST https://cotlet.dev/api/v1/meevo/get_register_summary
Returns the Register Summary of one location for one business day: sales by type, payments by method, membership sales, returns and deposits. Sales by type add up to total_sales, and payments add up to the same total. Reads one location per call.
Parameters
| Name | Type | Description |
|---|---|---|
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
| date required | date | Business day to read. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/get_register_summary \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"location_id":"201","date":"2026-10-10"}' result = client.call("meevo", "get_register_summary", {"location_id":"201","date":"2026-10-10"}) const result = await cotlet.call('meevo', 'get_register_summary', {"location_id":"201","date":"2026-10-10"}); cotlet call meevo get_register_summary --data '{"location_id":"201","date":"2026-10-10"}' Example response
{
"location_id": "201",
"date": "2026-10-10",
"currency": "USD",
"sales_by_type": {
"services": 2840,
"products": 410,
"packages": 600
},
"total_sales": 3850,
"payments": {
"card": 3120.5,
"cash": 500,
"gift_card": 229.5
},
"membership_sales": 0,
"returns": 0,
"deposits": 150
} POST https://cotlet.dev/api/v1/meevo/add_visit_note
Adds an internal visit note to a client profile, for example a color formula. The note is visible to staff, not to the client. note_type must be one set up at your location. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| client_id required | string | Client ID from find_client. |
| text required | string | Note text. |
| note_type | string | Visit note type as set up at your location. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/add_visit_note \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"client_id":"client_8c41d2","text":"text"}' result = client.call("meevo", "add_visit_note", {"client_id":"client_8c41d2","text":"text"}) const result = await cotlet.call('meevo', 'add_visit_note', {"client_id":"client_8c41d2","text":"text"}); cotlet call meevo add_visit_note --data '{"client_id":"client_8c41d2","text":"text"}' Example response
{
"note_id": "n_20311",
"client_id": "c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60",
"note_type": "Color formula",
"status": "saved"
} POST https://cotlet.dev/api/v1/meevo/book_appointment
Books one or more services in order for a client with one employee, starting at the time you give. Meevo sends your usual confirmation to the client. The call fails if the time is no longer free. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| client_id required | string | Client ID from find_client. |
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
| service_ids required | string[] | Service IDs from list_services, in order. |
| staff_id required | string | Employee performing the services. |
| start required | datetime | ISO 8601 with time zone. |
| note | string | Appointment note. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/book_appointment \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"client_id":"c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60","location_id":"201","service_ids":["9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"],"staff_id":"e1d2c3b4-a5f6-4e7d-9c8b-7a6f5e4d3c2b","start":"2026-10-17T10:00:00-04:00"}' result = client.call("meevo", "book_appointment", {"client_id":"c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60","location_id":"201","service_ids":["9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"],"staff_id":"e1d2c3b4-a5f6-4e7d-9c8b-7a6f5e4d3c2b","start":"2026-10-17T10:00:00-04:00"}) const result = await cotlet.call('meevo', 'book_appointment', {"client_id":"c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60","location_id":"201","service_ids":["9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"],"staff_id":"e1d2c3b4-a5f6-4e7d-9c8b-7a6f5e4d3c2b","start":"2026-10-17T10:00:00-04:00"}); cotlet call meevo book_appointment --data '{"client_id":"c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60","location_id":"201","service_ids":["9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"],"staff_id":"e1d2c3b4-a5f6-4e7d-9c8b-7a6f5e4d3c2b","start":"2026-10-17T10:00:00-04:00"}' Example response
{
"appointment_id": "4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9",
"status": "booked",
"client": {
"id": "c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60",
"name": "Jamie Doe",
"email": "client@example.com"
},
"services": [
{
"id": "9a8b7c6d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
"name": "Balayage",
"duration_minutes": 150,
"staff": "Alex Rivera"
}
],
"start": "2026-10-17T10:00:00-04:00",
"end": "2026-10-17T12:30:00-04:00",
"confirmation_status": "unconfirmed"
} POST https://cotlet.dev/api/v1/meevo/reschedule_appointment
Moves one appointment to a new start time, a new employee, or both. The services stay the same. Meevo sends your usual confirmation for the changed appointment. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| appointment_id required | string | Appointment ID from list_appointments. |
| start required | datetime | New start, ISO 8601 with time zone. |
| staff_id | string | New employee. Default: unchanged. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/reschedule_appointment \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"appointment_id":"4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9","start":"2026-10-16T09:00:00-04:00","staff_id":"a7b8c9d0-e1f2-4a3b-8c4d-9e0f1a2b3c4d"}' result = client.call("meevo", "reschedule_appointment", {"appointment_id":"4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9","start":"2026-10-16T09:00:00-04:00","staff_id":"a7b8c9d0-e1f2-4a3b-8c4d-9e0f1a2b3c4d"}) const result = await cotlet.call('meevo', 'reschedule_appointment', {"appointment_id":"4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9","start":"2026-10-16T09:00:00-04:00","staff_id":"a7b8c9d0-e1f2-4a3b-8c4d-9e0f1a2b3c4d"}); cotlet call meevo reschedule_appointment --data '{"appointment_id":"4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9","start":"2026-10-16T09:00:00-04:00","staff_id":"a7b8c9d0-e1f2-4a3b-8c4d-9e0f1a2b3c4d"}' Example response
{
"appointment_id": "4b5c6d7e-8f90-4a1b-b2c3-d4e5f6a7b8c9",
"status": "rescheduled",
"start": "2026-10-17T10:00:00-04:00",
"end": "2026-10-17T12:30:00-04:00",
"staff": "Sam Patel"
} POST https://cotlet.dev/api/v1/meevo/cancel_appointment
Cancels one appointment and records the reason you give. reason must be one set up at your location. Canceling affects the client's booking, so confirm it. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| appointment_id required | string | Appointment ID from list_appointments. |
| reason required | string | Cancellation reason as set up at your location. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/cancel_appointment \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"appointment_id":"appointment_8c41d2","reason":"reason"}' result = client.call("meevo", "cancel_appointment", {"appointment_id":"appointment_8c41d2","reason":"reason"}) const result = await cotlet.call('meevo', 'cancel_appointment', {"appointment_id":"appointment_8c41d2","reason":"reason"}); cotlet call meevo cancel_appointment --data '{"appointment_id":"appointment_8c41d2","reason":"reason"}' Example response
{
"appointment_id": "7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
"status": "canceled",
"reason": "Client request"
} POST https://cotlet.dev/api/v1/meevo/sell_package
Rings up one package for a client in the Register and records the payment. payment_type must match a payment type named in your Register. It moves money, so confirm it. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| client_id required | string | Client ID from find_client. |
| location_id | string | Location ID from list_locations. Default: the location you signed in to. |
| package_id required | string | Package ID from list_packages. |
| payment_type required | string | Payment type as named in your Register, e.g. Cash or Visa. |
Request
curl -X POST https://cotlet.dev/api/v1/meevo/sell_package \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"client_id":"client_8c41d2","package_id":"package_8c41d2","payment_type":"payment type"}' result = client.call("meevo", "sell_package", {"client_id":"client_8c41d2","package_id":"package_8c41d2","payment_type":"payment type"}) const result = await cotlet.call('meevo', 'sell_package', {"client_id":"client_8c41d2","package_id":"package_8c41d2","payment_type":"payment type"}); cotlet call meevo sell_package --data '{"client_id":"client_8c41d2","package_id":"package_8c41d2","payment_type":"payment type"}' Example response
{
"sale_id": "s_88421",
"status": "paid",
"client_id": "c3f1a2b4-5d6e-4f70-8a91-0b2c3d4e5f60",
"package": "5 Blowouts",
"amount": 200,
"payment_type": "Cash"
}