---
title: "Replace Draft Fields"
method: PUT
path: "/api/documents/drafts/{document_id}/fields"
tags: ["drafts"]
---

# Replace Draft Fields

`PUT /api/documents/drafts/{document_id}/fields`

## Request

- Base URL: `https://zsign.io` (the document declares no server; this is the origin it was published from)
- URL: `https://zsign.io/api/documents/drafts/{document_id}/fields`
- Auth: HTTP bearer

Whole-list replace. Translates the wire's nested `position` shape
into the flat dict DocumentProcessor.normalize_fields expects -- see
that method's docstring for why the shapes differ and normalize_fields'
contract cannot change (the live tag-parse path depends on it too).

CONTRACT: the response's `fields` must contain exactly one entry per
submitted field, in the SAME ORDER they were sent.

The editor reconciles this response to its own field list positionally
(frontend/src/services/draftService.ts) and has no way to detect a
violation -- it would silently apply one field's server-confirmed name
to a different field, and that wrong name would be written back on the
next autosave and carried into the signed document.

Nothing enforces this at the type level; it holds because every link is
order-preserving by construction (the comprehension below, the
one-append-per-input loop in normalize_fields, and returning that list
directly rather than re-fetching). Do not add a sort, a group-by-page,
or a position-dedupe step without also giving the client a stable
per-field key to reconcile on instead. TestAutosaveFieldsHTTP's ordering
tests pin this.

## Path parameters

- `document_id` string, uuid, required

## Request body

- DraftFieldsRequest: Body of PUT /api/documents/drafts/{id}/fields -- a whole-list replace, not per-field CRUD (see DraftDocumentService.replace_fields).
  - `fields` DraftField[], required
    - `type` 'signature' | 'initials' | 'text' | 'date' | 'checkbox' | 'radio', required
    - `party` string, nullable
    - `semantic_type` 'full_name', nullable
    - `label` string, nullable
    - `name` string, nullable
    - `required` boolean
    - `position` FieldPosition, required: Position data for a field on the PDF
      - `page_number` integer, required: Page number (1-indexed)
      - `file_position` integer: 1-based source PDF index in the envelope package. At most MAX_ENVELOPE_DOCUMENTS.
      - `x` number, required: X coordinate (top-left origin)
      - `y` number, required: Y coordinate (top-left origin)
      - `width` number, required: Field width
      - `height` number, required: Field height
    - `document_id` string, nullable
    - `group` string, nullable
    - `option_value` string, nullable
    - `default_value` string, nullable
    - `locked` boolean
  - `intended_recipients` IntendedRecipientIn[], nullable
    - `role` string, required
    - `name` string
    - `email` string
  - `revision` integer, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/zsign/apis/zsign-api.md) · [All operations](https://skmtc.dev/zsign/apis/zsign-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zsign/apis/zsign-api/revisions/a674ac4137ba?raw)
