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.

The picker is visible to any user whose 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

MethodPathRequired permission
GEThttps://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keysplatform:tenants:read
POSThttps://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keysplatform:tenants:manage
PATCHhttps://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keys/:idplatform:tenants:manage
DELETEhttps://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/api-keys/:idplatform:tenants:manage

Create an API key for a customer tenant

bash
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"
#   }
The raw key is returned only on creation. It is stored as a bcrypt hash server-side and cannot be retrieved again. Provide it to the customer immediately.

Privilege rules

RuleDetail
No platform permissions in keysplatform:* keys can never be embedded in an API key. Enforced in both ApiKeyController and ApiKeyAdminController.
Self-serve escalation guardRegular workspace users cannot grant a key more permissions than they hold themselves (ApiKeyController.create).
Admin bypassWhen 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

MethodPathRequired permission
GEThttps://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/webhook-configwebhook:read
PUThttps://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/webhook-configwebhook:update
DELETEhttps://devapi.teamcast.ai/api/v2/admin/tenants/:tenantId/webhook-configwebhook:update

Configure a webhook for a customer tenant

bash
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
}
Generate a fresh 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

EventWhen fired
interview.info_neededMissing JD / candidate info required from recruiter
interview.info_completedMissing info supplied
interview.plan_generatedPlan ready for HITL-1 review
interview.approvedRecruiter approved the plan
interview.rejectedRecruiter rejected the plan
interview.assessment_readyAssessment completed, ready for HITL-2 review
interview.completedInterview fully closed
interview.cancelledInterview cancelled
interview.modification_requestedModification requested on a completed interview
Payloads carry 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.

AudienceUse case
PLATFORMMachine-to-machine operations through the A2A / LIHA gateway. Requires client_credentials grant.
TENANTWorkspace-level integrations (ATS, recruiter tools). Supports authorization_code + PKCE for recruiter-delegated access.
OAuth client management for platform admins uses the existing 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:

  1. PermissionsGuard + PlatformGuard at the controller class level: the caller must hold the required permission key, and their tenant must have isPlatform = true.
  2. 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's parentPlatformId === actor.tenantId (Prisma lookup). Super admins (wildcard) pass unconditionally.
A platform admin from Platform A cannot read or write credentials for a customer workspace that belongs to Platform B — even if they guess the tenantId. The assertAccess check throws a 403 Forbidden for any tenantId not in their lineage.
Was this page helpful?