Skip to content

The Tally Sign API for your own systems

Create documents from your templates, send them, follow every signer and download the signed PDF, over a plain JSON REST API. Webhooks tell your systems the moment something is signed. Included on every plan, with no limit on documents.

Quick start signed in five calls

From an API key to a signed PDF. Everything answers JSON at https://app.tallysign.com/api/v1, and the full description is in the OpenAPI document.

1. Create an API key

In Tally Sign, an owner or admin opens Settings → AI & API and chooses Create key. Copy it then: it's shown once.

export TALLY_API_KEY="tsk_…"

2. Check it works

The answer names your company and whose key it is.

curl https://app.tallysign.com/api/v1/me \
  -H "Authorization: Bearer $TALLY_API_KEY"

3. Pick a template

Each template lists the roles that sign and the variables it needs. Note the id, the client's role and any variable marked required.

curl https://app.tallysign.com/api/v1/templates \
  -H "Authorization: Bearer $TALLY_API_KEY"

4. Create and send it

Name who signs for each role and fill in the variables. With send set to true it goes out at once; your own side fills from your profile.

curl -X POST "https://app.tallysign.com/api/v1/documents" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "templateId": "tpl_7Qm2xKp4Rv",
  "title": "Mutual NDA — Brightline Logistics",
  "variables": {
    "nda.effectiveDate": "October 1, 2026"
  },
  "recipients": [
    {
      "role": "client",
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "title": "VP of Operations",
      "company": "Brightline Logistics"
    }
  ],
  "message": "Here is the NDA we discussed. Thanks, Avery",
  "send": true
}'

5. Follow it, then download it

Each signer's status, when they viewed and signed, what they filled in, and the audit trail. Once it's completed, the PDF is the signed copy with its Certificate of Completion.

curl https://app.tallysign.com/api/v1/documents/$DOCUMENT_ID \
  -H "Authorization: Bearer $TALLY_API_KEY"

curl -L https://app.tallysign.com/api/v1/documents/$DOCUMENT_ID/pdf \
  -H "Authorization: Bearer $TALLY_API_KEY" -o signed.pdf

Authentication an API key per integration

Send the key as a bearer token on every request. Give each integration its own key, so you can see when each was last used and revoke one without touching the others.

Authorization: Bearer tsk_…

One company per key

A key reaches only its own company's templates and documents, the same ones its person sees in the app.

It acts as its person

Documents it sends come from the person who created the key, and the audit trail names them. Their own signature goes only to them.

The same rules as the app

Sending needs an active account; a suspended company or a person whose access was turned off can't use their keys.

Stored as a hash

Tally Sign keeps only a SHA-256 hash of each key. Lost one? Revoke it and create another.

Revoke any time

Settings → AI & API lists every key with when it was last used. Revoking one stops it, and its webhooks, at once.

HTTPS only

Send the key in the Authorization header over HTTPS. Never put it in a web page or a mobile app.

Reference every endpoint

Account

The key itself.

GET/api/v1/me

Check your API key

Which company the key works for and whose key it is. A good first call, and the test Zapier runs when you connect.

Request
curl "https://app.tallysign.com/api/v1/me" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "object": "api_key",
  "key": {
    "name": "Zapier",
    "prefix": "tsk_9fQ2xa"
  },
  "company": {
    "id": "org_Nb4kq2",
    "name": "Northbeam Software"
  },
  "user": {
    "id": "usr_Ab12cd",
    "name": "Avery Brooks",
    "email": "avery@northbeam.example"
  },
  "rateLimit": {
    "limit": 300,
    "windowSeconds": 60
  }
}

Templates

Documents start from a template: your wording, layout and signature blocks. Make them in Tally Sign.

GET/api/v1/templates

List templates

Your company's templates, oldest first, each with the roles it expects and every {{variable}} it uses.

Request
curl "https://app.tallysign.com/api/v1/templates" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "tpl_7Qm2xKp4Rv",
      "object": "template",
      "title": "Mutual Non-Disclosure Agreement",
      "description": "Two-way confidentiality agreement with a deal summary, plain-English intent and 15 standard sections.",
      "category": "nda",
      "createdAt": "2026-09-02T16:20:11.000Z",
      "updatedAt": "2026-09-18T09:41:37.000Z",
      "roles": [
        {
          "role": "sender",
          "label": "Your company",
          "type": "signer",
          "isSender": true,
          "order": 0,
          "name": "",
          "email": ""
        },
        {
          "role": "client",
          "label": "Counterparty",
          "type": "signer",
          "isSender": false,
          "order": 1,
          "name": "",
          "email": ""
        }
      ],
      "variables": [
        {
          "key": "client.company",
          "label": "Client company",
          "required": true,
          "kind": "recipient"
        },
        {
          "key": "client.name",
          "label": "Client name",
          "required": true,
          "kind": "recipient"
        },
        {
          "key": "nda.effectiveDate",
          "label": "NDA effective date",
          "default": "",
          "required": true,
          "kind": "variable"
        },
        {
          "key": "nda.purpose",
          "label": "NDA purpose",
          "default": "Evaluating, negotiating, and/or performing a potential business relationship between the parties.",
          "required": false,
          "kind": "variable"
        },
        {
          "key": "nda.termYears",
          "label": "NDA term years",
          "default": "three (3)",
          "required": false,
          "kind": "variable"
        },
        {
          "key": "org.legalName",
          "label": "Company legal name",
          "required": false,
          "kind": "company"
        },
        {
          "key": "today",
          "label": "Today",
          "required": false,
          "kind": "builtin"
        }
      ]
    }
  ],
  "hasMore": false,
  "nextCursor": null
}
GET/api/v1/templates/{id}

Get a template

One template, with its roles and variables: what to pass when you create a document from it.

Path

idrequired
string

Errors: not_found.

