Platform Admin

Platform Setup

Step-by-step guide for SuperAdmins to bootstrap the system, create a Platform, and issue API keys.

This guide is for Teamcast SuperAdmins provisioning a new integration partner. By the end you will have a Platform, at least one Tenant under it, and a working API key ready for the partner to call the Integration API.

All SuperAdmin endpoints require a JWT obtained from POST /api/v1/super-admin/auth/login. This is a separate login from the tenant admin login — use the dedicated /super-admin/login page.

Step 0 — Bootstrap the First SuperAdmin

This endpoint is only available once. It is permanently disabled after the first SuperAdmin account is created.

bash
curl -X POST https://mayaapi.teamcast.ai/api/v1/super-admin/auth/bootstrap \
  -H "Content-Type: application/json" \
  -d '{
    "email": "superadmin@teamcast.ai",
    "password": "<your_password>",
    "name": "Teamcast Admin"
  }'
Response 201
{
  "id": "uuid",
  "email": "superadmin@teamcast.ai",
  "name": "Teamcast Admin",
  "status": "ACTIVE",
  "createdAt": "2026-03-20T10:00:00.000Z"
}
After bootstrap completes, this endpoint returns 403 Forbidden on all future calls. To add more SuperAdmin accounts, use POST /api/v1/super-admin while authenticated.

Step 1 — Authenticate as SuperAdmin

bash
curl -X POST https://mayaapi.teamcast.ai/api/v1/super-admin/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "superadmin@teamcast.ai",
    "password": "<your_password>"
  }'
Response 200
{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "expiresIn": 3600,
  "user": {
    "id": "uuid",
    "email": "superadmin@teamcast.ai",
    "type": "super-admin"
  }
}

Include this token as Authorization: Bearer <accessToken> on all subsequent SuperAdmin requests.

Step 2 — Create a Platform

A Platform represents an integration partner or enterprise cluster. Every Tenant must belong to exactly one Platform.

FieldTypeRequiredConstraints
namestringYesMax 100 characters. Human-readable label.
domainstringYesValid domain name, globally unique. E.g. linkedin.com
settingsobjectNoFree-form JSON for partner metadata (contactEmail, region, etc.)
allowedPermissionsstring[]NoPermission ceiling for this platform. API keys issued under this platform may only use a subset of these. Defaults to the standard Integration API set if omitted (see table below).
bash
curl -X POST https://mayaapi.teamcast.ai/api/v1/super-admin/platforms \
  -H "Authorization: Bearer <superadmin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "LinkedIn",
    "domain": "linkedin.com",
    "settings": {
      "contactEmail": "api-team@linkedin.com",
      "region": "us-east"
    }
  }'
Response 201
{
  "id": "c2650bb0-49b5-438a-b4d0-f9049ccb9f8a",
  "name": "LinkedIn",
  "domain": "linkedin.com",
  "status": "ACTIVE",
  "settings": { "contactEmail": "api-team@linkedin.com", "region": "us-east" },
  "allowedPermissions": ["interview:create", "interview:read", "interview:update", "interview:approve", "interview:delete", "tenant:read", "user:create", "user:read", "user:update", "user:delete", "webhook:read", "webhook:update"],
  "createdAt": "2026-03-20T10:05:00.000Z"
}
Save the returned id — this is your PLATFORM_ID used in all subsequent calls. The allowedPermissions array is the ceiling — no API key issued to this platform can have permissions outside this set.

Step 3 — Issue a Platform API Key

Platform API keys let the partner backend call Integration API endpoints on behalf of any of their tenants. The caller must include X-Tenant-ID on every request to identify which tenant the action applies to. Each key's permissions must be a subset of the platform's allowedPermissions.

