API Reference

Authentication

Three credential types resolve to one unified principal, checked against RBAC permission keys on every route.

MethodHeaderTypical caller
Integration API keyX-API-Key: sk_live_<64 hex>Server-to-server ATS/HRIS integration
OAuth 2.1 access tokenAuthorization: Bearer <RS256 JWT>Partner apps acting on behalf of a recruiter
User session JWTAuthorization: Bearer <HS256 JWT>The recruiter dashboard itself

API keys

Keys are issued in the format sk_live_<64 hex> from POST /api-keys and shown exactly once — only a hash is stored server-side. Each key carries an explicit permission list (least-privilege by default), an optional expiry, and an optional IP allowlist.

Platform keys (owned by a platform tenant) must also send X-Tenant-ID to select which customer tenant the request applies to — validated to belong to that platform on every request, so a platform key can never reach another platform's tenants. Tenant-owned keys omit X-Tenant-ID; their own tenant is implicit.

bash
curl https://devapi.teamcast.ai/api/v2/integration/interviews/run_1735689600_a1f9c2 \
  -H "X-API-Key: sk_live_5f2c9a1b..." \
  -H "X-Tenant-ID: tnt_8a21b6"

Optional HMAC request signing

Keys can opt in to request signing (enableSigning at creation, returning a signingSecret). When enabled, every request must include:

HeaderValue
X-TimestampUnix seconds, must be within ±5 minutes of server time
X-Signaturesha256=<hex HMAC-SHA256> over the canonical string below
text
canonical_string = METHOD + "\n" + PATH_WITH_QUERY + "\n" + TIMESTAMP + "\n" + SHA256(raw_body)

# Example — POST /integration/interviews with no query string:
POST
/integration/interviews
1735689600
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85

The query string is included in the signed path (unlike some implementations that sign the path only) — sign the exact request you send, including any query parameters.

Permissions

Every route declares the permission key it needs; the composite guard resolves your credential to a principal ({ type, tenantId, userId?, clientId?, scopes?, permissions? }) before the permission check runs.

PermissionGrants
interview:createCreate interview runs
interview:readRead interview status and rankings
interview:updateSubmit missing candidate info
interview:approveApprove/reject/revise plans and assessments
interview:deleteCancel a run or purge candidate data
apikey:create / read / deleteManage your own API keys
webhook:read / updateManage your webhook configuration
X-Tenant-ID selects a tenant for platform keys; it never grants access to a tenant your key isn't authorized for. Every lookup by runId is additionally scoped by the resolved tenantId — a cross-tenant runId always 404s rather than leaking existence.
Was this page helpful?