Five concepts explain everything in the Partner API.
Partners & API keys
A partner app represents your organization on our platform. Apps are created by the GrowDental team (invite-only) and hold your contact details, BAA status, and webhook endpoints.
Each app has one or more API keys:
- Format:
gd_live_... — a prefix plus a 43-character random secret (~256 bits of entropy).
- Shown once at creation; we store only a SHA-256 hash, so a lost key can never be recovered — only replaced.
- Each key carries scopes (e.g.
calls:read, call-requests:write) that bound what it can do.
- Keys are rate limited individually: 600 requests/minute by default, 60/minute for bulk writes.
Kill switches exist at four granularities — app suspended, key revoked, practice grant revoked, webhook endpoint disabled — so access can be narrowed without tearing everything down.
Practices & grants
A practice is a dental office using GrowDental’s voice agents. Your app never sees all practices — it sees exactly the practices we have granted to it, typically the ones you share a business relationship with.
GET /practices lists your granted practices (id, name, slug, timezone, status, vertical). A grant can narrow your key’s scopes per practice, so a scope your key holds may still be refused for a specific practice.
- Every practice-scoped request is validated against your grants. Practices you have not been granted return 404, not 403 — practice IDs cannot be probed.
The grant is the tenancy boundary of the whole API: key → app → granted practices, checked on every request.
Calls & outcomes
A call is one phone conversation between a practice’s voice agent and a person — inbound or outbound. After every call, post-call processing classifies an outcome (e.g. appointment_booked, callback_requested, voicemail, no_answer) and writes a natural-language summary.
GET /practices/{practiceId}/calls lists calls; GET /calls/{callId} returns one call.
- Transcripts are PHI: the
transcript field is populated only with the transcripts:read scope and a signed BAA.
- Recordings are PHI too:
GET /calls/{callId}/recording (scope recordings:read + BAA) responds with a 302 redirect to a short-lived signed URL. Raw storage URLs are never exposed — follow the redirect immediately and re-request when you need the audio again.
Call requests
A call request is how you trigger outbound calling: POST /practices/{practiceId}/call-requests with 1–50 contacts, a purpose, optional free-text context, and an optional calling window.
The platform dialer takes it from there — practice-local calling hours, retry ladders, and concurrency caps all apply automatically. You influence what the agent says only through purpose and context; prompts and agent internals are not exposed.
Each contact progresses pending → calling → completed | failed (or skipped), and completed contacts link to the resulting call via call_id. Track progress by polling GET /call-requests/{callRequestId} or by subscribing to the call_request.completed event.
Always send an Idempotency-Key header when creating call requests. A blind
network retry without one can dial patients twice.
Webhooks & events
Instead of polling, register webhook endpoints (POST /webhook-endpoints) to receive events:
| Event | Fired when |
|---|
call.completed | A call finishes and its outcome is classified |
call.recording.ready | A call’s recording is processed and fetchable |
call_request.completed | Every contact in one of your call requests is terminal |
Delivery semantics, in one breath: at-least-once, unordered, signed, PHI-minimal.
- Every delivery carries an
X-GrowDental-Signature header (t=<unix>,v1=<HMAC-SHA256>) — verify it before trusting the payload.
- Retries use exponential backoff; endpoints that keep failing are auto-disabled until you re-enable them.
- De-duplicate on the
X-GrowDental-Delivery-Id header.
- Payloads contain IDs, outcomes, and API links — never transcripts, recordings, or patient details. PHI moves only over authenticated API pulls.
Coming later
Phase 2 adds patient intake (batch push of patients, appointments, and treatments through canonical schemas — drafts already in the API Reference) and segment/queue read-back. A partner-facing scheduling contract for mid-call booking into your system is planned behind that. These docs will grow as each phase ships; see the Changelog.