> ## Documentation Index
> Fetch the complete documentation index at: https://formhug.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Update an entry

> Partially update an entry: only the fields present in `field_values` change. For an
`attachment` field (or an attachment column inside a table / matrix) the submitted array
replaces the stored list — include the `id`s of files to keep and new `upload_id`s to add.

**Required scope:** `entry:write`.




## OpenAPI

````yaml /api-reference/openapi.yaml patch /api/v1/forms/{form_token}/entries/{serial_number}
openapi: 3.0.1
info:
  title: FormHug API V1
  version: v1
  description: >
    FormHug public REST API. All request/response keys are snake_case.


    Successful response:


    ```json

    {
      "data": { ... }
    }

    ```


    Paginated response:


    ```json

    {
      "data": [ ... ],
      "pagination": {
        "total": 123,
        "next_cursor": "NQ=="
      }
    }

    ```


    Error response:


    ```json

    {
      "error": "Human-readable message",
      "code": "password_required",
      "error_details": [
        { "attribute": "field_name", "message": "specific error" }
      ]
    }

    ```


    `code` is a machine-readable reason, present only where a client may need to
    branch

    on it (see `CodedErrorEnvelope`). `error_details` appears on validation
    failures and

    lists each offending attribute.
servers:
  - url: https://formhug.ai
security: []
tags:
  - name: Forms
    description: Form CRUD
  - name: Attachments
    description: >-
      2-step upload for form-element images (theme, rich-text, or field-element
      images). Prepare returns an `upload_id`; consume it in a theme update,
      attachment_commitments, or the form `fields` payload depending on purpose.
  - name: Entries
    description: Entries collected by a form owned by the current user
  - name: Folders
    description: Folder CRUD
  - name: Participated Forms
    description: Forms the current user has submitted to (does not own)
  - name: Published Form Entries
    description: Submit entries to a published form
  - name: Published Forms
    description: Read a published form's public structure for filling
  - name: Linked Form Options
    description: >-
      Discover candidate entries (and their `entry_token`s) for a `linked_form`
      field while filling a published form
  - name: Entry Attachments
    description: >-
      2-step upload for `attachment` field submissions. Prepare returns an
      `upload_id`; submit it under the attachment field in `field_values` when
      creating the entry.
  - name: Me
    description: Current authenticated user
  - name: Webhooks
    description: Webhook integrations attached to a form
  - name: Form Themes
    description: Read and update a form's visual theme
  - name: Form Settings
    description: >-
      Per-form settings — submission flow, availability, access control,
      presentation
  - name: Field Rules
    description: >-
      Read and replace a form's conditional field-display and post-submission
      redirect rules.
  - name: Form Folder
    description: Per-user folder placement for a shared form
  - name: OAuth
    description: OAuth 2.0 PKCE token issuance and revocation
  - name: Public Queries
    description: Public query pages that let visitors look up entries by chosen fields
paths:
  /api/v1/forms/{form_token}/entries/{serial_number}:
    parameters:
      - name: form_token
        in: path
        description: Form token
        required: true
        schema:
          type: string
      - name: serial_number
        in: path
        description: Per-form serial number of the entry
        required: true
        schema:
          type: integer
    patch:
      tags:
        - Entries
      summary: Update an entry
      description: >
        Partially update an entry: only the fields present in `field_values`
        change. For an

        `attachment` field (or an attachment column inside a table / matrix) the
        submitted array

        replaces the stored list — include the `id`s of files to keep and new
        `upload_id`s to add.


        **Required scope:** `entry:write`.
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EntryUpdateRequest'
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Entry'
        '403':
          description: Collaborator role lacks permission to edit entries
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: Entry not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Validation failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorEnvelope'
      security:
        - PersonalAccessToken:
            - entry:write