Request
curl "https://app.tallysign.com/api/v1/templates/$ID" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "id": "tpl_7Qm2xKp4Rv",
  "object": "template",
  "title": "Mutual Non-Disclosure Agreement",
  "description": "Two-way confidentiality agreement with a deal summary, plain-English intent and 15 standard sections.",
  "category": "nda",
  "createdAt": "2026-09-02T16:20:11.000Z",
  "updatedAt": "2026-09-18T09:41:37.000Z",
  "roles": [
    {
      "role": "sender",
      "label": "Your company",
      "type": "signer",
      "isSender": true,
      "order": 0,
      "name": "",
      "email": ""
    },
    {
      "role": "client",
      "label": "Counterparty",
      "type": "signer",
      "isSender": false,
      "order": 1,
      "name": "",
      "email": ""
    }
  ],
  "variables": [
    {
      "key": "client.company",
      "label": "Client company",
      "required": true,
      "kind": "recipient"
    },
    {
      "key": "client.name",
      "label": "Client name",
      "required": true,
      "kind": "recipient"
    },
    {
      "key": "nda.effectiveDate",
      "label": "NDA effective date",
      "default": "",
      "required": true,
      "kind": "variable"
    },
    {
      "key": "nda.purpose",
      "label": "NDA purpose",
      "default": "Evaluating, negotiating, and/or performing a potential business relationship between the parties.",
      "required": false,
      "kind": "variable"
    },
    {
      "key": "nda.termYears",
      "label": "NDA term years",
      "default": "three (3)",
      "required": false,
      "kind": "variable"
    },
    {
      "key": "org.legalName",
      "label": "Company legal name",
      "required": false,
      "kind": "company"
    },
    {
      "key": "today",
      "label": "Today",
      "required": false,
      "kind": "builtin"
    }
  ]
}

Documents

Create from a template, send, remind, void, follow and download.

GET/api/v1/documents

List documents

Documents, most recently changed first. Filter by status, change time, template or a search, and page with cursor.

Query

status
string
Only these statuses, comma-separated: sent,completed.
updatedSince
date-time
Only documents changed at or after this time (ISO 8601).
q
string
Search titles and descriptions.
templateId
string
Only documents made from this template.
limit
integer
Page size, 1 to 100 (default 25).
cursor
string
nextCursor from the previous page.

Errors: invalid_request.

Request
curl "https://app.tallysign.com/api/v1/documents?status=sent,completed&updatedSince=2026-10-01T00:00:00Z&limit=10" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "doc_3Hn8wLc2Tz",
      "object": "document",
      "title": "Mutual NDA — Brightline Logistics",
      "status": "sent",
      "category": "nda",
      "templateId": "tpl_7Qm2xKp4Rv",
      "createdAt": "2026-10-01T15:02:44.000Z",
      "updatedAt": "2026-10-01T15:02:47.000Z",
      "sentAt": "2026-10-01T15:02:47.000Z",
      "completedAt": null,
      "expiresAt": "2026-11-30T15:02:47.000Z",
      "url": "https://app.tallysign.com/documents/doc_3Hn8wLc2Tz",
      "recipients": [
        {
          "id": "rcp_Ns1aV0bQ",
          "role": "sender",
          "roleLabel": "Your company",
          "type": "signer",
          "name": "Avery Brooks",
          "email": "avery@northbeam.example",
          "company": "Northbeam Software, Inc.",
          "isSender": true,
          "status": "sent"
        },
        {
          "id": "rcp_Bl9dWh2K",
          "role": "client",
          "roleLabel": "Counterparty",
          "type": "signer",
          "name": "Dana Whitfield",
          "email": "dana@brightline.example",
          "company": "Brightline Logistics",
          "isSender": false,
          "status": "sent"
        }
      ]
    }
  ],
  "hasMore": true,
  "nextCursor": "eyJ1IjoiMjAyNi0xMC0wMVQxNTowMjo0Ny4wMDBaIiwiaSI6ImRvY18zSG44d0xjMlR6In0"
}
POST/api/v1/documents

Create a document from a template

Makes a draft from a template: name who signs for each role, fill in variables, and choose how it's sent. With send: true it goes out for signature at once; if anything is missing, nothing is created and the answer (not_ready) lists what. Your own side fills from the API key's person and company profile.

Body

templateIdrequired
string
The template to start from (GET /templates).
title
string
Document title (default: the template's).
variables
object
Values for the template's {{variables}}, by key.
recipients
RecipientInput[]
signingOrder
"parallel" | "sequential"
sequential asks signers one after another by order. Default: everyone at once.
expiresInDays
integer
Days until the signing links stop working (default 60). 1 to 365.
subject
string
Email subject of the signing request.
message
string
Personal note in the signing request email.
send
boolean
Send it for signature right away. If anything is missing, nothing is created and the answer lists what.

Each recipient

rolerequired
string
A role from the template (roles[].role), or a new one to add a signer.
name
string
email
string
title
string
company
string
order
integer
Signing order when signingOrder is sequential. 0 to 100.

Takes an Idempotency-Key header.

Errors: invalid_request, not_found, not_ready, billing_paused.

Request
curl -X POST "https://app.tallysign.com/api/v1/documents" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "templateId": "tpl_7Qm2xKp4Rv",
  "title": "Mutual NDA — Brightline Logistics",
  "variables": {
    "nda.effectiveDate": "October 1, 2026"
  },
  "recipients": [
    {
      "role": "client",
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "title": "VP of Operations",
      "company": "Brightline Logistics"
    }
  ],
  "message": "Here is the NDA we discussed. Thanks, Avery",
  "send": true
}'
Response · 201
{
  "id": "doc_3Hn8wLc2Tz",
  "object": "document",
  "title": "Mutual NDA — Brightline Logistics",
  "status": "sent",
  "category": "nda",
  "templateId": "tpl_7Qm2xKp4Rv",
  "createdAt": "2026-10-01T15:02:44.000Z",
  "updatedAt": "2026-10-01T15:02:47.000Z",
  "sentAt": "2026-10-01T15:02:47.000Z",
  "completedAt": null,
  "expiresAt": "2026-11-30T15:02:47.000Z",
  "url": "https://app.tallysign.com/documents/doc_3Hn8wLc2Tz",
  "recipients": [
    {
      "id": "rcp_Ns1aV0bQ",
      "role": "sender",
      "roleLabel": "Your company",
      "type": "signer",
      "name": "Avery Brooks",
      "email": "avery@northbeam.example",
      "company": "Northbeam Software, Inc.",
      "isSender": true,
      "status": "sent",
      "title": "COO",
      "order": 0,
      "viewedAt": null,
      "signedAt": null,
      "declinedReason": null,
      "fields": [],
      "fieldValues": {}
    },
    {
      "id": "rcp_Bl9dWh2K",
      "role": "client",
      "roleLabel": "Counterparty",
      "type": "signer",
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "company": "Brightline Logistics",
      "isSender": false,
      "status": "sent",
      "title": "VP of Operations",
      "order": 1,
      "viewedAt": null,
      "signedAt": null,
      "declinedReason": null,
      "fields": [],
      "fieldValues": {}
    }
  ],
  "signingOrder": "parallel",
  "subject": null,
  "message": "Here is the NDA we discussed. Thanks, Avery",
  "variables": {
    "nda.effectiveDate": "October 1, 2026",
    "nda.purpose": "Evaluating, negotiating, and/or performing a potential business relationship between the parties.",
    "nda.termYears": "three (3)"
  },
  "fieldValues": {},
  "hasSignedPdf": false,
  "pdfUrl": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/pdf",
  "events": [
    {
      "type": "email_sent",
      "detail": "Signing request emailed to Dana Whitfield <dana@brightline.example>",
      "at": "2026-10-01T15:02:48.000Z",
      "recipientId": "rcp_Bl9dWh2K"
    },
    {
      "type": "email_sent",
      "detail": "Signing request emailed to Avery Brooks <avery@northbeam.example>",
      "at": "2026-10-01T15:02:48.000Z",
      "recipientId": "rcp_Ns1aV0bQ"
    },
    {
      "type": "sent",
      "detail": "Sent for signature to Avery Brooks, Dana Whitfield",
      "at": "2026-10-01T15:02:47.000Z",
      "recipientId": null
    },
    {
      "type": "created",
      "detail": "Created through the API",
      "at": "2026-10-01T15:02:44.000Z",
      "recipientId": null
    }
  ]
}
GET/api/v1/documents/{id}

