Skip to content
SignWithDocs
Esc
  • Developer docs homeDocs
  • ChangelogDocs
  • OverviewREST API · Get started
  • Quick startREST API · Get started
  • Text tagsREST API · Get started
  • AuthenticationREST API · Get started
  • Making requestsREST API · Get started
  • ErrorsREST API · Get started

Templates API reference

Reusable documents with fields and roles, used to create signature requests.

Updated

List templates

get/api/v1/templates
  • Read-only keys can call this

Lists the templates the key's user can access, newest first. Use it to let users pick a template in your app, or to look up a template by your own external_id or by folder. Archived templates are excluded unless archived=true. List items omit fields and documents; fetch a single template to get them.

Query parameters

  • limitinteger

    Number of items per page, 1–100. Values outside that range fall back to 20 (below 1) or 100 (above 100).

    Default 201 to 100
  • cursorinteger

    The next_cursor from the previous page. Omit it for the first page.

  • qstring

    Case-insensitive search on the template name.

  • archivedboolean

    true to list only archived templates instead of active ones.

    Default false
  • external_idstring

    Only templates with this external_id.

  • folderstring

    Only templates in the folder with this exact name.

Request sample

curl https://app.signwith.co/api/v1/templates \
  -H "Authorization: Bearer $SIGNWITH_API_KEY"

Response 200

A page of templates. Each item in data is a template object (list version).

JSON
{
  "object": "list",
  "data": [
    {
      "object": "template",
      "id": 311,
      "name": "Residential lease",
      "external_id": "lease-v3",
      "folder": "Leasing",
      "roles": [
        "Tenant",
        "Landlord"
      ],
      "edit_url": "https://app.signwith.co/templates/311/edit",
      "created_by": {
        "id": 42,
        "email": "[email protected]",
        "name": "Ada Lovelace"
      },
      "archived_at": null,
      "created_at": "2026-09-20T09:12:44Z",
      "updated_at": "2026-09-21T16:03:10Z"
    }
  ],
  "has_more": true,
  "next_cursor": 311
}

Errors

401The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired)
403The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden)
429Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for POST /signature_requests/{id}/remind — signers were reminded less than an hour ago (remind_too_soon, with Retry-After). (rate_limited, remind_too_soon)
500Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error)

Codes listed are the examples the spec gives; see all error codes.

Create a template from documents

post/api/v1/templates

Uploads one or more documents (PDF or image, up to 10 per template, 25 MB each) and creates a template from them. Fillable PDF form fields are converted into template fields automatically.

Text tags. Write fields into the document itself and they're placed where the tag is, with the tag text hidden: {{Client signature;type=signature;role=Client}}. The first part is the field name, followed by key=value settings: type (any field type; default text), role (created on the template if new), required (default true), options (comma-separated, for select) and width/height in points. {{signature;role=Client}} on its own is a signature field named "Signature". The same tag on several pages becomes one field (e.g. initials on every page). When every tag names a role, the template gets exactly those roles. Tags work in PDFs from any editor; keep each one on a line of its own text, or colour it white, for the cleanest result.

To place signature and other fields yourself, pass fields (JSON requests): each field has a type, a role and one or more areas giving its page and position as fractions of the page size. Roles named in fields are created on the template. Otherwise, open the returned edit_url and place fields in the SignWith editor — a template needs at least one field before it can be sent.

Use it to sync documents generated by your system into SignWith. Two request formats are supported:

  • application/json — documents is an array of { name, file } where file is base64 content (a data: URI prefix is allowed) or an https:// URL SignWith downloads.
  • multipart/form-data — upload files directly as documents[].

If name is omitted, the first document's filename is used. If folder doesn't exist it is created. Invalid fields return 422 invalid_field. Triggers the template.created webhook.

Headers

  • Idempotency-Keystring

    A unique value (e.g. a UUID) that makes retries of this request safe. A successful response is stored for 24 hours and replayed for retries with the same key.

    at most 255 characters