components:
  schemas:
    EntryUpdateRequest:
      type: object
      required:
        - field_values
      properties:
        field_values:
          type: object
          description: >-
            Map keyed by field api_code; only the submitted fields change and
            unknown keys are dropped silently. For an `attachment` value, list
            the `id`s of stored files to keep plus any new `upload_id`s; files
            left out are removed from the entry.
          example:
            field_1: Jane Doe
    Entry:
      type: object
      required:
        - serial_number
        - token
        - created_at
        - updated_at
      description: >+
        A submitted entry. In addition to the fixed fields below, every field of
        the

        parent form appears as a top-level key on the entry under its
        `api_code`. The

        JSON value type for each such key is determined by the corresponding
        field's

        `type`.


        ## Field value shapes


        Each field of the parent form appears as a top-level key on the entry,
        keyed by its

        `api_code`. The JSON shape of the value depends on the field's `type`:


        | Field type (`type`) | Submitted value |

        |---|---|

        | `short_text` | String. The submitted text. |

        | `long_text` | String. Multi-line text. |

        | `radio` | Object `{ value, other_text?, extended_text? }`, or `null`
        when unset. `value` is the `api_code` of the selected choice.
        `other_text` carries the respondent's free-text input and is only
        present when the selected choice has `is_other: true`. `extended_text`
        carries the free-text input for a choice that has `allow_extended_text:
        true`. The two text keys are mutually exclusive per choice (an
        `is_other` choice cannot also enable `allow_extended_text`) and both are
        omitted when blank. On write, a bare string is accepted as shorthand for
        `{ value: <string> }`; `null` clears the field; text keys that don't
        match the selected choice's configuration are ignored. |

        | `checkbox` | Array of `{ value, other_text?, extended_text? }` objects
        with the same per-choice semantics as `radio`. Empty array when nothing
        is selected. At most one element may carry `other_text` (the element
        whose `value` corresponds to the `is_other` choice). On write, `null`
        clears the field; bare strings in the array are accepted as shorthand
        for `{ value: <string> }`; duplicate values are silently de-duplicated
        (first occurrence wins). |

        | `image_radio` | Object `{ value }`, or `null` when unset. `value` is
        the `api_code` of the selected choice. Image choices support neither
        `other_text` nor `extended_text`. On write, a bare string is accepted as
        shorthand for `{ value: <string> }`; `null` clears the field. |

        | `image_checkbox` | Array of `{ value }` objects — `value` is the
        `api_code` of a selected choice. Empty array when nothing is selected.
        On write, `null` clears the field; bare strings in the array are
        accepted as shorthand; duplicate values are silently de-duplicated
        (first occurrence wins). |

        | `dropdown` | Object `{ value, other_text? }`, or `null` when unset.
        Same `value` and `other_text` semantics as `radio`. `dropdown` does not
        support `extended_text`. |

        | `number` | Number. Stored as a float; integer-looking values may
        serialize without a decimal point. |

        | `email` | String — an email address. |

        | `phone` | Object `{ country_id, country_code, number }`. `country_id`
        is an ISO 3166-1 alpha-2 country code (e.g. `"CN"`, `"US"`) and is
        required; `country_code` is the dialing code without `+` (e.g. `"86"`,
        `"1"`) and is optional on write — when omitted it is derived from
        `country_id`; `number` is the local number without the dialing-code
        prefix. |

        | `date` | Naive wall-clock string formatted per the field's
        `precision`: `"YYYY-MM"` (month), `"YYYY-MM-DD"` (day), `"YYYY-MM-DD
        HH:mm"` (minute), `"YYYY-MM-DD HH:mm:ss"` (second). Values are
        interpreted in the form's `timezone` setting. When no `timezone` is
        supplied at creation time, the form uses your account's timezone,
        falling back to `UTC` if that is unset or invalid. |

        | `name` | String — the submitted name. |

        | `url` | String — a URL. |

        | `address` | Object `{ address_line1, address_line2, city, state,
        postal_code, country }`. `country` is an ISO 3166-1 alpha-2 country
        code; `state` is an ISO 3166-2 subdivision code (e.g. `"CA"`, `"NY"`),
        not a localized label. |

        | `rating` | Integer — the chosen rating level (1..`rating_max`). |

        | `nps` | Integer — the selected score (0..10). |

        | `attachment` | Array of objects `{ id: string, name: string, url:
        string, file_size: integer, content_type: string }`. `url` is a signed
        download link valid for 24 hours — refetch the entry to get a fresh link
        rather than caching it; `name` is the original filename. |

        | `audio` | Read-only object `{ id, name, url, file_size, content_type,
        duration }` describing the recording (`url` is a signed download link
        valid for 24 hours; `duration` is the recording length). Null when no
        recording. Submitting a value for an audio field is not supported. |

        | `cascade` | Object `{ level_1: <api_code>, level_2: <api_code>, ... }`
        — one key per level (the field's `levels` setting, default `2`). Each
        value is the `api_code` of the choice selected at that level. |

        | `ranking` | Object `{ <choice_api_code>: <rank> }` — `rank` is a
        positive integer, contiguous starting at `1` for the highest-ranked
        choice. Unranked choices are omitted. |

        | `matrix` | Nested object `{ <statement_api_code>: {
        <dimension_api_code>: <cell_value> }, ... }`. Each cell reads and writes
        its dimension type's own entry value shape — e.g. a `dropdown` cell is
        `{ value: <choice_api_code> }` (bare-string shorthand accepted on
        write), a `number` cell is a number. |

        | `likert` | Object `{ <statement_api_code>: [<choice_api_code>, ...]
        }`. The value is always an array — a single-choice answer is wrapped in
        a one-element array. |

        | `time` | Object `{ hour: integer, minute: integer }`, plus `second:
        integer` when the field has `include_second` enabled (e.g. `{ "hour": 9,
        "minute": 5 }`). |

        | `location` | Object `{ longitude: number, latitude: number, address:
        string }`. |

        | `signature` | Read-only string — a signed download URL for the
        signature image, valid for 24 hours. Refetch the entry to obtain a fresh
        link rather than caching it. Submitting a value for a signature field is
        not supported. |

        | `matrix_rating` | Nested object `{ <statement_api_code>: {
        <dimension_api_code>: <integer> } }`. The inner integer is the chosen
        rating level (1..`rating_max`). |

        | `table` | Array of row objects `[{ <dimension_api_code>: <cell_value>,
        ... }]`. Each cell reads and writes its dimension type's own entry value
        shape — e.g. a `dropdown` cell is `{ value: <choice_api_code> }`
        (bare-string shorthand accepted on write), a `number` cell is a number.
        |

        | `product` | Array `[{ api_code, number, specification? }]`.
        `specification` is present when the goods item has dimensions; it is an
        object of `{ <dim_api_code>: <option_api_code> }`. |

        | `booking` | Array of reservations. On write: `[{ api_code,
        scheduled_at, end_at?, number? }]` — `api_code` is the reservation item;
        `scheduled_at` (and `end_at`) are ISO8601 date-time strings; `number`
        defaults to 1 (values other than 1 require `allow_multiple_number:
        true`). For a weekly-schedule item send `scheduled_at` on the target
        day. For a per-day-of-week time-slot item send `scheduled_at` = day +
        slot start and `end_at` = day + slot end, matching one of the item's
        configured slots (`quota_setting.daily_time_range_quotas[].start_time` /
        `end_time`). `item_name` / `time_range_code` are server-derived and
        ignored on write. Send `[]` to clear. On read: `[{ api_code,
        scheduled_at, end_at, number, item_name, time_range_code }]`. |

        | `linked_form` | On write: string — the `entry_token` of an entry in
        the associated form, or `null` to clear. Public submitters can discover
        valid `entry_token`s via `GET
        /api/v1/f/{form_token}/associated_entry_options`. The server resolves
        the token against `associated_form_token`; an unknown token yields 422.
        On read: one of three shapes — (1) `null` if not linked; (2) `{
        "deleted": true }` if the linked entry has been deleted; (3) Object `{
        entry_token, serial_number, associated_fields, display_fields }`
        describing the linked entry, where `associated_fields` /
        `display_fields` map each `api_code` (from `associated_field_api_codes`
        / `display_field_api_codes` respectively) to that field's value,
        formatted per the linked field's own type (recursive — e.g. a `date`
        field renders as its naive wall-clock string, an `attachment` field
        renders as its array of file objects). |

        | `formula` | The computed result. A number, a naive date string
        (`YYYY-MM-DD`), or a string, depending on what the formula evaluates to.
        |

        | `page_break` | None — display-only field; never appears as an entry
        value. |

        | `description` | None — display-only field; never appears as an entry
        value. |

      properties:
        serial_number:
          type: integer
          description: Per-form auto-increment sequence number
          example: 42
        token:
          type: string
          description: Entry token
          example: aB2cD9eF
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      additionalProperties:
        description: >-
          Field value keyed by api_code; the value type depends on the field
          type.
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Error message
    ValidationErrorEnvelope:
      type: object
      required:
        - error
        - error_details
      description: >-
        Returned on model validation failures. error_details lists per-field
        errors.
      properties:
        error:
          type: string
          example: Name can't be blank
        error_details:
          type: array
          items:
            type: object
            required:
              - attribute
              - message
            properties:
              attribute:
                type: string
                example: name
              message:
                type: string
                example: can't be blank
  securitySchemes:
    PersonalAccessToken:
      type: http
      scheme: bearer
      bearerFormat: PAT
      description: >
        Personal Access Token prefixed with `fh_`. Sent as `Authorization:
        Bearer fh_xxx`.

        The scope required by each endpoint is listed in that endpoint's
        description.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.