Developers
Errors
Every code the API answers with, what it means, and what to do.
Every error is one envelope. The code is the contract: stable, and what your software branches on to choose its own words for the client. The message is for the developer and may be reworded.
{ "error": { "type": "conflict", "code": "slot_unavailable",
"message": "That time is no longer available.",
"param": "starts_at", "details": {},
"request_id": "0b9f6c1e-…",
"doc_url": "https://www.daobook.com.au/developers/errors#slot_unavailable" } }
400 invalid_request
The request is malformed: a bug in the integration.
| Code | Message | What to do |
|---|---|---|
| invalid_json | The request body is not valid JSON. | Send a JSON body with Content-Type: application/json. |
| missing_parameter | A required parameter is missing. | Add the parameter named in param. |
| unknown_parameter | The request carries a parameter this endpoint does not take. | Remove the parameter named in param, or check its spelling against the reference. |
| invalid_parameter | A parameter has a value this endpoint cannot use. | Check the value of the parameter named in param against the reference. |
| invalid_timestamp | A time must be an RFC 3339 instant with a UTC offset, such as 2026-11-03T10:00:00+11:00. | Send times as RFC 3339 instants with an offset, such as 2026-11-03T10:00:00+11:00. |
| idempotency_key_required | This request creates something, so it needs an Idempotency-Key header. | Add an Idempotency-Key header: a new one for each distinct booking, the same one for a retry. |
401 authentication
No key, or not a live one.
| Code | Message | What to do |
|---|---|---|
| invalid_api_key | The request has no live API key. Send one as Authorization: Bearer dbk_live_… | Check the key is sent as Authorization: Bearer and has not been revoked or expired. The account owner can make a new one in Settings → Integrations → Developer API. |
403 permission
A live key that may not do this.
| Code | Message | What to do |
|---|---|---|
| api_not_enabled | The Daobook API is not enabled for this account. | Daobook has switched the API off for this business. Write to admin@daobook.com.au. |
| account_inactive | This account is not active. | The business's Daobook subscription is not active. The account owner can see why in Daobook. |
| insufficient_scope | This key does not hold the scope this endpoint needs. | The key lacks the scope in details.required_scope. The account owner makes a key that holds it. |
404 not_found
No such thing, or not this key's to see. The API never confirms that something exists.
| Code | Message | What to do |
|---|---|---|
| not_found | No such resource. | The id is wrong, belongs to another business, is outside the key's locations, or the record is gone. Nothing to retry. |
| verification_failed | No patient matches those details. | The details did not match exactly one patient, and the answer never says which one was wrong. Ask the caller once more, then offer a callback or a new booking. |
409 conflict
Something changed; choose again.
| Code | Message | What to do |
|---|---|---|
| request_in_progress | A request with this Idempotency-Key is still running. | An earlier request with this Idempotency-Key is still running. Wait a moment, then retry with the same key and body to receive its answer. |
| slot_unavailable | That time is no longer available. | Read availability again and let the client choose another time. |
| duplicate_client | A client with these details is already on file; details.client is the match and details.matched_on says what agreed. | Use the client in details.client, or send on_duplicate=return to have the match answered as the client instead of a refusal. |
422 refused
Well-formed, but a rule of the clinic says no.
| Code | Message | What to do |
|---|---|---|
| idempotency_key_reused | This Idempotency-Key was already used with a different request body. | This Idempotency-Key was used with a different body. Use a new key for a new booking. |
| not_bookable | That appointment type, practitioner or location is not offered for online booking. | The location, practitioner or appointment type is not offered for online booking. Read locations, practitioners and appointment types again; the clinic may have changed its settings. |
| client_details_required | The clinic's booking form requires client details this request does not carry. | Collect the fields in details.missing from the client; the location's required_client_fields lists them. |
| terms_required | The clinic requires the client's acceptance of its terms. | Show the client the location's terms or privacy policy text and send consents with accepted: true and the version shown. |
| terms_outdated | The clinic has changed its terms since the version the client accepted. | The clinic has changed the text. Show the client the current version (details.current_version, from GET /locations/{id}) and send that version. |
| payment_required | This appointment type takes a deposit or a card hold at booking, which the API does not handle. Send the client to the booking page. | The appointment type takes a deposit or a card hold at booking, which the API does not handle. Send the client to details.booking_page_url. |
| cancellation_not_allowed | The clinic's rules do not allow the client to cancel this appointment. | The clinic's rules do not allow a client's cancellation now; details.outcome says what the clinic offers instead. Show the client the clinic's phone number or booking page. |
| reschedule_not_allowed | The clinic's rules do not allow the client to move this appointment. | The clinic's rules do not allow a client's reschedule now; details.outcome says what a cancel would do instead (cancel, late_cancel or call). Offer that, or the clinic's phone number. |
| entry_closed | This waiting list entry is already booked, so it cannot be removed. | The waiting list entry is already booked, so there is nothing to remove. Read it with GET /waiting_list_entries/{id}; its status is booked. |
| confirmation_not_allowed | This appointment cannot be confirmed: it is not scheduled, or it has already started. | The booking is no longer scheduled, or it has started. Read it with GET /appointments/{id} and tell the client where it stands. |
| client_archived | This client is archived. Restore them in Daobook before changing their details. | Ask the clinic to restore the client from their profile, or read them with GET /clients/{id}; their status is archived. |
429 rate_limited
Too many requests.
| Code | Message | What to do |
|---|---|---|
| rate_limited | Too many requests. Wait for the number of seconds in Retry-After and try again. | Wait the seconds in Retry-After, then continue. The limit is 200 requests a minute per key, of which 30 may be writes. |
| too_many_attempts | Too many failed caller checks for this number, name or key. Wait for the number of seconds in Retry-After and offer a callback. | Five checks have failed for this number or name in the hour, or fifty for the key. Offer the caller a callback, and check again after the seconds in Retry-After. |
500 server
Our fault. Retry with the same Idempotency-Key.
| Code | Message | What to do |
|---|---|---|
| internal_error | Something went wrong on our side. Retry with the same Idempotency-Key, and quote the request_id if it persists. | Retry with the same Idempotency-Key. If it persists, write to admin@daobook.com.au with the request_id. |
503 server
Our fault. Retry with the same Idempotency-Key.
| Code | Message | What to do |
|---|---|---|
| temporarily_unavailable | The service is briefly unavailable. Retry with the same Idempotency-Key. | Retry with the same Idempotency-Key after a short wait. |