FieldTypeRequiredDescription
namestringYesHuman-readable label (e.g. "LinkedIn Production Key")
permissionsstring[]YesList of permission strings. Must be a subset of the platform's allowedPermissions.
expiresAtISO 8601 stringNoKey expiry date. Omit for no expiry.
PermissionScopeAllows
interview:createInterviewPOST /integration/interviews
interview:readInterviewGET /integration/interviews/:runId and /integration/rankings
interview:updateInterviewPATCH /integration/interviews/:runId/info and /plan/revise
interview:approveInterviewPOST /integration/interviews/:runId/plan/approve|reject and /assessment/approve|reject
interview:deleteInterviewDELETE /integration/interviews/:runId and /candidate-data
tenant:createTenant mgmtPOST /platform-admin/tenants
tenant:readTenant mgmtGET /tenants and /tenants/:id
tenant:updateTenant mgmtPUT /platform-admin/tenants/:id
tenant:deleteTenant mgmtDELETE /platform-admin/tenants/:id
user:createUser mgmtPOST /users
user:readUser mgmtGET /users and /users/:id
user:updateUser mgmtPUT /users/:id
user:deleteUser mgmtDELETE /users/:id
apikey:createAPI key mgmtPOST /platform-admin/api-keys
apikey:readAPI key mgmtGET /platform-admin/api-keys
apikey:deleteAPI key mgmtDELETE /platform-admin/api-keys/:id
webhook:readWebhookGET /platform-admin/webhook-config, GET /tenants/:id/webhook-config
webhook:updateWebhookPUT /platform-admin/webhook-config, PATCH /platform-admin/webhook-config/{activate,deactivate}, PUT /tenants/:id/webhook-config
bash
curl -X POST https://mayaapi.teamcast.ai/api/v1/super-admin/platforms/c2650bb0-49b5-438a-b4d0-f9049ccb9f8a/api-keys \
  -H "Authorization: Bearer <superadmin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "LinkedIn Production Key",
    "permissions": [
      "interview:create",
      "interview:read",
      "interview:update",
      "interview:approve",
      "interview:delete"
    ]
  }'
Response 201
{
  "id": "key-uuid",
  "name": "LinkedIn Production Key",
  "key": "sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "permissions": ["interview:create", "interview:read", "interview:update", "interview:approve", "interview:delete"],
  "platformId": "c2650bb0-49b5-438a-b4d0-f9049ccb9f8a",
  "createdAt": "2026-03-20T10:10:00.000Z"
}
The raw key value is returned only once. Store it in a secrets manager immediately. There is no way to retrieve it again — you must revoke and reissue if lost.

Platform Management

bash
curl https://mayaapi.teamcast.ai/api/v1/super-admin/platforms \
  -H "Authorization: Bearer <superadmin_token>"

Adding More SuperAdmins

bash
curl -X POST https://mayaapi.teamcast.ai/api/v1/super-admin \
  -H "Authorization: Bearer <superadmin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "another@teamcast.ai",
    "password": "<your_password>",
    "name": "Second Admin"
  }'

Permission Ceiling Model

Every platform has an allowedPermissions ceiling set by Teamcast SuperAdmin at platform creation time. This is the maximum set of permissions any API key issued under that platform can hold.

The enforcement happens at two points:

WhereWhat is checked
Key issuance (POST /api-keys)Requested permissions must be a subset of platform.allowedPermissions — 400 if any exceed the ceiling
Every API call (runtime)Guard re-reads platform.allowedPermissions and rejects keys whose permissions have been narrowed since issuance — no restart required
To grant a platform new permissions (e.g. tenant:create), first update allowedPermissions on the platform via PATCH /api/v1/super-admin/platforms/{id}, then issue a new API key with those permissions. Existing keys are not automatically upgraded.
Narrowing a platform's allowedPermissions takes effect immediately for all existing keys under that platform — no key rotation required.

Setup Checklist

StepEndpointStatus
Bootstrap first SuperAdminPOST /super-admin/auth/bootstrapOne-time
SuperAdmin loginPOST /super-admin/auth/loginRecurring
Create Platform with allowedPermissionsPOST /super-admin/platformsPer partner
Issue Platform API key (subset of ceiling)POST /super-admin/platforms/{id}/api-keysPer environment
Configure Platform webhookPUT /platform-admin/webhook-configOnce per platform (covers all tenants)
Create first TenantPOST /tenants (with SA token)Per customer
Configure Tenant webhook (optional override)PUT /tenants/{id}/webhook-configOnly if tenant needs a different endpoint
Verify healthGET /api/v1/health/readyBefore go-live
Was this page helpful?