Skip to main content

API Reference

Complete reference for the Qlarr backend REST API. There is no global route prefix — all endpoints are at the root level (no /api/ prefix) and routes are unversioned.

For authentication details, see Authentication.

Roles

Role names as used in the codebase: super_admin, survey_admin, surveyor, analyst.

A global JwtAuthGuard protects every route unless it is marked @Public(); a RolesGuard enforces @Roles(...). "Auth: none" below means the route is public. "Auth: authenticated" means any valid token is accepted regardless of role.


Health

GET /health

Liveness check — the app is up and serving HTTP.

  • Auth: none

GET /health/db

Readiness check — proves the app can reach PostgreSQL.

  • Auth: none

Authentication

POST /user/login

Authenticate with email and password. Returns an access token + refresh token.

  • Body: { email, password }
  • Auth: none
  • Rate limit: 10 attempts / 5 min per email

POST /user/refresh_token

Refresh an expired access token. Refresh tokens are not rotated.

  • Body: { accessToken, refreshToken }
  • Auth: none

POST /user/forgot_password

Send a password reset email (PIN to the registered address).

  • Body: { email }
  • Auth: none
  • Rate limit: 5 attempts / 15 min per email

POST /user/reset_password

Reset a password using the reset token from the email.

  • Body: { refreshToken, newPassword }
  • Auth: none

POST /logout

Log out and invalidate the current session.

  • Auth: authenticated

GET /auth/me

Verify the current JWT and return its decoded principal.

  • Auth: authenticated

Users

GET /users/me

Get the current user's profile.

  • Auth: authenticated

GET /user/all

List all users.

  • Auth: super_admin, survey_admin

GET /user/count_by_role

Get user counts grouped by role.

  • Auth: super_admin

POST /user/create

Create a new user.

  • Body: { firstName, lastName, email, roles }
  • Auth: super_admin

GET /user/{userId}

Get user details by ID.

  • Auth: authenticated

PUT /user/{userId}

Update a user (name, roles).

  • Body: { firstName?, lastName?, roles? }
  • Auth: super_admin

DELETE /user/{userId}

Delete a user.

  • Auth: super_admin

PUT /user/profile

Update own profile.

  • Body: { firstName?, lastName?, email?, password?, newPassword? }
  • Auth: authenticated
  • Rate limit: 5 attempts / 15 min per user (for email/password changes)

POST /user/confirm_new_email

Confirm an email-address change using a PIN.

  • Body: { pin }
  • Auth: authenticated
  • Rate limit: 5 attempts / 15 min per user

Surveys

GET /survey/all

List all surveys with pagination and filtering.

  • Query: page, per_page, sort_by, status
  • Auth: authenticated

GET /survey/offline

Get surveys available for offline mode.

  • Auth: super_admin, survey_admin, surveyor

POST /survey/create

Create a new survey.

  • Body: { name, usage? } (usage: web | offline | mixed)
  • Auth: super_admin, survey_admin

POST /survey/import

Import a survey from an export ZIP.

  • Body: multipart file upload (file)
  • Auth: super_admin, survey_admin

GET /survey/{surveyId}

Get survey metadata.

  • Auth: authenticated

PUT /survey/{surveyId}

Update survey metadata (name, dates, quota, privacy, navigation, etc.).

  • Body: survey settings
  • Auth: super_admin, survey_admin

PUT /survey/{surveyId}/close

Close/deactivate a survey.

  • Auth: super_admin, survey_admin

POST /survey/{surveyId}/clone

Clone an existing survey.

  • Auth: super_admin, survey_admin

GET /survey/{surveyId}/export

Export a survey as a ZIP package.

  • Auth: super_admin, survey_admin

DELETE /survey/{surveyId}

Delete a survey.

  • Auth: super_admin, survey_admin

Survey Design

GET /survey/{surveyId}/design

Get the current survey design (editor input + version metadata).

  • Auth: super_admin, survey_admin

POST /survey/{surveyId}/design

Save/update the survey design.

  • Query: version
  • Body: survey design JSON
  • Auth: super_admin, survey_admin

POST /survey/{surveyId}/change_code

Rename a question/component code throughout the design.

  • Query: from, to
  • Auth: super_admin, survey_admin

POST /survey/{surveyId}/design/publish

Publish a survey design version.

  • Query: version, sub_version
  • Auth: super_admin, survey_admin

POST /survey/{surveyId}/offline/design

