API Reference
The DiveDesk REST API — read-only v1. Connect your shop's website, CRM, or reporting tools to your DiveDesk data.
Authentication
Every request needs a per-shop API key sent as a bearer token. Keys are issued by DiveDesk — ask your DiveDesk contact (hello@divedesk.io) to issue a key for your shop. The full key is shown once at creation and only a hash is stored, so a lost key is revoked and re-issued, never recovered. The key alone identifies the shop: there is no shop id in the URL, and a key can only ever read its own shop's data.
curl https://divedesk.io/api/v1/ping \ -H "Authorization: Bearer dd_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Base URL: https://divedesk.io/api/v1. Requests are limited to 120/minute per key; over-limit calls get a 429. Keys stop working immediately when revoked, and while a shop is suspended or churned every call returns 403.
Errors
Errors are JSON with a single error string. 401 = missing, malformed, or revoked key · 403 = shop not active · 429 = rate limited · 500 = something broke on our side.
{ "error": "Invalid or revoked API key" }GET /ping
Connectivity and auth check. Returns the shop the key belongs to.
curl "https://divedesk.io/api/v1/ping" -H "Authorization: Bearer dd_live_…"
Response
{
"ok": true,
"shop": "coastal-dive-co",
"shopName": "Coastal Dive Co",
"keyName": "Website integration"
}GET /shop
The authenticated shop's profile.
curl "https://divedesk.io/api/v1/shop" -H "Authorization: Bearer dd_live_…"
Response
{
"slug": "coastal-dive-co",
"name": "Coastal Dive Co",
"status": "active",
"plan": "starter",
"timezone": "America/Chicago",
"domain": "coastal-dive-co.divedesk.io",
"createdAt": "2026-08-01T14:00:00.000Z"
}GET /students
Contacts/students, newest first. Contact fields only — never medical or waiver data.
Query parameters
- page — 1-based page (default 1)
- limit — per page, max 100 (default 25)
- search — matches email, full name, or phone
curl "https://divedesk.io/api/v1/students" -H "Authorization: Bearer dd_live_…"
Response
{
"page": 1,
"totalPages": 4,
"totalDocs": 87,
"docs": [
{
"id": 123,
"firstName": "Jane",
"lastName": "Diver",
"fullName": "Jane Diver",
"email": "jane@example.com",
"phone": "512-555-0100",
"createdAt": "2026-07-14T18:22:00.000Z",
"updatedAt": "2026-08-02T09:10:00.000Z"
}
]
}GET /orders
Orders with line items, newest first. Relationships are returned as bare ids.
Query parameters
- page — 1-based page (default 1)
- limit — per page, max 100 (default 25)
- status — filter by order status (e.g. paid)
curl "https://divedesk.io/api/v1/orders" -H "Authorization: Bearer dd_live_…"
Response
{
"page": 1,
"totalPages": 12,
"totalDocs": 288,
"docs": [
{
"id": 456,
"orderNumber": "TSA-1042",
"status": "paid",
"channel": "pos",
"subtotal": 499,
"tax": 41.17,
"total": 540.17,
"paidAt": "2026-08-20T16:03:00.000Z",
"studentId": 123,
"items": [
{ "type": "course", "name": "Open Water Diver", "quantity": 1, "unitPrice": 499, "total": 499, "variantSku": null }
],
"createdAt": "2026-08-20T16:02:40.000Z",
"updatedAt": "2026-08-20T16:03:05.000Z"
}
]
}GET /classes
Scheduled classes with their days.
Query parameters
- page — 1-based page (default 1)
- limit — per page, max 100 (default 25)
- upcoming — true = only classes with a future day, excluding cancelled
curl "https://divedesk.io/api/v1/classes" -H "Authorization: Bearer dd_live_…"
Response
{
"page": 1,
"totalPages": 2,
"totalDocs": 31,
"docs": [
{
"id": 789,
"title": "Lake Travis — Sept 12 & 13",
"capacity": 6,
"cancelled": false,
"publicDescription": "Open water dives, both lake days.",
"days": [
{ "date": "2026-09-12T13:00:00.000Z", "type": "lake", "label": "Lake Day 1", "showUpTime": "7:30 AM" }
],
"createdAt": "2026-08-15T12:00:00.000Z"
}
]
}Webhooks & write access
v1 is read-only by design — writes (creating orders, enrolling students) and outbound webhooks are on the roadmap. Inbound vendor webhooks (Stripe, Quo) are separate, signature-verified endpoints and don't use API keys.
Questions, or need a key for your shop? Email hello@divedesk.io.