---
title: "Submit a questionnaire response via public token (no authentication required)"
method: POST
path: "/public/questionnaires/submit"
tags: ["PublicQuestionnaires"]
---

# Submit a questionnaire response via public token (no authentication required)

`POST /public/questionnaires/submit`

## Request

- Base URL: `https://api.clinicos.vet/backend/business`
- URL: `https://api.clinicos.vet/backend/business/public/questionnaires/submit`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/docs/public/questionnaires/submit/post.ts> (a function with typed inputs; its response is checked against the schema)

## Request body

- SubmitQuestionnaireResponseRequest: Request to submit a response via public link
  - `token` string, required
  - `responses` string, required
  - `submittedBy` string, nullable
  - `schemaVersion` union: The questionnaire version the fill page loaded (`questionnaire.version` from the public GET), so the submission is checked against the form the client actually saw (ITE-1091). A consent submitted against an older version is refused with 409; null (a page that predates pinning) is accepted and recorded as unpinned.
    - integer
    - string, int32
  - `signerName` string, nullable: The name the signer typed beside their drawn signature (ITE-1091).

## Response `201`

Created

- QuestionnaireResponseDto: Full questionnaire response (submission) DTO
  - `id` string
  - `questionnaireId` string
  - `questionnaire` QuestionnaireListItemDto: Lightweight questionnaire item for lists
    - `id` string
    - `name` string
    - `description` string, nullable
    - `type` 'Intake' | 'PreVisit' | 'PostVisit' | 'Satisfaction' | 'Custom' | 'NewClient' | 'AppointmentConfirmation' | 'Consent' | 'Handout'
    - `status` integer
    - `isTemplate` boolean
    - `version` union
      - integer
      - string, int32
    - `createdAt` string, date-time
    - `updatedAt` string, date-time
    - `automationCount` union: Number of active and inactive automation rules referencing this form. Populated by the list endpoint via a join on automation_questionnaire_refs.
      - integer
      - string, int32
  - `patientId` string, nullable
  - `patient` PatientSummaryDto: Lightweight patient summary for lists and references
    - `id` string: Unique patient identifier
    - `name` string: The patient's name
    - `species` string: The species name. References a species from GET /species endpoint.
    - `speciesId` string, nullable: The species ID for programmatic lookups.
    - `breed` string: The breed name
    - `sex` string: The patient's sex
    - `dateOfBirth` string, date-time, nullable: Date of birth, if known
    - `isEstimatedAge` boolean
    - `fixed` boolean: Whether the patient is spayed/neutered
    - `treatmentAcceptanceRate` union
      - number, double
      - string, double
  - `clientId` string, nullable
  - `client` ClientSummaryDto
    - `id` string
    - `firstName` string
    - `lastName` string
    - `email` string, nullable
    - `phoneNumber` string, nullable
  - `appointmentId` string, nullable
  - `responses` string
  - `status` integer
  - `submittedAt` string, date-time, nullable
  - `submittedBy` string, nullable
  - `createdAt` string, date-time
  - `updatedAt` string, date-time
  - `readAt` string, date-time, nullable: When the client read a read-only handout on the public page (ITE-1712). A Completed handout with no ReadAt was completed by opening the link, before ITE-1712: opened, not read.
  - `customAttributes` string, nullable
  - `linkExpiresAt` string, date-time, nullable: Latest expiry among the response's public links. Lets read surfaces derive "Sent, awaiting" (InProgress, unexpired) vs "Expired" (InProgress, expired).
  - `linkFirstViewedAt` string, date-time, nullable: Earliest first-view among the response's public links (null = never opened). Lets read surfaces distinguish "Sent, awaiting" from "Opened, awaiting".
  - `handoutVersion` union: Handouts (ITE-1474): the content version the client was sent, from the response's latest link. Null for other types, or a link sent before the handout had a version.
    - integer
    - string, int32
  - `deliveryMethod` string, nullable: How the latest link reached the client (ITE-1477): "Email", "SMS", "Both", or "InClinic" for a tablet / QR handoff. Null for a link from before the channel was recorded.

## Other responses

- `400`: Bad Request
- `409`: Conflict
- `410`: Gone

## Changes

- **2026-10-28** `099cf36186e0`: 3 warning, 9 info
  - added the new `Handout` enum value to the `questionnaire/oneOf[#/components/schemas/QuestionnaireListItemDto]/type` response property for the response status `201` (media type: text/plain)
  - added the new `Handout` enum value to the `questionnaire/oneOf[#/components/schemas/QuestionnaireListItemDto]/type` response property for the response status `201` (media type: application/json)
  - added the new `Handout` enum value to the `questionnaire/oneOf[#/components/schemas/QuestionnaireListItemDto]/type` response property for the response status `201` (media type: text/json)
  - added the optional property `deliveryMethod` to the response with the `201` status (media type: text/plain)
  - …8 more
- …earlier changes not shown

[Operation history](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/changes/public/questionnaires/submit/post.md)

---

[API](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1.md) - [All operations](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/llms.txt) - [OpenAPI document](https://skmtc.dev/clinicos/apis/pawthosx-business-api-v1/revisions/099cf36186e0?raw)