Get a document

Status, every recipient with when they viewed and signed, what each signer filled in, and the audit trail. A signer's fields and fieldValues fill in once they sign (until then they're empty: entries before signing aren't agreed to), and fieldValues on the document merges every signer's. Files signers uploaded are listed with a link to download them with your API key.

Path

idrequired
string

Errors: not_found.

Request
curl "https://app.tallysign.com/api/v1/documents/$ID" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "id": "doc_3Hn8wLc2Tz",
  "object": "document",
  "title": "Mutual NDA — Brightline Logistics",
  "status": "sent",
  "category": "nda",
  "templateId": "tpl_7Qm2xKp4Rv",
  "createdAt": "2026-10-01T15:02:44.000Z",
  "updatedAt": "2026-10-01T17:44:09.000Z",
  "sentAt": "2026-10-01T15:02:47.000Z",
  "completedAt": null,
  "expiresAt": "2026-11-30T15:02:47.000Z",
  "url": "https://app.tallysign.com/documents/doc_3Hn8wLc2Tz",
  "recipients": [
    {
      "id": "rcp_Ns1aV0bQ",
      "role": "sender",
      "roleLabel": "Your company",
      "type": "signer",
      "name": "Avery Brooks",
      "email": "avery@northbeam.example",
      "company": "Northbeam Software, Inc.",
      "isSender": true,
      "status": "sent",
      "title": "COO",
      "order": 0,
      "viewedAt": null,
      "signedAt": null,
      "declinedReason": null,
      "fields": [],
      "fieldValues": {}
    },
    {
      "id": "rcp_Bl9dWh2K",
      "role": "client",
      "roleLabel": "Counterparty",
      "type": "signer",
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "company": "Brightline Logistics",
      "isSender": false,
      "status": "signed",
      "title": "VP of Operations",
      "order": 1,
      "viewedAt": "2026-10-01T17:42:51.000Z",
      "signedAt": "2026-10-01T17:44:09.000Z",
      "declinedReason": null,
      "fields": [
        {
          "id": "f_Nm3kQ8",
          "type": "name",
          "label": "Full name",
          "key": "Full name",
          "value": "Dana Whitfield"
        },
        {
          "id": "f_Tt7wL2",
          "type": "title",
          "label": "Title",
          "key": "Title",
          "value": "VP of Operations"
        },
        {
          "id": "f_Ds4pR9",
          "type": "date",
          "label": "Date signed",
          "key": "Date signed",
          "value": "2026-10-01"
        },
        {
          "id": "f_Ne1xC5",
          "type": "text",
          "label": "Email for notices",
          "key": "Email for notices",
          "value": "legal@brightline.example"
        },
        {
          "id": "f_Em6hB0",
          "type": "number",
          "label": "Number of employees",
          "key": "Number of employees",
          "value": 240
        },
        {
          "id": "f_Rg2vJ7",
          "type": "dropdown",
          "label": "Region",
          "key": "Region",
          "value": "North America"
        },
        {
          "id": "f_Pd8sK3",
          "type": "dateInput",
          "label": "Disclosures start",
          "key": "Disclosures start",
          "value": "2026-10-15"
        },
        {
          "id": "f_Cb5mT1",
          "type": "checkbox",
          "label": "Share with affiliates",
          "key": "Share with affiliates",
          "value": false
        },
        {
          "id": "f_Fl9qW4",
          "type": "file",
          "label": "Certificate of insurance",
          "key": "Certificate of insurance",
          "value": "Brightline COI 2026.pdf",
          "files": [
            {
              "id": "sf_Hq2cV8xWm4Lp0aTz9Ke",
              "filename": "Brightline COI 2026.pdf",
              "size": 186412,
              "contentType": "application/pdf",
              "sha256": "9b2f4c0e7a1d3e5f8c6b9a0d2e4f6a8c1b3d5e7f9a0c2e4b6d8f0a1c3e5b7d9f",
              "uploadedAt": "2026-10-01T17:43:30.000Z",
              "url": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/files/sf_Hq2cV8xWm4Lp0aTz9Ke"
            }
          ]
        }
      ],
      "fieldValues": {
        "Full name": "Dana Whitfield",
        "Title": "VP of Operations",
        "Date signed": "2026-10-01",
        "Email for notices": "legal@brightline.example",
        "Number of employees": 240,
        "Region": "North America",
        "Disclosures start": "2026-10-15",
        "Share with affiliates": false,
        "Certificate of insurance": "Brightline COI 2026.pdf"
      }
    }
  ],
  "signingOrder": "parallel",
  "subject": null,
  "message": "Here is the NDA we discussed. Thanks, Avery",
  "variables": {
    "nda.effectiveDate": "October 1, 2026",
    "nda.purpose": "Evaluating, negotiating, and/or performing a potential business relationship between the parties.",
    "nda.termYears": "three (3)"
  },
  "fieldValues": {
    "Full name": "Dana Whitfield",
    "Title": "VP of Operations",
    "Date signed": "2026-10-01",
    "Email for notices": "legal@brightline.example",
    "Number of employees": 240,
    "Region": "North America",
    "Disclosures start": "2026-10-15",
    "Share with affiliates": false,
    "Certificate of insurance": "Brightline COI 2026.pdf"
  },
  "hasSignedPdf": false,
  "pdfUrl": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/pdf",
  "events": [
    {
      "type": "signed",
      "detail": "Signed by Dana Whitfield <dana@brightline.example>",
      "at": "2026-10-01T17:44:09.000Z",
      "recipientId": "rcp_Bl9dWh2K"
    },
    {
      "type": "file_uploaded",
      "detail": "Dana Whitfield <dana@brightline.example> uploaded “Brightline COI 2026.pdf” (182 KB, SHA-256 9b2f4c0e…) for “Certificate of insurance”",
      "at": "2026-10-01T17:44:09.000Z",
      "recipientId": "rcp_Bl9dWh2K"
    },
    {
      "type": "email_sent",
      "detail": "Signing request emailed to Dana Whitfield <dana@brightline.example>",
      "at": "2026-10-01T15:02:48.000Z",
      "recipientId": "rcp_Bl9dWh2K"
    },
    {
      "type": "email_sent",
      "detail": "Signing request emailed to Avery Brooks <avery@northbeam.example>",
      "at": "2026-10-01T15:02:48.000Z",
      "recipientId": "rcp_Ns1aV0bQ"
    },
    {
      "type": "sent",
      "detail": "Sent for signature to Avery Brooks, Dana Whitfield",
      "at": "2026-10-01T15:02:47.000Z",
      "recipientId": null
    },
    {
      "type": "created",
      "detail": "Created through the API",
      "at": "2026-10-01T15:02:44.000Z",
      "recipientId": null
    }
  ]
}
DELETE/api/v1/documents/{id}

