Interview Lifecycle API Reference

Version: 1.0
Last Updated: 2026-07-16

All endpoints are located under /api/v1/interviews/ and require the X-Tenant-ID header for tenant scoping.


Create Interview

Purpose

Initialize a new interview session for a survey respondent.

URL

/api/v1/interviews

Method

POST

Authentication

Bearer token authentication required.

Permissions

forms:session:create

Request Body

{
  "survey_id": "uuid",
  "session_token": "string",
  "respondent_id": "uuid (optional)",
  "total_questions": 50,
  "survey_name": "string (optional)",
  "interview_metadata": {}
}
FieldTypeRequiredDescription
survey_idUUIDYesSurvey to conduct
session_tokenstringYesUnique session identifier
respondent_idUUIDNoRespondent being interviewed
total_questionsintegerNoExpected question count
survey_namestringNoDisplay name
interview_metadataobjectNoAdditional metadata

Response

{
  "id": "uuid",
  "tenant_id": "uuid",
  "survey_id": "uuid",
  "session_token": "string",
  "status": "created",
  "started_at": null,
  "paused_at": null,
  "completed_at": null,
  "terminated_at": null,
  "current_page": 0,
  "answered_count": 0,
  "created_at": "ISO8601"
}

Error Responses

StatusDescription
400Missing tenant ID or invalid survey
401Authentication required
403Insufficient permissions
500Internal server error

Example Request

curl -X POST "http://form-service:8010/api/v1/interviews" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{
    "survey_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "session_token": "interview_abc123",
    "respondent_id": "r1e2s3p4-o5n6d7e8t9t0"
  }'

List Interviews

Purpose

Retrieve paginated list of interviews with optional filtering.

URL

/api/v1/interviews

Method

GET

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Request Parameters

ParameterTypeRequiredDescription
statusstringNoFilter by status
survey_idUUIDNoFilter by survey
interviewer_idUUIDNoFilter by interviewer
respondent_idUUIDNoFilter by respondent
searchstringNoSearch by session token
sortstringNoSort field
skipintegerNoDefault: 0
limitintegerNoDefault: 20, max: 100

Response

{
  "items": [...],
  "total": 100,
  "skip": 0,
  "limit": 20,
  "has_next": true,
  "has_previous": false
}

Get Interview

Purpose

Retrieve details of a specific interview.

URL

/api/v1/interviews/{interview_id}

Method

GET

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Response

{
  "id": "uuid",
  "tenant_id": "uuid",
  "survey_id": "uuid",
  "respondent_id": "uuid",
  "interviewer_id": "uuid",
  "session_token": "string",
  "status": "in_progress",
  "started_at": "ISO8601",
  "last_heartbeat_at": "ISO8601",
  "current_page": 15,
  "answered_count": 15,
  "total_questions": 50,
  "created_at": "ISO8601",
  "updated_at": "ISO8601"
}

Error Responses

StatusDescription
400Missing tenant ID
401Authentication required
403Insufficient permissions
404Interview not found

Update Interview

Purpose

Update interview metadata and progress.

URL

/api/v1/interviews/{interview_id}

Method

PATCH

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Request Body

{
  "current_page": 20,
  "answered_count": 20,
  "total_questions": 50,
  "interview_metadata": {}
}
FieldTypeDescription
current_pageintegerCurrent navigation position
answered_countintegerQuestions answered
total_questionsintegerTotal questions in survey
interview_metadataobjectAdditional metadata

Response

Updated InterviewDto.

Error Responses

StatusDescription
400Invalid data or missing tenant ID
409Concurrent modification detected

Transition Interview

Purpose

Change interview status through valid lifecycle transitions.

URL

/api/v1/interviews/{interview_id}/transition

Method

POST

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Request Body

{
  "to_status": "in_progress",
  "form_data": {},
  "is_complete": false,
  "current_page": 50,
  "version_id": "uuid (optional)",
  "edit_response_id": "uuid (optional)"
}

Valid Transitions

created → in_progress
in_progress → paused
in_progress → completed
in_progress → terminated
completed → needs_revision
needs_revision → in_progress

Response

Updated InterviewDto.

Error Responses

StatusDescription
400Invalid status or transition not allowed
404Interview not found

Interview Heartbeat

Purpose

Ping to indicate interview is still active.

URL

/api/v1/interviews/{interview_id}/heartbeat

Method

POST

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Response

{
  "status": "in_progress",
  "heartbeat_at": "2026-07-16T10:30:00.000Z"
}

Error Responses

StatusDescription
400Interview not heartbeat-eligible
404Interview not found

Get Termination Details

Purpose

Retrieve termination information for a terminated interview.

URL

/api/v1/interviews/{interview_id}/termination

Method

GET

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Response

{
  "id": "uuid",
  "interview_id": "uuid",
  "terminated_by": "uuid",
  "terminated_at": "ISO8601",
  "termination_reason": "refused_to_continue",
  "explanatory_text": "Respondent declined to answer sensitive questions",
  "data_saved": true,
  "retry_submission_available": false
}

Error Responses

StatusDescription
404No termination record found

List Termination Policies

Purpose

Retrieve available termination reason options and policies.

URL

/api/v1/interviews/termination-policies

Method

GET

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Response

[
  {
    "value": "refused_to_continue",
    "label": "Refused to Continue",
    "description": "Respondent declined to continue the interview"
  }
]

Retry Submission

Purpose

Retry submission for a terminated interview with partial data.

URL

/api/v1/interviews/{interview_id}/retry-submission

Method

POST

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Response

Updated TerminationDto.


Delete Interview

Purpose

Soft-delete an interview (only if status is "created").

URL

/api/v1/interviews/{interview_id}

Method

DELETE

Authentication

Bearer token authentication required.

Permissions

forms:session:delete

Response

No content (204) on success.

Error Responses

StatusDescription
400Interview not in "created" status
403Insufficient permissions

List Interview Events

Purpose

Retrieve audit trail of interview state changes.

URL

/api/v1/interviews/{interview_id}/events

Method

GET

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Response

[
  {
    "id": "uuid",
    "interview_id": "uuid",
    "event_type": "interview.started",
    "to_status": "in_progress",
    "actor_id": "uuid",
    "created_at": "ISO8601"
  }
]

Resolve Interview by Session Token

Purpose

Look up an interview using its session token.

URL

/api/v1/interviews/resolve/by-session-token/{session_token}

Method

GET

Authentication

Bearer token authentication required.

Permissions

forms:session:read

Response

InterviewDto for the matching interview.

Error Responses

StatusDescription
404Interview not found