Request bodyJSON or multipart/form-data

  • namestring

    Template name. Defaults to the first document's name.

  • external_idstring

    Your own ID for the template.

  • folderstring

    Folder name. Created if it doesn't exist.

  • passwordstring

    Password for encrypted PDFs.

  • documentsarray of objectsRequired
    1 to 10 items
    2 child fields
    • namestring

      Document name. Defaults to Document <n>.

    • filestringRequired

      Base64-encoded PDF or image (a data: URI prefix is allowed), or an https:// URL to download it from. Max 25 MB.

  • fieldsarray of objects

    Fields to place on the documents, in addition to any fillable PDF form fields. Roles named here are added to the template (at most 10 roles).

    6 child fields
    • namestring

      Field name, used as the key in prefill. Defaults to e.g. Signature 2.

    • typestringRequired
      One of text, signature, initials, date, checkbox, number, phone, select, radio, multiple, image, file, stamp
    • rolestring

      Role that fills this field. Created on the template if it doesn't exist. Defaults to the template's first role.

    • requiredboolean
      Default true
    • optionsarray of strings

      Choices for select, radio and multiple fields (required for those types).

    • areasarray of objectsRequired

      Where the field goes. A field can appear in several places.

      at least 1 item
      6 child fields
      • pageintegerRequired

        1-based page number; must exist in the document.

        at least 1
      • xnumberRequired
        0 to 1
      • ynumberRequired
        0 to 1
      • wnumberRequired
        at most 1, greater than 0
      • hnumberRequired
        at most 1, greater than 0
      • documentinteger

        0-based index of the document within the template.

        Default 0at least 0

As multipart/form-data, send the same text fields plus the files:

  • documents[]filesRequired

    PDF or image files, 25 MB max each.

    1 to 10 items

Request sample

curl -X POST https://app.signwith.co/api/v1/templates \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Residential lease",
  "external_id": "lease-v3",
  "folder": "Leasing",
  "documents": [
    {
      "name": "Lease agreement",
      "file": "https://files.acme.co/templates/lease-v3.pdf"
    }
  ]
}'
Example: Base64 document with password
curl -X POST https://app.signwith.co/api/v1/templates \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "NDA",
  "documents": [
    {
      "name": "nda.pdf",
      "file": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFI+PgplbmRvYmoK..."
    }
  ],
  "password": "s3cret"
}'
Example: Document with signature fields placed by the API
curl -X POST https://app.signwith.co/api/v1/templates \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Consulting agreement",
  "documents": [
    {
      "name": "Consulting agreement",
      "file": "https://files.acme.co/contracts/consulting.pdf"
    }
  ],
  "fields": [
    {
      "name": "Client name",
      "type": "text",
      "role": "Client",
      "areas": [
        {
          "page": 1,
          "x": 0.12,
          "y": 0.18,
          "w": 0.35,
          "h": 0.03
        }
      ]
    },
    {
      "name": "Client signature",
      "type": "signature",
      "role": "Client",
      "areas": [
        {
          "page": 3,
          "x": 0.1,
          "y": 0.78,
          "w": 0.3,
          "h": 0.06
        }
      ]
    },
    {
      "name": "Consultant signature",
      "type": "signature",
      "role": "Consultant",
      "areas": [
        {
          "page": 3,
          "x": 0.55,
          "y": 0.78,
          "w": 0.3,
          "h": 0.06
        }
      ]
    },
    {
      "name": "Payment terms",
      "type": "select",
      "role": "Client",
      "required": false,
      "options": [
        "Net 15",
        "Net 30"
      ],
      "areas": [
        {
          "page": 2,
          "x": 0.12,
          "y": 0.42,
          "w": 0.2,
          "h": 0.03
        }
      ]
    }
  ]
}'
Example: upload files with multipart/form-data
curl -X POST https://app.signwith.co/api/v1/templates \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F 'name=Residential lease' \
  -F 'folder=Leasing' \
  -F 'documents[][email protected]' \
  -F 'documents[][email protected]'

Response 201

The template was created. Returns a template object.

Example response: see the example object below.

Errors