Delete a draft or voided document

Sent, completed and declined documents are part of the signing record and can't be deleted. Void a sent one instead.

Path

idrequired
string

Errors: not_found, not_deletable.

Request
curl -X DELETE "https://app.tallysign.com/api/v1/documents/$ID" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "id": "doc_3Hn8wLc2Tz",
  "object": "document",
  "deleted": true
}
POST/api/v1/documents/{id}/send

Send a draft for signature

Emails each signer their own signing link (the first ones only, when signing in order). Answers not_ready with the list of what's missing when it can't be sent yet.

Path

idrequired
string

Body

signingOrder
"parallel" | "sequential"
sequential asks signers one after another by order. Default: everyone at once.
expiresInDays
integer
Days until the signing links stop working (default 60). 1 to 365.
subject
string
Email subject of the signing request.
message
string
Personal note in the signing request email.

Takes an Idempotency-Key header.

Errors: not_found, not_ready, conflict, billing_paused.

Request
curl -X POST "https://app.tallysign.com/api/v1/documents/$ID/send" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "signingOrder": "sequential",
  "expiresInDays": 30,
  "message": "Here is the NDA we discussed. Thanks, Avery"
}'
Response · 200
{
  "document": {
    "id": "doc_3Hn8wLc2Tz",
    "object": "document",
    "title": "Mutual NDA — Brightline Logistics",
    "status": "sent",
    "category": "nda",
    "templateId": "tpl_7Qm2xKp4Rv",
    "createdAt": "2026-10-01T15:02:44.000Z",
    "updatedAt": "2026-10-01T15:02:47.000Z",
    "sentAt": "2026-10-01T15:02:47.000Z",
    "completedAt": null,
    "expiresAt": "2026-11-30T15:02:47.000Z",
    "url": "https://app.tallysign.com/documents/doc_3Hn8wLc2Tz",
    "recipients": [
      {
        "id": "rcp_Ns1aV0bQ",
        "role": "sender",
        "roleLabel": "Your company",
        "type": "signer",
        "name": "Avery Brooks",
        "email": "avery@northbeam.example",
        "company": "Northbeam Software, Inc.",
        "isSender": true,
        "status": "sent",
        "title": "COO",
        "order": 0,
        "viewedAt": null,
        "signedAt": null,
        "declinedReason": null,
        "fields": [],
        "fieldValues": {}
      },
      {
        "id": "rcp_Bl9dWh2K",
        "role": "client",
        "roleLabel": "Counterparty",
        "type": "signer",
        "name": "Dana Whitfield",
        "email": "dana@brightline.example",
        "company": "Brightline Logistics",
        "isSender": false,
        "status": "sent",
        "title": "VP of Operations",
        "order": 1,
        "viewedAt": null,
        "signedAt": null,
        "declinedReason": null,
        "fields": [],
        "fieldValues": {}
      }
    ],
    "signingOrder": "parallel",
    "subject": null,
    "message": "Here is the NDA we discussed. Thanks, Avery",
    "variables": {
      "nda.effectiveDate": "October 1, 2026",
      "nda.purpose": "Evaluating, negotiating, and/or performing a potential business relationship between the parties.",
      "nda.termYears": "three (3)"
    },
    "fieldValues": {},
    "hasSignedPdf": false,
    "pdfUrl": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/pdf",
    "events": [
      {
        "type": "email_sent",
        "detail": "Signing request emailed to Dana Whitfield <dana@brightline.example>",
        "at": "2026-10-01T15:02:48.000Z",
        "recipientId": "rcp_Bl9dWh2K"
      },
      {
        "type": "email_sent",
        "detail": "Signing request emailed to Avery Brooks <avery@northbeam.example>",
        "at": "2026-10-01T15:02:48.000Z",
        "recipientId": "rcp_Ns1aV0bQ"
      },
      {
        "type": "sent",
        "detail": "Sent for signature to Avery Brooks, Dana Whitfield",
        "at": "2026-10-01T15:02:47.000Z",
        "recipientId": null
      },
      {
        "type": "created",
        "detail": "Created through the API",
        "at": "2026-10-01T15:02:44.000Z",
        "recipientId": null
      }
    ]
  },
  "deliveries": [
    {
      "name": "Avery Brooks",
      "email": "avery@northbeam.example",
      "delivered": true
    },
    {
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "delivered": true
    }
  ]
}
POST/api/v1/documents/{id}/remind