Get design differences for offline sync (published version + new resources since the client's last-modified time).

  • Body: { version, subVersion, lastModified }
  • Auth: super_admin, survey_admin, surveyor

Survey Execution

Survey run endpoints are public (no authentication required). The parallel preview endpoints require authentication and are used by admins to test surveys.

POST /survey/{surveyId}/run/start

Start a survey session.

  • Body: { lang?, navigationMode?, values?, clientUTCTime? }
  • Auth: none

POST /survey/{surveyId}/run/navigate

Navigate to the next/previous page or submit.

  • Body: { responseId, navigationDirection, values?, events?, clientUTCTime? }
  • Auth: none

GET /survey/{surveyId}/run/runtime.js

Get the generated JavaScript state machine for client-side execution.

  • Auth: none

POST /survey/{surveyId}/preview/start

Start a survey in preview mode.

  • Query: mode (optional: online | offline)
  • Body: { lang?, navigationMode?, values?, clientUTCTime? }
  • Auth: authenticated

POST /survey/{surveyId}/preview/navigate

Navigate in preview mode.

  • Query: mode (optional)
  • Body: { responseId, navigationDirection, values?, events?, clientUTCTime? }
  • Auth: authenticated

GET /survey/{surveyId}/preview/runtime.js

Get the runtime JavaScript for preview mode.

  • Auth: authenticated

Responses

GET /response/{responseId}

Get a single response with resolved, labelled values.

  • Auth: super_admin, survey_admin, analyst

GET /response_with_event/{responseId}

Get a response together with its timeline events.

  • Auth: super_admin, survey_admin, analyst

GET /survey/{surveyId}/response/summary

Get a paginated response summary for a survey.

  • Query: page, per_page, status (ALL | COMPLETE | INCOMPLETE | PREVIEW), surveyor, confirm_files_export
  • Auth: super_admin, survey_admin, analyst

GET /survey/{surveyId}/response/analytics

Get aggregated analytics for survey responses.

  • Query: max_responses (optional)
  • Auth: super_admin, survey_admin, analyst

GET /survey/{surveyId}/response/export/{format}/{from}/{to}

Export responses in a given format.

  • Path: format (CSV | EXCEL | JSON), from/to (response indices)
  • Query: complete, db_values
  • Auth: super_admin, survey_admin, analyst

GET /survey/{surveyId}/response/files/download/{from}/{to}

Download response files as a ZIP archive.

  • Query: complete
  • Auth: super_admin, survey_admin, analyst

DELETE /survey/{surveyId}/response/{responseId}

Delete a response.

  • Auth: super_admin, survey_admin

Response Files

POST /survey/{surveyId}/response/attach/{responseId}/{questionId}

Upload a file attachment to a response.

  • Body: multipart file
  • Auth: none

GET /survey/{surveyId}/response/attach/{responseId}/{questionId}

Download a response file attachment.

  • Auth: none

GET /survey/{surveyId}/response/{responseId}/attach/{filename}

Download a response file by filename (legacy path).

  • Auth: none

POST /survey/{surveyId}/response/preview/attach/{responseId}/{questionId}

Upload a preview/test response file.

  • Body: multipart file
  • Auth: authenticated

Offline Sync

POST /survey/{surveyId}/response/{responseId}/upload

Upload a complete offline survey response.

  • Body: { versionId, lang, values?, startDate, submitDate, userId, navigationIndex, events? }
  • Auth: super_admin, survey_admin, surveyor

POST /survey/{surveyId}/offline/response/{responseId}/upload/{fileName}

Upload a file from an offline response.

  • Body: multipart file
  • Auth: super_admin, survey_admin, surveyor

POST /survey/{surveyId}/offline/response/{responseId}/upload/{filename}/exists

Check whether an offline response file has already been uploaded.

  • Auth: super_admin, survey_admin, surveyor

Survey Resources

POST /survey/{surveyId}/resource

Upload a resource file (images, media) for a survey.

  • Body: multipart file
  • Auth: super_admin, survey_admin

GET /survey/{surveyId}/resource/{fileName}

Download a survey resource file (cached).

  • Auth: none

DELETE /survey/{surveyId}/resource/{fileName}

Delete a survey resource file.

  • Auth: super_admin, survey_admin

Autocomplete

GET /survey/{surveyId}/autocomplete/{filename}

Search autocomplete values (respondent-facing).

  • Query: q (search term), limit (1–100, default 10)
  • Auth: none

GET /autocomplete/{surveyId}/{componentId}

Get all autocomplete values for a question (design-time).

  • Auth: super_admin, survey_admin

POST /autocomplete/{surveyId}/{componentId}

Upload autocomplete data for a question.

  • Body: multipart file
  • Auth: super_admin, survey_admin

Notes

  • Dates are UTC wall-clock strings in yyyy-MM-dd HH:mm:ss format.
  • Survey ID in the path determines the survey context; the backend is single-tenant, so no tenant header is needed.
  • File uploads go through Multer with a per-request size limit.
  • Errors are shaped by a global exception filter; malformed or invalid bodies are rejected by a global validation pipe.