Skip to main content
Every request to the Partner API is authenticated with your API key as a Bearer token:
curl https://voice.growdental.ai/api/partner/v1/practices \
  -H "Authorization: Bearer gd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
There are no cookies, sessions, or OAuth flows — one header, every request, always over HTTPS.

Key format

gd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
└┬┘ └┬─┘ └──────────────────┬────────────────────┘
 │   │                      └ 43-char base62 secret (~256 bits)
 │   └ environment (live; test reserved for a future sandbox)
 └ GrowDental prefix
  • Keys are issued by the GrowDental team and shown exactly once at creation. We store only a SHA-256 hash — a lost key cannot be recovered, only replaced.
  • Store keys in a secret manager. Never commit them, log them, or ship them to browsers or mobile apps; all calls should come from your servers.
  • Only live keys are issued today. The gd_test_ prefix is reserved for a future sandbox environment.

Scopes

Each key carries a set of scopes. Requests that need a scope your key lacks fail with 403 insufficient_scope. Practice grants can further narrow scopes per practice — a request that clears your key’s scopes can still be refused for a practice whose grant does not include that scope.
ScopeGrantsPHI
practices:readList granted practices
calls:readCall outcomes, durations, summaries
transcripts:readCall transcriptsYes
recordings:readCall recording audioYes
call-requests:writeCreate and read your call requests
webhooks:manageWebhook endpoint CRUD
intake:writeBatch patient/appointment/treatment push (Phase 2)Yes
scheduling:manageMid-call scheduling integration (Phase 3)
Ask for the narrowest scope set that covers your integration — adding a scope later is a quick, non-breaking change on our side.

The BAA gate

Scopes marked PHI above are hard-gated in code, not just in paperwork: until a Business Associate Agreement is executed for your app, any request using them returns:
{
  "error": "baa_required",
  "message": "The scope recordings:read exposes PHI and requires a signed BAA. Contact support to complete your BAA."
}
Everything else (outcomes, summaries, call triggering, webhooks) works without a BAA, so you can build and test most of an integration while the agreement is in flight. Contact partners@growdental.ai to start the BAA process.

Key rotation

Rotation is a coordinated, zero-downtime handoff:
1

Request a new key

Email us (or use your admin contact) to issue a second key with the same scopes. Both keys work simultaneously — there is no forced cutover.
2

Deploy the new key

Roll the new key out through your secret manager and verify traffic succeeds with it (watch for 401s).
3

Revoke the old key

Tell us to revoke the old key. Revocation is immediate; revoked keys get 401 key_revoked on every request.
Rotate immediately if a key may have been exposed (committed to a repo, printed in logs, shared over an insecure channel). We also track lastUsedAt per key and may flag long-unused keys for cleanup.

Authentication errors

Statuserror codeMeaning
401missing_authorizationNo or malformed Authorization: Bearer ... header
401invalid_api_keyKey is unknown (check for truncation/whitespace)
401key_revokedKey was revoked — switch to your current key
403app_suspendedYour partner app is suspended — contact us
403insufficient_scopeKey lacks the required scope
403baa_requiredPHI scope used without a signed BAA
404not_foundResource missing or practice not granted to your app (deliberately indistinguishable)

Rate limits

Limits are per key, per minute, on a fixed window:
  • 600 requests/minute for most endpoints.
  • 60 requests/minute for bulk writes (call-request creation) — a separate budget, so bulk traffic never starves your reads.
Exceeding a limit returns 429 rate_limited with a Retry-After header (seconds). Back off for at least that long; requests sent while limited still count against the window.