Remind signers

Emails a reminder to everyone still waiting to sign, or to one signer. Each signer is reminded at most once an hour.

Path

idrequired
string

Body

recipientId
string
Remind only this signer.
role
string
Remind only the signer with this role.
message
string
A note in the reminder.

Takes an Idempotency-Key header.

Errors: not_found, invalid_request, too_soon.

Request
curl -X POST "https://app.tallysign.com/api/v1/documents/$ID/remind" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "role": "client",
  "message": "A reminder about the NDA. Thanks!"
}'
Response · 200
{
  "documentId": "doc_3Hn8wLc2Tz",
  "reminded": [
    {
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "delivered": true
    }
  ]
}
POST/api/v1/documents/{id}/void

Void a document

Cancels a document that's awaiting signatures. Its signing links stop working, and signers who had it are told (unless your company turned that email off).

Path

idrequired
string

Body

reason
string
Recorded in the audit trail and included in the void notice to signers.

Takes an Idempotency-Key header.

Errors: not_found, conflict.

Request
curl -X POST "https://app.tallysign.com/api/v1/documents/$ID/void" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "reason": "Replaced by the revised NDA."
}'
Response · 200
{
  "id": "doc_3Hn8wLc2Tz",
  "object": "document",
  "title": "Mutual NDA — Brightline Logistics",
  "status": "voided",
  "category": "nda",
  "templateId": "tpl_7Qm2xKp4Rv",
  "createdAt": "2026-10-01T15:02:44.000Z",
  "updatedAt": "2026-10-01T15:02:47.000Z",
  "sentAt": "2026-10-01T15:02:47.000Z",
  "completedAt": null,
  "expiresAt": "2026-11-30T15:02:47.000Z",
  "url": "https://app.tallysign.com/documents/doc_3Hn8wLc2Tz",
  "recipients": [
    {
      "id": "rcp_Ns1aV0bQ",
      "role": "sender",
      "roleLabel": "Your company",
      "type": "signer",
      "name": "Avery Brooks",
      "email": "avery@northbeam.example",
      "company": "Northbeam Software, Inc.",
      "isSender": true,
      "status": "sent",
      "title": "COO",
      "order": 0,
      "viewedAt": null,
      "signedAt": null,
      "declinedReason": null,
      "fields": [],
      "fieldValues": {}
    },
    {
      "id": "rcp_Bl9dWh2K",
      "role": "client",
      "roleLabel": "Counterparty",
      "type": "signer",
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "company": "Brightline Logistics",
      "isSender": false,
      "status": "sent",
      "title": "VP of Operations",
      "order": 1,
      "viewedAt": null,
      "signedAt": null,
      "declinedReason": null,
      "fields": [],
      "fieldValues": {}
    }
  ],
  "signingOrder": "parallel",
  "subject": null,
  "message": "Here is the NDA we discussed. Thanks, Avery",
  "variables": {
    "nda.effectiveDate": "October 1, 2026",
    "nda.purpose": "Evaluating, negotiating, and/or performing a potential business relationship between the parties.",
    "nda.termYears": "three (3)"
  },
  "fieldValues": {},
  "hasSignedPdf": false,
  "pdfUrl": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/pdf",
  "events": [
    {
      "type": "email_sent",
      "detail": "Signing request emailed to Dana Whitfield <dana@brightline.example>",
      "at": "2026-10-01T15:02:48.000Z",
      "recipientId": "rcp_Bl9dWh2K"
    },
    {
      "type": "email_sent",
      "detail": "Signing request emailed to Avery Brooks <avery@northbeam.example>",
      "at": "2026-10-01T15:02:48.000Z",
      "recipientId": "rcp_Ns1aV0bQ"
    },
    {
      "type": "sent",
      "detail": "Sent for signature to Avery Brooks, Dana Whitfield",
      "at": "2026-10-01T15:02:47.000Z",
      "recipientId": null
    },
    {
      "type": "created",
      "detail": "Created through the API",
      "at": "2026-10-01T15:02:44.000Z",
      "recipientId": null
    }
  ]
}
GET/api/v1/documents/{id}/pdf

Download the PDF

A completed document's signed PDF: every page as signed, its exhibits, and the Certificate of Completion with the audit trail at the end. Before it's completed, a preview of the document as it stands (add preview=true to always get the preview). The answer may be a redirect to a short-lived file link: follow it (curl -L).

Path

idrequired
string

Errors: not_found.

Request
curl -L "https://app.tallysign.com/api/v1/documents/$ID/pdf" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -o signed.pdf

Response · 200: The PDF.

GET/api/v1/documents/{id}/files/{fileId}

Download a signer's file

A file a signer uploaded into a File upload field, once they've signed with it: a PDF, or a JPEG or PNG image, under the name it had. Its id and url are in the signer's fields (files). The answer may be a redirect to a short-lived file link: follow it (curl -L).

Path

idrequired
string
fileIdrequired
string

Errors: not_found.

Request
curl -L "https://app.tallysign.com/api/v1/documents/$ID/files/$FILE_ID" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -OJ

Response · 200: The file.

Webhook subscriptions

Have Tally Sign post events to your URL. What arrives is described under Webhooks below.

GET/api/v1/webhooks

List webhook subscriptions

The subscriptions this API key made.

Request
curl "https://app.tallysign.com/api/v1/webhooks" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "object": "list",
  "data": [
    {
      "id": "whk_5Jr0pYt8Gs",
      "object": "webhook",
      "url": "https://hooks.zapier.com/hooks/standard/1234567/abcdef/",
      "events": [
        "document.completed"
      ],
      "description": "Zapier: completed NDAs to the shared drive",
      "createdAt": "2026-10-02T10:15:00.000Z",
      "lastDeliveryAt": null,
      "lastError": null
    }
  ],
  "hasMore": false,
  "nextCursor": null
}
POST/api/v1/webhooks

Subscribe to events

Tally Sign posts each event you pick to your URL as JSON, signed with the subscription's secret. Failed deliveries are retried for about a day. Answering 410 Gone removes the subscription. Only company owners' and admins' keys can subscribe.

