API Reference
Interviews
Create and manage interview records — CRUD endpoints with multi-tenant isolation.
Interview endpoints handle the full lifecycle of an interview record: creation, retrieval, status updates, plan management, and assessment access. All endpoints support both JWT authentication and API Key + X-Tenant-ID header authentication, and automatically scope results to the caller's tenant.
Endpoints
| Method | Endpoint | Permission | Description |
|---|---|---|---|
| POST | /interviews/parse-resume | interview:create | Extract structured text from a resume file (PDF, DOCX, TXT) |
| GET | /interviews/counts | interview:read | Get interview counts grouped by status |
| POST | /interviews | interview:create | Create interview directly (admin UI) |
| GET | /interviews | interview:read | List interviews with search, status filter, and pagination |
| GET | /interviews/:id | interview:read | Get single interview |
| PUT | /interviews/:id | interview:update | Update interview fields |
| DELETE | /interviews/:id | interview:delete | Delete interview record |
| POST | /interviews/:id/conduct | interview:conduct | Start live interview session |
| POST | /interviews/:id/invite | interview:update | Generate candidate token and send invite email |
| POST | /interviews/:id/assess | interview:assess | Deprecated — assessment runs automatically |
| POST | /interviews/:id/override | interview:update | Apply recruiter override patch (add/remove skills, set role family) |
| GET | /interviews/:id/overrides | interview:read | Get all override patches for an interview |
POST /interviews/parse-resume
Accepts a resume file (PDF, DOCX, or plain text) and returns clean extracted text suitable for pre-filling the interview creation form. Accepts multipart/form-data with a single file field.
curl -X POST https://mayaapi.teamcast.ai/api/v1/interviews/parse-resume \
-H "Authorization: Bearer <jwt>" \
-F "file=@/path/to/resume.pdf"{
"resumeText": "Jane Smith\nSenior Software Engineer\n\nExperience:\n- 5 years TypeScript, React...",
"originalLength": 4821
}jobDescription or a candidate notes field when creating the interview.GET /interviews/counts
Returns the count of interviews in each status for the authenticated tenant. Useful for dashboard summary cards.
curl https://mayaapi.teamcast.ai/api/v1/interviews/counts \
-H "Authorization: Bearer <jwt>"{
"total": 142,
"planned": 8,
"approved": 94,
"inProgress": 2,
"infoNeeded": 3
}approved includes both APPROVED and COMPLETED interviews so the dashboard card reflects all interviews that have passed the plan approval gate.POST /interviews
Creates an interview record directly from the admin dashboard. External partner systems should use the Integration API (POST /integration/interviews) instead.
curl -X POST https://mayaapi.teamcast.ai/api/v1/interviews \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"candidateName": "Jane Smith",
"candidateEmail": "jane@example.com",
"position": "Senior Engineer",
"level": "SENIOR",
"skills": ["TypeScript", "React", "Node.js"],
"jobDescription": "Build scalable platform services with modern tooling.",
"scheduledAt": "2024-02-01T10:00:00.000Z"
}'{
"id": "interview-uuid",
"tenantId": "tenant-uuid",
"candidateName": "Jane Smith",
"candidateEmail": "jane@example.com",
"position": "Senior Engineer",
"level": "senior",
"skills": ["TypeScript", "React", "Node.js"],
"duration": 45,
"status": "planned",
"workflowState": null,
"planId": null,
"sessionId": null,
"runId": null,
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-15T10:00:00.000Z"
}roleFamily. All artifacts are stored and visible on the GET /interviews/:id response. Taxonomy enrichment for unknown roles and skill graph edges runs asynchronously in the background.GET /interviews
Returns a paginated list of interviews for the authenticated tenant. Supports full-text search across candidate name, position, and email, plus filtering by workflow status.
# List with pagination
curl "https://mayaapi.teamcast.ai/api/v1/interviews?page=1&limit=20" \
-H "Authorization: Bearer <jwt>"
# Search by name or position
curl "https://mayaapi.teamcast.ai/api/v1/interviews?search=Jane&status=PENDING" \
-H "Authorization: Bearer <jwt>"| Query Param | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number (1-indexed) |
| limit | number | 20 | Items per page (max 100) |
| status | string | - | Filter by workflow status (e.g. PENDING, COMPLETED, IN_PROGRESS) |
| search | string | - | Search candidate name, email, or position |
{
"data": [
{
"id": "interview-uuid",
"candidateName": "Jane Smith",
"candidateEmail": "jane@example.com",
"position": "Senior Engineer",
"level": "senior",
"skills": ["TypeScript", "React"],
"duration": 45,
"status": "planned",
"workflowState": "pending",
"planId": "plan-uuid",
"sessionId": null,
"runId": "agno-run-uuid",
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-15T10:00:00.000Z"
}
],
"total": 47,
"page": 1,
"limit": 20,
"totalPages": 3
}GET /interviews/:id
Returns the full interview record including all fields.
curl https://mayaapi.teamcast.ai/api/v1/interviews/interview-uuid \
-H "Authorization: Bearer <jwt>"{
"id": "interview-uuid",
"tenantId": "tenant-uuid",
"candidateName": "Jane Smith",
"candidateEmail": "jane@example.com",
"position": "Senior Engineer",
"level": "senior",
"skills": ["TypeScript", "React", "Node.js"],
"duration": 45,
"status": "planned",
"jobDescription": "Build scalable platform services...",
"workflowState": "pending",
"runId": "agno-run-uuid",
"planId": "plan-uuid",
"sessionId": null,
"callbackUrl": "https://ats.example.com/webhook",
"candidateClaimedSkills": ["React", "TypeScript", "Node.js"],
"candidateEvidencedSkills": ["React", "TypeScript"],
"candidateDemonstratedSkills": ["React", "TypeScript"],
"canonicalPayload": {
"skills": ["React", "TypeScript", "Node.js"],
"jobDescription": "Build scalable platform services...",
"candidateResume": "Jane Smith...",
"roleFamily": "frontend_engineering",
"roleCategory": "engineering",
"relatedSkills": ["Next.js", "Redux", "GraphQL"]
},
"diffReport": { "skills[0]": { "before": "ReactJS", "after": "React" } },
"rawPayload": { "position": "Sr Engineer", "skills": ["ReactJS", "TS", "Node.js"] },
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-01-15T10:45:00.000Z"
}candidateDemonstratedSkills is written by the assessor agent after the interview completes — it contains skills scored 2 or higher in the assessment.canonicalPayload.roleFamily and roleCategory are set by the AI taxonomy enricher and drive competency selection in the planner.canonicalPayload.relatedSkills are adjacent skills discovered via the capability graph.POST /interviews/:id/conduct
Creates a live interview session for an approved interview. Called internally when the candidate starts their session. Returns a sessionId used for the WebSocket connection.
curl -X POST https://mayaapi.teamcast.ai/api/v1/interviews/interview-uuid/conduct \
-H "Authorization: Bearer <jwt>"{
"sessionId": "session-uuid",
"interviewId": "interview-uuid",
"status": "created"
}POST /interviews/:id/invite
Generates a signed candidate access token for the interview and sends an invitation email to the candidate. If a token already exists for the interview, the existing token is reused (so the link stays stable). Returns the interview link and whether the email was delivered.
| Requirement | Detail |
|---|---|
| candidateEmail | Must be set on the interview record before calling this endpoint |
| Token expiry | 7 days from generation (configurable via CANDIDATE_TOKEN_EXPIRY_DAYS) |
| Sent from the configured SMTP sender — brandless candidate layout |
curl -X POST https://mayaapi.teamcast.ai/api/v1/interviews/interview-uuid/invite \
-H "Authorization: Bearer <jwt>"{
"interviewLink": "{YOUR_APP_URL}/interview/join/abc123token",
"token": "abc123token",
"emailSent": true
}/invite again reuses the same token — the link does not change. Use this to resend without invalidating an existing link.POST /interviews/:id/assess
This endpoint is deprecated and will throw a 400 Bad Request. The Assessor Agent runs automatically via Kafka when the interview session ends — no manual trigger is needed. To retrigger a failed assessment, use the POST /a2a/interview/:id/retrigger-assessment endpoint.
interview.completed Kafka event and is handled by the Assessor Agent at port 7779. The admin UI retrigger button uses the A2A retrigger endpoint instead.Error Responses
404 Not Found
{
"statusCode": 404,
"message": "Interview not found"
}403 Forbidden
{
"statusCode": 403,
"message": "Insufficient permissions. Required: interview:read"
}POST /integration/interviews) are also accessible via these endpoints using their id.