Get booking configuration
curl --request GET \
--url https://deepcontext.app/api/public/tenants/{slug}const options = {method: 'GET'};
fetch('https://deepcontext.app/api/public/tenants/{slug}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"business_name": "<string>",
"branding": {},
"timezone": "<string>",
"services": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"duration_minutes": 123,
"price_cents": 0,
"form_fields": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "text",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"required": true,
"placeholder": "<string>",
"help_text": "<string>",
"min": 123,
"max": 123
}
]
}
],
"sms_consent_enabled": true
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}API reference
Get booking configuration
Services, their questions, branding, and the tenant timezone.
GET
/
api
/
public
/
tenants
/
{slug}
Get booking configuration
curl --request GET \
--url https://deepcontext.app/api/public/tenants/{slug}const options = {method: 'GET'};
fetch('https://deepcontext.app/api/public/tenants/{slug}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"business_name": "<string>",
"branding": {},
"timezone": "<string>",
"services": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"duration_minutes": 123,
"price_cents": 0,
"form_fields": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "text",
"options": [
{
"value": "<string>",
"label": "<string>"
}
],
"required": true,
"placeholder": "<string>",
"help_text": "<string>",
"min": 123,
"max": 123
}
]
}
],
"sms_consent_enabled": true
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}Everything needed to render the form. Call it once when the page loads.
Questions live inside each service
form_fields is a property of a service, not of the tenant, and there is deliberately
no top-level mirror — a mirror is how the two lists drift and the form starts asking the
wrong thing. If the customer switches service, re-render from the new service’s list.
See Questions in the guide for the per-type validation rules and a
client-side normalizer that matches the server.
Things that will catch you out
price_centscan benulland carries no currency.nullmeans the tenant doesn’t publish a price for that service — render nothing, not “$0”.sms_consent_enabledis a tenant-level capability, not a prompt. It istrueonly when the tenant has a phone line that is both active and A2P/10DLC registered — the same bar the send path applies, sotruemeans a text can really be delivered. Render the consent checkbox only when it istrue. Leave it unticked, and label it as what the customer is asking for, above the compliance disclosure. It is a TCPA consent record: never pre-tick it. Scope the label to the appointment, not to one message — our hosted page says “Text me about this appointment” rather than “…a confirmation”, because reminders are the obvious next transactional message and you cannot go back and re-consent people. The disclosure’s “Message frequency may vary” is what covers that.- Only active services appear. Combined with the 5-minute shared cache, a service
deactivated moments ago can still be listed here and then fail the submit with
400 invalid_service. Treat that error as “reload the config”, not as a bug. - A question that was soft-deleted while still attached is silently skipped, not an error. The booking page stays up; the missing question is only visible in our logs.
Path Parameters
The tenant's public booking slug. Issued by DPC; there is no discovery endpoint.