Body

urlrequired
string
Public https URL that receives the events.
eventsrequired
("document.sent" | "recipient.viewed" | "recipient.signed" | "document.completed" | "document.declined" | "document.voided" | "document.expired")[]
Which events to send.
description
string
A note so you can tell subscriptions apart, e.g. Zapier: signed NDAs to Slack.

Takes an Idempotency-Key header.

Errors: invalid_request, forbidden.

Request
curl -X POST "https://app.tallysign.com/api/v1/webhooks" \
  -H "Authorization: Bearer $TALLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "url": "https://hooks.zapier.com/hooks/standard/1234567/abcdef/",
  "events": [
    "document.completed"
  ],
  "description": "Zapier: completed NDAs to the shared drive"
}'
Response · 201
{
  "id": "whk_5Jr0pYt8Gs",
  "object": "webhook",
  "url": "https://hooks.zapier.com/hooks/standard/1234567/abcdef/",
  "events": [
    "document.completed"
  ],
  "description": "Zapier: completed NDAs to the shared drive",
  "createdAt": "2026-10-02T10:15:00.000Z",
  "lastDeliveryAt": null,
  "lastError": null,
  "secret": "whsec_4mZq9Tn2bW7yLc0aRf5uXe1k"
}
DELETE/api/v1/webhooks/{id}

Unsubscribe

Stops the subscription. Deliveries still waiting are dropped.

Path

idrequired
string

Errors: not_found.

Request
curl -X DELETE "https://app.tallysign.com/api/v1/webhooks/$ID" \
  -H "Authorization: Bearer $TALLY_API_KEY"
Response · 200
{
  "id": "whk_5Jr0pYt8Gs",
  "object": "webhook",
  "deleted": true
}

What signers filled in typed values, ready for a spreadsheet

Every recipient on a document, and every webhook about one, carries what that signer entered: each field with its label and typed value, the same as one flat object for no-code tools, and the files they uploaded.

  • A signer's fields and fieldValues fill in once they sign. Until then they're empty: what someone types before signing isn't agreed to.
  • Values are typed: a number as a number, a checkbox as true or false, a dropdown or radio as the option chosen, a date they picked and the date they signed as YYYY-MM-DD, anything else as text. Left empty: null.
  • Signatures and initials aren't listed (signedAt says they signed), nor conditional fields that stayed hidden.
  • fieldValues keys are the field's label as you wrote it in the template, or its type (Text) when it has none. A label used twice by one signer becomes Label (2), Label (3) in page order.
  • The document's fieldValues merges every signer's. A key two signers share is prefixed by the role label: Counterparty: Company. Keys come from the document as sent, so they stay the same as more people sign. Read values by key: the order of an object's keys isn't guaranteed (fields is in page order).
  • File uploads give the file's name as the value, and the file under files with its size, type and SHA-256. Download it with your API key from url.

Each field

idrequired
string
The field's id in the document.
typerequired
"name" | "title" | "company" | "email" | "date" | "text" | "checkbox" | "dropdown" | "radio" | "number" | "dateInput" | "file"
date is the date they signed; dateInput a date they picked.
labelrequired
string
The field's label as the sender wrote it; its type (e.g. Text) when it has none.
keyrequired
string
Its key in fieldValues: the label, made unique per signer as Label (2), Label (3) in page order.
valuerequired
string | number | boolean | null
Typed: a number as a number, a checkbox as true or false, a dropdown or radio as the option chosen, date and dateInput as YYYY-MM-DD, a file upload as the file's name, anything else as text. null when left empty.
files
SignerFile[]
File upload fields: the file they signed with.

Each file

idrequired
string
filenamerequired
string
The name the signer's file had.
sizerequired
integer
Bytes. -9007199254740991 to 9007199254740991.
contentTyperequired
string
application/pdf, image/jpeg or image/png (checked from the file itself).
sha256required
string
SHA-256 of the file, hex: the fingerprint on the Certificate of Completion.
uploadedAtrequired
date-time
When the signer uploaded it.
urlrequired
string
Download it with your API key (GET /documents/{id}/files/{fileId}). Not a public link.
A signer who has signed (part of their fields, and all of fieldValues)
{
  "fields": [
    {
      "id": "f_Em6hB0",
      "type": "number",
      "label": "Number of employees",
      "key": "Number of employees",
      "value": 240
    },
    {
      "id": "f_Rg2vJ7",
      "type": "dropdown",
      "label": "Region",
      "key": "Region",
      "value": "North America"
    },
    {
      "id": "f_Pd8sK3",
      "type": "dateInput",
      "label": "Disclosures start",
      "key": "Disclosures start",
      "value": "2026-10-15"
    },
    {
      "id": "f_Cb5mT1",
      "type": "checkbox",
      "label": "Share with affiliates",
      "key": "Share with affiliates",
      "value": false
    },
    {
      "id": "f_Fl9qW4",
      "type": "file",
      "label": "Certificate of insurance",
      "key": "Certificate of insurance",
      "value": "Brightline COI 2026.pdf",
      "files": [
        {
          "id": "sf_Hq2cV8xWm4Lp0aTz9Ke",
          "filename": "Brightline COI 2026.pdf",
          "size": 186412,
          "contentType": "application/pdf",
          "sha256": "9b2f4c0e7a1d3e5f8c6b9a0d2e4f6a8c1b3d5e7f9a0c2e4b6d8f0a1c3e5b7d9f",
          "uploadedAt": "2026-10-01T17:43:30.000Z",
          "url": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/files/sf_Hq2cV8xWm4Lp0aTz9Ke"
        }
      ]
    }
  ],
  "fieldValues": {
    "Full name": "Dana Whitfield",
    "Title": "VP of Operations",
    "Date signed": "2026-10-01",
    "Email for notices": "legal@brightline.example",
    "Number of employees": 240,
    "Region": "North America",
    "Disclosures start": "2026-10-15",
    "Share with affiliates": false,
    "Certificate of insurance": "Brightline COI 2026.pdf"
  }
}

Webhooks told the moment it's signed

Subscribe a URL to the events you care about with POST /api/v1/webhooks. Tally Sign posts each one as JSON, signed with the subscription's secret. Automations can send the same payload to a URL too, without code.

Events

