Credentials — Connect Your Own Accounts
Some of the best things an assistant can do require your accounts: booking into your Semble diary, sending calls through your own Twilio account, using your own OpenAI key. Credentials are how you hand those over safely — values are stored encrypted in the platform's secret store, never returned by any read endpoint, and only used server-side when an integration needs them.
Credentials live at two levels:
- Account-level (recommended) — set once, used by every app in the account. This is the right home for partner-grade setups: your Twilio account, payment keys, model-provider keys you don't want to repeat per customer.
- App-level — for special cases where one app needs its own credential (a different Semble diary, a one-off key).
Resolution: when a call or message needs a credential, the platform resolves account-level credential first, then falls back to the platform default. Apps don't carry credentials in this model; the account does — use app-level only when an app genuinely differs.
Available to any signed-in caller. Returns the static catalog of
supported credential types (e.g. semble_api_key,
twilio_byot, openai_api_key) with the body
schema each type expects (Twilio = accountSid +
authToken; OpenAI = apiKey; etc.).
curl 'https://api.everycallhandled.com/api/v1/credentials/catalog' \
-H 'Authorization: Bearer YOUR_TOKEN'Requires view_credentials (and the account must be yours
or beneath yours). Returns metadata only — never the secret value.
curl 'https://api.everycallhandled.com/api/v1/merchants/{merchantId}/credentials' \
-H 'Authorization: Bearer YOUR_TOKEN'Requires edit_credentials. The PUT body shape depends on
the credential type — see the catalog above. DELETE is a hard delete of
the stored secret; it cannot be undone, and voice/SMS resolution falls
back to platform credentials immediately.
curl -X PUT 'https://api.everycallhandled.com/api/v1/merchants/{merchantId}/credentials/{name}' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"value":"sk_live_..."}'curl -X DELETE 'https://api.everycallhandled.com/api/v1/merchants/{merchantId}/credentials/{name}' \
-H 'Authorization: Bearer YOUR_TOKEN'Requires view_credentials. Metadata only — never the
secret value.
curl 'https://api.everycallhandled.com/api/v1/apps/{appId}/credentials' \
-H 'Authorization: Bearer YOUR_TOKEN'Requires edit_credentials. POST creates (or replaces by
name); PUT updates an existing credential's value.
The value goes into the encrypted secret store; only the credential's name and type are kept on the app.
curl -X PUT 'https://api.everycallhandled.com/api/v1/apps/{appId}/credentials/{name}' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"value":"sk_live_..."}'curl -X POST https://api.everycallhandled.com/api/v1/apps/$APP_ID/credentials \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "name": "semble-main", "type": "semble_api_key", "value": "sk_live_..." }'Requires view_credentials. Pings the upstream API with
the stored credential — the quickest way to confirm a key works before a
caller finds out it doesn't.
Response (200):
{ "ok": true|false, "detail": "..." }
curl -X POST 'https://api.everycallhandled.com/api/v1/apps/{appId}/credentials/{name}/test' \
-H 'Authorization: Bearer YOUR_TOKEN'Requires edit_credentials. Hard delete; cannot be
undone.
curl -X DELETE 'https://api.everycallhandled.com/api/v1/apps/{appId}/credentials/{name}' \
-H 'Authorization: Bearer YOUR_TOKEN'