400The request body is not valid JSON. (invalid_json)
401The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired)
403The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden)
409A request with the same Idempotency-Key is still being processed. Retry shortly. (idempotency_key_in_use)
422The request is valid JSON but can't be processed. See error.code; the codes each endpoint can return are described in the endpoint's description and in the error table above. (missing_parameter, invalid_parameter, invalid_request, missing_documents, too_many_documents, document_too_large, invalid_document, invalid_file_type, pdf_encrypted, missing_signers, invalid_signer, already_completed, not_open, nothing_to_remind, invalid_field, template_has_no_fields, template_archived, signer_finished, idempotency_key_reused, invalid_discount_code, already_purchased, billing_details_required)
429Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for POST /signature_requests/{id}/remind — signers were reminded less than an hour ago (remind_too_soon, with Retry-After). (rate_limited, remind_too_soon)
500Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error)

Codes listed are the examples the spec gives; see all error codes.

Get a template

get/api/v1/templates/{id}
  • Read-only keys can call this

Returns a template with its roles, fields and documents. Use it to find out which roles to assign signers to and which field names you can prefill before creating a signature request.

Path parameters

  • idintegerRequired

    Template ID.

Request sample

curl https://app.signwith.co/api/v1/templates/311 \
  -H "Authorization: Bearer $SIGNWITH_API_KEY"

Response 200

The template. Returns a template object.

Example response: see the example object below.

Errors

401The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired)
403The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden)
404The resource doesn't exist or belongs to another account. (not_found)
429Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for POST /signature_requests/{id}/remind — signers were reminded less than an hour ago (remind_too_soon, with Retry-After). (rate_limited, remind_too_soon)
500Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error)

Codes listed are the examples the spec gives; see all error codes.

Update a template

patch/api/v1/templates/{id}
  • Needs a full-access key

Renames a template, changes its external_id or folder, renames its roles, or replaces its fields. Use it to keep template metadata in sync with your system, or to place fields on a template created without them. Only the parameters you send are changed.

roles is matched by position: the first name renames the first role, and so on. Extra names add new roles (without fields). Roles can't be removed through the API.

fields, when sent, replaces all of the template's fields (send [] to remove them all). Roles named in fields that don't exist yet are added. Invalid fields return 422 invalid_field.

Changes only affect signature requests sent afterwards: requests already sent keep the fields and documents they were sent with. PUT is accepted as an alias. Triggers the template.updated webhook.

Path parameters

  • idintegerRequired

    Template ID.

Request body

  • namestring
  • external_idstring or null

    Your own ID for the template. Send null to clear it.

  • folderstring

    Folder name. Created if it doesn't exist.

  • rolesarray of strings

    New role names, matched by position. Extra names add roles.

  • fieldsarray of objects

    Replaces all of the template's fields. Roles named here are added if missing.

    6 child fields
    • namestring

      Field name, used as the key in prefill. Defaults to e.g. Signature 2.

    • typestringRequired
      One of text, signature, initials, date, checkbox, number, phone, select, radio, multiple, image, file, stamp
    • rolestring

      Role that fills this field. Created on the template if it doesn't exist. Defaults to the template's first role.

    • requiredboolean
      Default true
    • optionsarray of strings

      Choices for select, radio and multiple fields (required for those types).

    • areasarray of objectsRequired

      Where the field goes. A field can appear in several places.

      at least 1 item
      6 child fields
      • pageintegerRequired

        1-based page number; must exist in the document.

        at least 1
      • xnumberRequired
        0 to 1
      • ynumberRequired
        0 to 1
      • wnumberRequired
        at most 1, greater than 0
      • hnumberRequired
        at most 1, greater than 0
      • documentinteger

        0-based index of the document within the template.

        Default 0at least 0

Request sample

curl -X PATCH https://app.signwith.co/api/v1/templates/311 \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Residential lease (2027)",
  "external_id": "lease-v4",
  "folder": "Leasing",
  "roles": [
    "Tenant",
    "Landlord"
  ]
}'
Example: Replace all fields
curl -X PATCH https://app.signwith.co/api/v1/templates/311 \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fields": [
    {
      "name": "Tenant signature",
      "type": "signature",
      "role": "Tenant",
      "areas": [
        {
          "page": 4,
          "x": 0.1,
          "y": 0.8,
          "w": 0.3,
          "h": 0.06
        }
      ]
    },
    {
      "name": "Landlord signature",
      "type": "signature",
      "role": "Landlord",
      "areas": [
        {
          "page": 4,
          "x": 0.55,
          "y": 0.8,
          "w": 0.3,
          "h": 0.06
        }
      ]
    }
  ]
}'