document.sentA document was sent for signature (again, when an edited version is sent).
recipient.viewedA signer opened the document and interacted with it for the first time (link scanners don't count).
recipient.signedA signer signed. Sent for every signer, your own side included.
document.completedEveryone has signed. The signed PDF is ready to download.
document.declinedA signer declined to sign. recipient.declinedReason says why.
document.voidedA document awaiting signatures was voided.
document.expiredThe signing links expired before everyone signed.

Delivery

  • Answer with any 2xx within 10 seconds. Do the slow work afterwards.
  • Anything else is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours, then dropped. The id stays the same on every retry, so you can ignore repeats.
  • Answering 410 Gone deletes the subscription.
  • Only public https addresses receive events. Redirects aren't followed.
  • Headers: X-Tally-Event, X-Tally-Delivery and X-Tally-Signature.
  • Admins see every subscription in Settings → AI & API and can remove any of them. Revoking a key removes its subscriptions.
What your URL receives (recipient.signed)
{
  "id": "whd_W2fK8nQx0aLm",
  "event": "recipient.signed",
  "at": "2026-10-01T17:44:09.512Z",
  "subscription": {
    "id": "whk_5Jr0pYt8Gs"
  },
  "document": {
    "id": "doc_3Hn8wLc2Tz",
    "title": "Mutual NDA — Brightline Logistics",
    "status": "sent",
    "url": "https://app.tallysign.com/documents/doc_3Hn8wLc2Tz",
    "total": 0,
    "currency": null,
    "sentAt": "2026-10-01T15:02:47.000Z",
    "completedAt": null,
    "expiresAt": "2026-11-30T15:02:47.000Z",
    "templateId": "tpl_7Qm2xKp4Rv",
    "signedPdfUrl": null,
    "salesforce": null,
    "fieldValues": {
      "Full name": "Dana Whitfield",
      "Title": "VP of Operations",
      "Date signed": "2026-10-01",
      "Email for notices": "legal@brightline.example",
      "Number of employees": 240,
      "Region": "North America",
      "Disclosures start": "2026-10-15",
      "Share with affiliates": false,
      "Certificate of insurance": "Brightline COI 2026.pdf"
    }
  },
  "recipients": [
    {
      "id": "rcp_Ns1aV0bQ",
      "role": "sender",
      "name": "Avery Brooks",
      "email": "avery@northbeam.example",
      "company": "Northbeam Software, Inc.",
      "type": "signer",
      "status": "sent",
      "signedAt": null,
      "isSender": true,
      "fields": [],
      "fieldValues": {}
    },
    {
      "id": "rcp_Bl9dWh2K",
      "role": "client",
      "name": "Dana Whitfield",
      "email": "dana@brightline.example",
      "company": "Brightline Logistics",
      "type": "signer",
      "status": "signed",
      "signedAt": "2026-10-01T17:44:09.000Z",
      "isSender": false,
      "fields": [
        {
          "id": "f_Nm3kQ8",
          "type": "name",
          "label": "Full name",
          "key": "Full name",
          "value": "Dana Whitfield"
        },
        {
          "id": "f_Tt7wL2",
          "type": "title",
          "label": "Title",
          "key": "Title",
          "value": "VP of Operations"
        },
        {
          "id": "f_Ds4pR9",
          "type": "date",
          "label": "Date signed",
          "key": "Date signed",
          "value": "2026-10-01"
        },
        {
          "id": "f_Ne1xC5",
          "type": "text",
          "label": "Email for notices",
          "key": "Email for notices",
          "value": "legal@brightline.example"
        },
        {
          "id": "f_Em6hB0",
          "type": "number",
          "label": "Number of employees",
          "key": "Number of employees",
          "value": 240
        },
        {
          "id": "f_Rg2vJ7",
          "type": "dropdown",
          "label": "Region",
          "key": "Region",
          "value": "North America"
        },
        {
          "id": "f_Pd8sK3",
          "type": "dateInput",
          "label": "Disclosures start",
          "key": "Disclosures start",
          "value": "2026-10-15"
        },
        {
          "id": "f_Cb5mT1",
          "type": "checkbox",
          "label": "Share with affiliates",
          "key": "Share with affiliates",
          "value": false
        },
        {
          "id": "f_Fl9qW4",
          "type": "file",
          "label": "Certificate of insurance",
          "key": "Certificate of insurance",
          "value": "Brightline COI 2026.pdf",
          "files": [
            {
              "id": "sf_Hq2cV8xWm4Lp0aTz9Ke",
              "filename": "Brightline COI 2026.pdf",
              "size": 186412,
              "contentType": "application/pdf",
              "sha256": "9b2f4c0e7a1d3e5f8c6b9a0d2e4f6a8c1b3d5e7f9a0c2e4b6d8f0a1c3e5b7d9f",
              "uploadedAt": "2026-10-01T17:43:30.000Z",
              "url": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/files/sf_Hq2cV8xWm4Lp0aTz9Ke"
            }
          ]
        }
      ],
      "fieldValues": {
        "Full name": "Dana Whitfield",
        "Title": "VP of Operations",
        "Date signed": "2026-10-01",
        "Email for notices": "legal@brightline.example",
        "Number of employees": 240,
        "Region": "North America",
        "Disclosures start": "2026-10-15",
        "Share with affiliates": false,
        "Certificate of insurance": "Brightline COI 2026.pdf"
      }
    }
  ],
  "recipient": {
    "id": "rcp_Bl9dWh2K",
    "role": "client",
    "name": "Dana Whitfield",
    "email": "dana@brightline.example",
    "company": "Brightline Logistics",
    "type": "signer",
    "status": "signed",
    "signedAt": "2026-10-01T17:44:09.000Z",
    "isSender": false,
    "declinedReason": null,
    "fields": [
      {
        "id": "f_Nm3kQ8",
        "type": "name",
        "label": "Full name",
        "key": "Full name",
        "value": "Dana Whitfield"
      },
      {
        "id": "f_Tt7wL2",
        "type": "title",
        "label": "Title",
        "key": "Title",
        "value": "VP of Operations"
      },
      {
        "id": "f_Ds4pR9",
        "type": "date",
        "label": "Date signed",
        "key": "Date signed",
        "value": "2026-10-01"
      },
      {
        "id": "f_Ne1xC5",
        "type": "text",
        "label": "Email for notices",
        "key": "Email for notices",
        "value": "legal@brightline.example"
      },
      {
        "id": "f_Em6hB0",
        "type": "number",
        "label": "Number of employees",
        "key": "Number of employees",
        "value": 240
      },
      {
        "id": "f_Rg2vJ7",
        "type": "dropdown",
        "label": "Region",
        "key": "Region",
        "value": "North America"
      },
      {
        "id": "f_Pd8sK3",
        "type": "dateInput",
        "label": "Disclosures start",
        "key": "Disclosures start",
        "value": "2026-10-15"
      },
      {
        "id": "f_Cb5mT1",
        "type": "checkbox",
        "label": "Share with affiliates",
        "key": "Share with affiliates",
        "value": false
      },
      {
        "id": "f_Fl9qW4",
        "type": "file",
        "label": "Certificate of insurance",
        "key": "Certificate of insurance",
        "value": "Brightline COI 2026.pdf",
        "files": [
          {
            "id": "sf_Hq2cV8xWm4Lp0aTz9Ke",
            "filename": "Brightline COI 2026.pdf",
            "size": 186412,
            "contentType": "application/pdf",
            "sha256": "9b2f4c0e7a1d3e5f8c6b9a0d2e4f6a8c1b3d5e7f9a0c2e4b6d8f0a1c3e5b7d9f",
            "uploadedAt": "2026-10-01T17:43:30.000Z",
            "url": "https://app.tallysign.com/api/v1/documents/doc_3Hn8wLc2Tz/files/sf_Hq2cV8xWm4Lp0aTz9Ke"
          }
        ]
      }
    ],
    "fieldValues": {
      "Full name": "Dana Whitfield",
      "Title": "VP of Operations",
      "Date signed": "2026-10-01",
      "Email for notices": "legal@brightline.example",
      "Number of employees": 240,
      "Region": "North America",
      "Disclosures start": "2026-10-15",
      "Share with affiliates": false,
      "Certificate of insurance": "Brightline COI 2026.pdf"
    }
  }
}

Check the signature

X-Tally-Signature is sha256= followed by the HMAC-SHA256 of the raw body with your subscription's secret, in hex. Compute it over the bytes you received, before parsing, and compare in constant time.

Node.js
import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody: the request body exactly as received (a Buffer or string), before JSON parsing.
function isFromTallySign(rawBody, signatureHeader, secret) {
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  const got = Buffer.from(signatureHeader ?? "");
  return got.length === expected.length && timingSafeEqual(got, Buffer.from(expected));
}
Python
import hashlib, hmac

def is_from_tally_sign(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

Errors one shape for all of them

The HTTP status says what kind of problem it is, and the body says which one, in words you can show a person.

{
  "error": {
    "code": "not_ready",
    "message": "It can't be sent yet: Dana Whitfield: add a valid email address.",
    "details": {
      "issues": [
        "Dana Whitfield: add a valid email address."
      ]
    }
  }
}
CodeStatusMeaning
invalid_request400The request isn't valid: a missing or wrong field (details.fields says which), bad JSON or an unknown filter.
unauthorized401No API key, or it isn't valid any more (revoked, or its person was removed).
billing_paused402Sending is paused for your company's account. Drafts can still be made; an admin can resolve it in Settings → Billing.
forbidden403The key can't do this (e.g. only owners' and admins' keys subscribe to webhooks), or the account is suspended.
not_found404No such document, template, signer or subscription in your company.
conflict409The document isn't in a state that allows it (e.g. voiding a completed document), or the same Idempotency-Key is still being worked on.
not_deletable409Only drafts and voided documents can be deleted.
not_ready422It can't be sent yet. details.issues lists what's missing (a signer's email, a variable).
idempotency_key_reused422This Idempotency-Key was already used for a different request.
too_soon429That signer was reminded within the last hour.
rate_limited429Over 300 requests a minute for this key. Wait for Retry-After seconds.
server_error500Something went wrong on our side. It's logged; try again.

Limits and conventions so retries and paging just work

300 requests a minute

Per key. Every answer has X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; past the limit you get 429 with Retry-After.

Pages with a cursor

Lists answer with data, hasMore and nextCursor. Pass nextCursor as cursor for the next page. Documents come most recently changed first.

Safe retries

Send an Idempotency-Key header (a UUID) when creating, sending, reminding, voiding or subscribing. A retry within 24 hours gets the first answer back.

JSON in, JSON out

Field names are camelCase. Times are ISO 8601 in UTC. Unknown fields may be added to answers, so don't fail on them.

No limit on documents

Every plan sends as many documents as you need. The rate limit stops runaway loops, not real work.

Versioned

Everything lives under /api/v1. Changes that could break your code come as a new version, never in this one.

No code

Zapier and Make

Zapier and Make work with Tally Sign today through webhooks and the REST API: catch an event when a document is signed, or call the API to send one.

In Zapier, use Webhooks by Zapier: Catch Hook as the trigger, and subscribe its URL to the events you want. To send a document, call POST /api/v1/documents with Webhooks by Zapier: Custom Request and your API key.

AI apps

ChatGPT, Claude and MCP

For AI apps there's a built-in MCP server at /api/mcp. ChatGPT and Claude connect with a sign-in; Claude Code, Cursor and other MCP clients use the same API keys as this API.

Connect an AI app

Questions

Does the API cost extra?

No. It's part of both plans, and API calls, documents and webhooks aren't metered.

Can I make templates through the API?

Not today. Make and edit templates in Tally Sign, where you see the page as it will print, then create documents from them through the API. AI apps connected over MCP can draft documents block by block.

Can my customers sign inside my own product?

Yes. Create and send the document, then ask for that signer's signing link and open it in their browser. Each link handed out is recorded in the audit trail. Keep the link to that person: whoever opens it can sign as them.

Is a document sent through the API the same as one sent from the app?

Yes. The same checks, emails, reminders, automations, audit trail and Certificate of Completion.

Where's the OpenAPI document?

At https://app.tallysign.com/api/v1/openapi.json. It's OpenAPI 3.1, generated from the same definitions the API checks requests with, so it's always current.

How do I test without emailing real people?

Use your own addresses as the signers while you build. Every email and signature is real, so use documents you're happy to void, and delete drafts and voided ones when you're done.

Send your first document today set up in under 30 minutes