Platform & Partners
Integration Management
Platform admins can provision API keys, webhooks, and OAuth clients for any customer tenant under their platform.
The Platform Console (/admin/integrations) gives platform admins a single place to manage integration credentials for all customer tenants under their platform. The integrations section has three tabs: API Keys, Webhooks, and OAuth Apps.
Tenant picker
Above the tabs sits a Tenant picker — a dropdown listing every customer workspace under the platform admin's platform. The platform tenant itself is excluded; only the customer workspaces appear. Selecting a workspace switches all three tabs to show and manage that workspace's credentials.
permissions[] contains * (super admin) or platform:tenants:read (platform admin). Super admins see all tenants across all platforms; platform admins see only customer workspaces under their own platform.The selected tenant is persisted as a forTenant URL query parameter so switching tabs preserves the selection. When forTenant is absent from the URL, the first tenant in the list is auto-selected via router.replace (no browser history entry added).
API Keys
Platform admins can create, edit, and revoke API keys for any customer tenant. Keys are stored under the target tenant's tenantId and are immediately visible to that tenant's admins at /recruiter/integrations/api-keys.
Endpoints
| Method | Path | Required permission |
|---|---|---|
| GET | https://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keys | platform:tenants:read |
| POST | https://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keys | platform:tenants:manage |
| PATCH | https://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keys/:id | platform:tenants:manage |
| DELETE | https://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keys/:id | platform:tenants:manage |
Create an API key for a customer tenant
POST https://devapi.teamcast.ai/api/v2/admin/tenants/CUSTOMER_TENANT_ID/api-keys
Authorization: Bearer <platform_admin_token>
{
"name": "Liha ATS integration",
"permissions": [
"interview:create",
"interview:read",
"interview:approve",
"interview:update",
"candidate:read",
"recording:read",
"webhook:read"
]
}
# → {
# "id": "apk_...",
# "name": "Liha ATS integration",
# "key": "tc_live_...", ← shown once only
# "permissions": [...],
# "tenantId": "CUSTOMER_TENANT_ID",
# "createdAt": "2026-07-18T10:00:00.000Z"
# }Privilege rules
| Rule | Detail |
|---|---|
| No platform permissions in keys | platform:* keys can never be embedded in an API key. Enforced in both ApiKeyController and ApiKeyAdminController. |
| Self-serve escalation guard | Regular workspace users cannot grant a key more permissions than they hold themselves (ApiKeyController.create). |
| Admin bypass | When creating via the admin endpoint, the escalation guard is skipped. platform:tenants:manage + PlatformGuard are the sole authorization — platform admins grant any workspace-level permissions to a key. |
Webhooks
Each customer tenant can have one webhook config: a callback URL, a signing secret, a list of subscribed events, and an active flag. Platform admins can upsert or delete this config for any tenant under their platform.
Endpoints
| Method | Path | Required permission |
|---|---|---|
| GET | https://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/webhook-config | webhook:read |
| PUT | https://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/webhook-config | webhook:update |
| DELETE | https://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/webhook-config | webhook:update |
Configure a webhook for a customer tenant
PUT https://devapi.teamcast.ai/api/v2/admin/tenants/CUSTOMER_TENANT_ID/webhook-config
Authorization: Bearer <platform_admin_token>
{
"callback_url": "https://customer.example.com/webhooks/teamcast",
"secret": "a1b2c3...",
"events": [
"interview.plan_generated",
"interview.assessment_ready",
"interview.completed"
],
"is_active": true
}secret on the UI before saving (the Generate new secret button uses crypto.getRandomValues). Each save rotates the secret — the previous secret stops verifying immediately. Store it before saving.Subscribed events
| Event | When fired |
|---|---|
| interview.info_needed | Missing JD / candidate info required from recruiter |
| interview.info_completed | Missing info supplied |
| interview.plan_generated | Plan ready for HITL-1 review |
| interview.approved | Recruiter approved the plan |
| interview.rejected | Recruiter rejected the plan |
| interview.assessment_ready | Assessment completed, ready for HITL-2 review |
| interview.completed | Interview fully closed |
| interview.cancelled | Interview cancelled |
| interview.modification_requested | Modification requested on a completed interview |
coverage_summary only — never a score or hire/no-hire label. This is an EU AI Act compliance requirement.OAuth Clients
Platform admins can create OAuth 2.1 clients for customer tenants via the OAuth Apps tab. The audience determines which tier the client operates at.
| Audience | Use case |
|---|---|
| PLATFORM | Machine-to-machine operations through the A2A / LIHA gateway. Requires client_credentials grant. |
| TENANT | Workspace-level integrations (ATS, recruiter tools). Supports authorization_code + PKCE for recruiter-delegated access. |
GET /admin/oauth-clients endpoint with audience filtering. See the OAuth docs for the full authorization code and client credentials flows.Security: cross-tenant access control
All admin integration endpoints enforce a two-step authorization check:
PermissionsGuard+PlatformGuardat the controller class level: the caller must hold the required permission key, and their tenant must haveisPlatform = true.assertAccess(actor, tenantId)in each handler: allows the call if the target tenant is the caller's own platform tenant or if the target tenant'sparentPlatformId === actor.tenantId(Prisma lookup). Super admins (wildcard) pass unconditionally.
assertAccess check throws a 403 Forbidden for any tenantId not in their lineage.