Response 200

The updated template. Returns a template object.

Example response: see the example object below.

Errors

400The request body is not valid JSON. (invalid_json)
401The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired)
403The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden)
404The resource doesn't exist or belongs to another account. (not_found)
422The request is valid JSON but can't be processed. See error.code; the codes each endpoint can return are described in the endpoint's description and in the error table above. (missing_parameter, invalid_parameter, invalid_request, missing_documents, too_many_documents, document_too_large, invalid_document, invalid_file_type, pdf_encrypted, missing_signers, invalid_signer, already_completed, not_open, nothing_to_remind, invalid_field, template_has_no_fields, template_archived, signer_finished, idempotency_key_reused, invalid_discount_code, already_purchased, billing_details_required)
429Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for POST /signature_requests/{id}/remind — signers were reminded less than an hour ago (remind_too_soon, with Retry-After). (rate_limited, remind_too_soon)
500Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error)

Codes listed are the examples the spec gives; see all error codes.

Duplicate a template

post/api/v1/templates/{id}/duplicate

Creates a copy of a template, including its documents, fields and roles. Use it to create a variant (for example a per-customer version) without re-uploading and re-placing fields. Optionally give the copy a new name, external_id or folder. Triggers the template.created webhook.

Path parameters

  • idintegerRequired

    Template ID.

Headers

  • Idempotency-Keystring

    A unique value (e.g. a UUID) that makes retries of this request safe. A successful response is stored for 24 hours and replayed for retries with the same key.

    at most 255 characters

Request body (optional)

  • namestring

    Name of the copy. Defaults to the original name followed by "(Clone)".

  • external_idstring
  • folderstring

    Folder for the copy. Created if it doesn't exist.

Request sample

curl -X POST https://app.signwith.co/api/v1/templates/311/duplicate \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Residential lease — Riverside Apartments",
  "external_id": "lease-v3-riverside",
  "folder": "Leasing"
}'

Response 201

The new template. Returns a template object.

Example response: see the example object below.

Errors

400The request body is not valid JSON. (invalid_json)
401The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired)
403The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden)
404The resource doesn't exist or belongs to another account. (not_found)
409A request with the same Idempotency-Key is still being processed. Retry shortly. (idempotency_key_in_use)
422The request is valid JSON but can't be processed. See error.code; the codes each endpoint can return are described in the endpoint's description and in the error table above. (missing_parameter, invalid_parameter, invalid_request, missing_documents, too_many_documents, document_too_large, invalid_document, invalid_file_type, pdf_encrypted, missing_signers, invalid_signer, already_completed, not_open, nothing_to_remind, invalid_field, template_has_no_fields, template_archived, signer_finished, idempotency_key_reused, invalid_discount_code, already_purchased, billing_details_required)
429Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for POST /signature_requests/{id}/remind — signers were reminded less than an hour ago (remind_too_soon, with Retry-After). (rate_limited, remind_too_soon)
500Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error)

Codes listed are the examples the spec gives; see all error codes.

Archive a template

post/api/v1/templates/{id}/archive

Archives a template so it no longer shows among active templates. Use it when a document version is retired. Existing signature requests are not affected. Archiving an already archived template succeeds and returns it unchanged. The template.archived webhook fires only the first time. Archived templates can't be used for new signature requests (422 template_archived), and signing links of unfinished requests from them stop working.

Path parameters

  • idintegerRequired

    Template ID.

Headers

  • Idempotency-Keystring

    A unique value (e.g. a UUID) that makes retries of this request safe. A successful response is stored for 24 hours and replayed for retries with the same key.

    at most 255 characters

Request sample

curl -X POST https://app.signwith.co/api/v1/templates/311/archive \
  -H "Authorization: Bearer $SIGNWITH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Response 200

The archived template. Returns a template object.

Example response: see the example object below.

Errors

401The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired)
403The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden)
404The resource doesn't exist or belongs to another account. (not_found)
409A request with the same Idempotency-Key is still being processed. Retry shortly. (idempotency_key_in_use)
429Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for POST /signature_requests/{id}/remind — signers were reminded less than an hour ago (remind_too_soon, with Retry-After). (rate_limited, remind_too_soon)
500Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error)

