---
title: "Add a document to a template"
method: POST
path: "/templates/{id}/documents"
tags: ["Templates"]
---

# Add a document to a template

`POST /templates/{id}/documents`

## Request

- Base URL: `https://api.firma.dev/functions/v1/signing-request-api`
- URL: `https://api.firma.dev/functions/v1/signing-request-api/templates/{id}/documents`
- Auth: API key in header `Authorization`
- TypeScript: <https://skmtc.dev/firma/apis/firma-partner-api/docs/templates/:id/documents/post.ts> (a function with typed inputs; its response is checked against the schema)

Adds a document (a temporary upload from `POST /documents`) to the template's document set, at `position` or last. Documents at that position and after it move up by one. At most 20 documents and 100 MB per template.

**Available to every company.** This operation is part of the multi-document contract (API 01.39.00). For a signing request or template the API key cannot see, it answers `404` with code `NOT_FOUND` ("Endpoint not found"), exactly as an unknown endpoint does. While multi-document editing is suspended, this operation returns `409 MULTI_DOCUMENT_READ_ONLY` for parents on the multi-document read-only path and `404 NOT_FOUND` for parents on the single-document path.

## Path parameters

- `id` string, uuid, required

## Request body

- object
  - `document_id` string, uuid, required: Temporary upload id from POST /documents (a PDF). Consumed once the document is added.
  - `position` integer: 1-based position of the new document; at most the current count + 1. Defaults to last.
  - `label` string, nullable: Display name of the document (no control characters).
  - `original_filename` string, nullable: File name to record for the document (no control characters).

## Response `200`

Document added; the full document set after the change

- DocumentSetMutationResponse: Answer of every /documents mutation: the full document set after the change and its two versions.
  - `documents` DocumentSummary[], required
    - `document_id` string, uuid, nullable, required: Id of the document. null only for the one document of a signing request or template whose document set has never been changed (see the example).
    - `position` integer, required: 1-based position in the set.
    - `label` string, nullable, required: Display name, or null.
    - `original_filename` string, nullable, required: File name recorded at upload, or null.
    - `page_count` integer, nullable, required: Number of pages of this document.
    - `document_url` string, nullable: Signed URL (1 hour) of the file `document_url_kind` names. Absent on list responses.
    - `document_url_kind` 'stored' | 'signed' | 'null', nullable, required: `stored`: the document as stored; `signed`: the individually sealed document. Always `stored` on templates; null on signing-request list entries.
    - `document_only_hash` string, nullable: SHA-256 of the exact bytes of the sealed PDF that `document_url` (when `document_url_kind` is `signed`) and `GET /signing-requests/{id}/documents/{document_id}/download?type=document` serve, as 64 lowercase hexadecimal characters. It is computed after Firma's digital seal is applied. It is not the hash of the uploaded file, and not the hash of `final_document_download_url`, which also contains the completion certificate. `null` until the certificate is bound. Signing requests only.
  - `documents_version` integer, required
  - `documents_layout_version` integer, required

## Other responses

- `400`: Bad request: `VALIDATION_ERROR`, `DOCUMENT_UPLOAD_NOT_FOUND`, `MAX_DOCUMENTS_EXCEEDED`. `MALFORMED_PDF` (see MalformedPdfError) when a page of the PDF has no valid content: `malformed_pages` lists the 1-based page numbers and nothing is written. `VALIDATION_ERROR` "The uploaded document is not a readable PDF" also covers a file that starts like a PDF but whose page tree cannot be read; before 01.40.01 that case answered 500.
- `401`: Unauthorized - Invalid or missing API key
- `404`: NOT_FOUND: the parent uses the single-document path while multi-document editing is suspended, or the template is absent, deleted or not visible to this API key ("Endpoint not found"). DOCUMENT_NOT_FOUND: no document with this id in this template.
- `409`: Conflict: `MULTI_DOCUMENT_READ_ONLY`, `DOCUMENT_SET_VERSION_CONFLICT`, `DOCUMENT_SET_BUSY`, `DOCUMENT_SET_DISPATCH_STALE`, `DOCUMENT_CANDIDATE_EXPIRED`, `DOCUMENT_SET_INCONSISTENT`
- `413`: DOCUMENT_SET_TOO_LARGE: the document set would exceed 104,857,600 bytes
- `429`: Too Many Requests - Rate limit exceeded
- `500`: Internal error (code `INTERNAL`)

## Changes

- **2026-10-17** `a6525941bc28`: 1 breaking, 1 info
  - added `#/components/schemas/MultiDocumentError, #/components/schemas/MalformedPdfError` to the response body `oneOf` list for the response status `400`
  - removed `#/components/schemas/Error, subschema #2` from the response body `allOf` list for the response status `400`
- **2026-10-10** `bfc2b19c9c7e`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/firma/apis/firma-partner-api/changes/templates/:id/documents/post.md)

---

[API](https://skmtc.dev/firma/apis/firma-partner-api.md) - [All operations](https://skmtc.dev/firma/apis/firma-partner-api/llms.txt) - [OpenAPI document](https://skmtc.dev/firma/apis/firma-partner-api/revisions/7326991ebc59?raw)