Codes listed are the examples the spec gives; see all error codes.

The template object

A template, including its fields and documents.

  • objectstringRequired
    Always template
  • idintegerRequired
  • namestringRequired
  • external_idstring or nullRequired

    Your own ID for the template.

  • folderstring or nullRequired

    Name of the folder the template is in.

  • rolesarray of stringsRequired

    Role names in signing order.

  • edit_urlstringRequired

    Opens the template in the SignWith editor, where the user can place or adjust fields.

    URL
  • created_byobject or nullRequired

    A SignWith user (a member of your team).

    3 child fields
    • idintegerRequired
    • emailstringRequired
      email address
    • namestring or nullRequired

      First and last name, or null if not set.

  • archived_atstring (date-time) or nullRequired
  • created_atstring (date-time)Required
  • updated_atstring (date-time)Required
  • fieldsarray of objectsRequired

    A field placed on a template's documents. Keys with no value are omitted.

    6 child fields
    • idstring (uuid)Required

      Stable field ID.

    • namestring

      Field name. Use it as the key in prefill. Omitted if the field has no name.

    • typestringRequired

      Field type, e.g. text, signature, initials, date, number, checkbox, radio, select, multiple, image, file, phone, stamp, cells.

    • rolestring

      Name of the role that fills this field.

    • requiredbooleanRequired

      Whether the signer must fill the field.

    • optionsarray of strings

      Allowed values for select, radio and multiple fields.

  • documentsarray of objectsRequired

    A document (one uploaded file) of a template.

    4 child fields
    • idintegerRequired
    • namestringRequired

      File name without extension.

    • urlstringRequired

      Download link for the original file.

      URL
    • preview_image_urlstring or null

      Image of the first page, if available.

      URL
JSON
{
  "object": "template",
  "id": 311,
  "name": "Residential lease",
  "external_id": "lease-v3",
  "folder": "Leasing",
  "roles": [
    "Tenant",
    "Landlord"
  ],
  "edit_url": "https://app.signwith.co/templates/311/edit",
  "created_by": {
    "id": 42,
    "email": "[email protected]",
    "name": "Ada Lovelace"
  },
  "archived_at": null,
  "created_at": "2026-09-20T09:12:44Z",
  "updated_at": "2026-09-21T16:03:10Z",
  "fields": [
    {
      "id": "0f9c2b7e-5d1a-4e8b-9a61-3c2e7d4f1a90",
      "name": "Tenant name",
      "type": "text",
      "role": "Tenant",
      "required": true
    },
    {
      "id": "6a3e1d42-8b7c-4f19-a0d5-2e9b4c7f8a13",
      "name": "Monthly rent",
      "type": "number",
      "role": "Tenant",
      "required": true
    },
    {
      "id": "b2d8f4a1-3c6e-4a7b-8d92-5f1e0c3a9b76",
      "name": "Start date",
      "type": "date",
      "role": "Tenant",
      "required": true
    },
    {
      "id": "91c7e3b5-2a4d-4f8e-b610-7d3a5c9e2f48",
      "name": "Pets",
      "type": "select",
      "role": "Tenant",
      "required": false,
      "options": [
        "None",
        "Cat",
        "Dog"
      ]
    },
    {
      "id": "4e8a2c6f-9b1d-4a3e-8c57-1f6d0b9e3a24",
      "name": "Tenant signature",
      "type": "signature",
      "role": "Tenant",
      "required": true
    },
    {
      "id": "c5f1a9d3-7e2b-4c8a-9f60-3b8e4d2a7c15",
      "name": "Landlord signature",
      "type": "signature",
      "role": "Landlord",
      "required": true
    }
  ],
  "documents": [
    {
      "id": 7730,
      "name": "Lease agreement",
      "url": "https://app.signwith.co/file/eyJfcmFpbHMiOnsiZGF0YSI6MTIzfX0/lease-agreement.pdf",
      "preview_image_url": "https://app.signwith.co/file/eyJfcmFpbHMiOnsiZGF0YSI6MTI0fX0/0.jpg"
    }
  ]
}

Base URL, pagination and idempotency work the same on every endpoint: see making requests. Every error code is on errors.

Start building

The API and MCP server come with every account. 3 free documents a month, then pay per document.