# API reference

docuinked has 29 tools. Each is a REST route and an MCP tool from one registry, so this page can't drift from the product.

Base URL: `https://docuinked.com`. Send your key as `Authorization: Bearer di_test_...`. Bodies are JSON. The machine-readable copy is the [OpenAPI file](/openapi.json).

Every success looks like this:

```json
{"status": "ok", "request_id": "req_...", "data": {}}
```

Path parameters such as `{id}` go in the URL. On GET routes, other fields are query parameters. Write calls take an `Idempotency-Key` header of up to 200 characters. The same key returns the first result and does not repeat the work. Limit: 120 requests a minute per key. See [errors](/docs/errors) for failures.

## whoami

**Check connection.** Confirms the connection works. Shows the account name, whether it is in test mode (no email is ever sent) or live, and the daily limit on live sends.

`GET /v1/whoami`

```json
{
  "additionalProperties": false,
  "properties": {},
  "required": [],
  "type": "object"
}
```

## create_document

**Create a document.** Creates a draft from a PDF (pdf_url, pdf_base64, or several files) with signers and fields. Fields go after anchor text, on {{signature:1}} tags in the PDF, or at page coordinates; with none, fields go on the PDF's own Signature, Date and Name lines (one signer per signature line, placement: labels), or else one signature field per signer on the last page. Returns draft_hash, review_url, warnings and next_action. Sending is a separate step: send_document with the draft_hash. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/documents`

```json
{
  "additionalProperties": false,
  "properties": {
    "consumer_disclosure": {
      "description": "Signers are consumers: shows the ESIGN consumer disclosure and asks them to open a test PDF. Default false.",
      "type": "boolean"
    },
    "expires_in_days": {
      "description": "Default 30.",
      "maximum": 365,
      "minimum": 1,
      "type": "integer"
    },
    "fields": {
      "description": "Leave out to use the PDF's Signature, Date and Name lines, or else one signature field per signer on the last page.",
      "items": {
        "additionalProperties": false,
        "properties": {
          "anchor": {
            "description": "Text in the PDF to place the field just after, such as 'Signature:'. Easier than coordinates.",
            "type": "string"
          },
          "h": {
            "description": "Height as a fraction of page height. Has a sensible default per kind.",
            "type": "number"
          },
          "kind": {
            "enum": [
              "signature",
              "initials",
              "date",
              "name",
              "text",
              "checkbox",
              "dropdown",
              "radio",
              "attachment"
            ]
          },
          "label": {
            "description": "Shown to the signer, such as 'Upload a photo ID'.",
            "maxLength": 80,
            "type": "string"
          },
          "options": {
            "description": "Choices for dropdown and radio fields.",
            "items": {
              "maxLength": 60,
              "type": "string"
            },
            "maxItems": 20,
            "type": "array"
          },
          "page": {
            "description": "Needed with x and y. Left out when using anchor.",
            "minimum": 1,
            "type": "integer"
          },
          "required": {
            "type": "boolean"
          },
          "signer": {
            "description": "1 for the first signer in the list, 2 for the second.",
            "minimum": 1,
            "type": "integer"
          },
          "w": {
            "description": "Width as a fraction of page width. Has a sensible default per kind.",
            "type": "number"
          },
          "x": {
            "description": "Left edge as a fraction of page width.",
            "maximum": 1,
            "minimum": 0,
            "type": "number"
          },
          "y": {
            "description": "Top edge as a fraction of page height.",
            "maximum": 1,
            "minimum": 0,
            "type": "number"
          }
        },
        "required": [
          "signer",
          "kind"
        ],
        "type": "object"
      },
      "type": "array"
    },
    "files": {
      "description": "Several PDFs or images joined into one document, in order. Each item has url or base64.",
      "items": {
        "additionalProperties": false,
        "properties": {
          "base64": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "maxItems": 20,
      "type": "array"
    },
    "message": {
      "description": "Note shown in the signing email.",
      "maxLength": 2000,
      "type": "string"
    },
    "metadata": {
      "description": "Your own keys and values, returned on reads and webhooks' document lookups.",
      "type": "object"
    },
    "ordered": {
      "description": "Sign one at a time in list order.",
      "type": "boolean"
    },
    "pdf_base64": {
      "type": "string"
    },
    "pdf_url": {
      "description": "Public https link to the PDF.",
      "type": "string"
    },
    "reminder_every_days": {
      "description": "0 turns reminders off. Default 3.",
      "maximum": 30,
      "minimum": 0,
      "type": "integer"
    },
    "send": {
      "description": "Also send, under this key's send policy. Default false.",
      "type": "boolean"
    },
    "signers": {
      "items": {
        "additionalProperties": false,
        "properties": {
          "access_code": {
            "description": "Optional code shared with the signer outside email.",
            "type": "string"
          },
          "email": {
            "format": "email",
            "type": "string"
          },
          "name": {
            "maxLength": 120,
            "type": "string"
          },
          "role": {
            "description": "cc gets the finished copy and never signs. Default signer.",
            "enum": [
              "signer",
              "cc"
            ]
          }
        },
        "required": [
          "name",
          "email"
        ],
        "type": "object"
      },
      "maxItems": 10,
      "minItems": 1,
      "type": "array"
    },
    "title": {
      "maxLength": 200,
      "type": "string"
    }
  },
  "required": [
    "title",
    "signers"
  ],
  "type": "object"
}
```

## send_document

**Send for signature.** Asks to send a draft to its signers. The draft_hash must match the current draft. With an agent key or an MCP connection, nothing is sent: it creates an approval request and returns approval_url, and the document goes out only after a named person approves that exact draft (in test mode, simulate_approval can stand in for the person). In test mode no email is sent, signers at sign@test.docuinked.com or decline@test.docuinked.com act at once, and signing links come back. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/documents/{id}/send`

```json
{
  "additionalProperties": false,
  "properties": {
    "draft_hash": {
      "description": "From create_document. Refuses if the draft has changed since. Required for agent keys.",
      "type": "string"
    },
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## list_documents

**List documents.** Lists documents in the current mode (test or live), newest first, with each signer's status. Filter by status; limit is 1 to 100.

`GET /v1/documents`

```json
{
  "additionalProperties": false,
  "properties": {
    "limit": {
      "maximum": 100,
      "minimum": 1,
      "type": "integer"
    },
    "starting_after": {
      "description": "Pass next_starting_after from the previous page.",
      "type": "string"
    },
    "status": {
      "enum": [
        "draft",
        "pending_approval",
        "sent",
        "sealing",
        "completed",
        "declined",
        "voided",
        "expired"
      ]
    },
    "updated_since": {
      "description": "Only documents changed since this time.",
      "format": "date-time",
      "type": "string"
    }
  },
  "required": [],
  "type": "object"
}
```

## get_document

**Get a document.** Shows one document's status, each signer's progress and its review link.

`GET /v1/documents/{id}`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## get_signed_pdf

**Get the signed PDF.** Returns the sealed, signed PDF as base64 with its SHA-256, once the document is completed. The file can be large.

`GET /v1/documents/{id}/signed_pdf`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## get_original_pdf

**Get the original PDF.** Returns the document as it was uploaded, before any signature, as base64 with its SHA-256. Use it to preview a draft or a document in progress.

`GET /v1/documents/{id}/original_pdf`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## get_evidence

**Get the evidence record.** Returns the full audit trail: every event, its hash chain, and the seal certificate.

`GET /v1/documents/{id}/evidence`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## remind_signers

**Remind signers.** Emails a reminder now to every signer of a sent document who hasn't signed yet. Returns how many were reminded. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/documents/{id}/remind`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## void_document

**Void a document.** Cancels a sent document that is still waiting for signatures, so it can no longer be signed. This can't be undone. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/documents/{id}/void`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    },
    "reason": {
      "description": "Optional. Kept in the evidence log and shown in the document's history.",
      "maxLength": 500,
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## create_signing_link

**Create a signing link.** Makes a signing link for one signer of a sent document, for your own app or message. With embed true it returns embed_url for an iframe on a site listed in your branding. Anyone holding the link can sign as that signer. Live agent keys and MCP connections can't create links for live documents. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/documents/{id}/signing_links`

```json
{
  "additionalProperties": false,
  "properties": {
    "embed": {
      "type": "boolean"
    },
    "id": {
      "type": "string"
    },
    "signer": {
      "minimum": 1,
      "type": "integer"
    }
  },
  "required": [
    "id",
    "signer"
  ],
  "type": "object"
}
```

## simulate_approval

**Simulate the approval (test).** Test mode only. Approves a test document's pending approval as the account's person would, then sends it, so CI and agent evals can run the approval step unattended. Live documents always need a person to approve at approval_url. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/test/documents/{id}/approve`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## simulate_signer

**Simulate a signer (test).** Test mode only. Signs or declines as one signer (signer is their position, from 1) so a whole flow runs without a browser. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/test/documents/{id}/simulate`

```json
{
  "additionalProperties": false,
  "properties": {
    "action": {
      "enum": [
        "sign",
        "decline"
      ]
    },
    "id": {
      "type": "string"
    },
    "signer": {
      "minimum": 1,
      "type": "integer"
    }
  },
  "required": [
    "id",
    "signer",
    "action"
  ],
  "type": "object"
}
```

## update_signer

**Fix a recipient.** Corrects the name or email of someone who hasn't signed yet, on a sent document. Old links stop working and a new request goes to the new address. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/documents/{id}/signers/{position}`

```json
{
  "additionalProperties": false,
  "properties": {
    "email": {
      "type": "string"
    },
    "id": {
      "type": "string"
    },
    "name": {
      "maxLength": 120,
      "type": "string"
    },
    "position": {
      "type": "string"
    }
  },
  "required": [
    "id",
    "position"
  ],
  "type": "object"
}
```

## bulk_send

**Bulk send a template.** Creates and sends one document per recipient set from a template, up to 100 at a time. With agent keys and MCP connections, each live document waits for its own approval. Over REST, an Idempotency-Key makes retries safe. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/templates/{id}/bulk`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    },
    "recipients": {
      "items": {
        "additionalProperties": false,
        "properties": {
          "metadata": {
            "type": "object"
          },
          "signers": {
            "items": {
              "additionalProperties": false,
              "properties": {
                "access_code": {
                  "description": "Optional code shared with the signer outside email.",
                  "type": "string"
                },
                "email": {
                  "format": "email",
                  "type": "string"
                },
                "name": {
                  "maxLength": 120,
                  "type": "string"
                },
                "role": {
                  "description": "cc gets the finished copy and never signs. Default signer.",
                  "enum": [
                    "signer",
                    "cc"
                  ]
                }
              },
              "required": [
                "name",
                "email"
              ],
              "type": "object"
            },
            "maxItems": 10,
            "minItems": 1,
            "type": "array"
          },
          "title": {
            "maxLength": 200,
            "type": "string"
          }
        },
        "required": [
          "signers"
        ],
        "type": "object"
      },
      "maxItems": 100,
      "minItems": 1,
      "type": "array"
    }
  },
  "required": [
    "id",
    "recipients"
  ],
  "type": "object"
}
```

## test_webhook

**Send a test event.** Sends a signed test event to the webhook right away and reports what the endpoint answered. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/webhooks/{id}/test`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## list_webhook_deliveries

**Webhook delivery log.** The last 50 delivery attempts for a webhook: event, status code, error and time taken.

`GET /v1/webhooks/{id}/deliveries`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## get_attachment

**Get a signer's upload.** Returns a file a signer uploaded, as base64, with its name, type and SHA-256. Field IDs are listed in get_evidence.

`GET /v1/documents/{id}/attachments/{field}`

```json
{
  "additionalProperties": false,
  "properties": {
    "field": {
      "type": "string"
    },
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id",
    "field"
  ],
  "type": "object"
}
```

## delete_document

**Delete a document.** Permanently deletes a document that isn't in progress: its encryption key is destroyed, so its files can never be read again. The evidence log keeps a record that it existed. Not available to agent keys. Send an `Idempotency-Key` header so a retry can't repeat the work.

`DELETE /v1/documents/{id}`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## create_template

**Save as a template.** Makes a reusable template from a draft or finished document: same file, fields and signer roles, with names and emails cleared. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/documents/{id}/template`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    },
    "title": {
      "maxLength": 200,
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

## get_branding

**Get branding.** Shows the account's signer-facing name, accent colour, logo, embed origins and whether docuinked branding is hidden.

`GET /v1/branding`

```json
{
  "additionalProperties": false,
  "properties": {},
  "required": [],
  "type": "object"
}
```

## update_branding

**Update branding.** Sets what signers see: your name, accent colour, logo, and the sites allowed to embed signing. Fields you leave out stay as they are. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/branding`

```json
{
  "additionalProperties": false,
  "properties": {
    "accent_color": {
      "pattern": "^#[0-9A-Fa-f]{6}$",
      "type": "string"
    },
    "display_name": {
      "maxLength": 80,
      "type": "string"
    },
    "embed_origins": {
      "description": "Sites allowed to frame signing, like https://app.example.com.",
      "items": {
        "type": "string"
      },
      "maxItems": 10,
      "type": "array"
    },
    "hide_docuinked_branding": {
      "type": "boolean"
    },
    "logo_png_base64": {
      "description": "PNG under 200 KB.",
      "type": "string"
    }
  },
  "required": [],
  "type": "object"
}
```

## create_account

**Create a sub-account.** For platforms: makes an account for one of your customers. Act for it on any call with the header DocuInked-Account and your own key. Each has its own documents, branding and webhooks. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/accounts`

```json
{
  "additionalProperties": false,
  "properties": {
    "name": {
      "maxLength": 120,
      "type": "string"
    }
  },
  "required": [
    "name"
  ],
  "type": "object"
}
```

## list_accounts

**List sub-accounts.** Lists the sub-accounts this account manages, for platforms.

`GET /v1/accounts`

```json
{
  "additionalProperties": false,
  "properties": {},
  "required": [],
  "type": "object"
}
```

## list_templates

**List templates.** Lists reusable templates with their IDs and signer roles, for create_from_template.

`GET /v1/templates`

```json
{
  "additionalProperties": false,
  "properties": {},
  "required": [],
  "type": "object"
}
```

## create_from_template

**Start from a template.** Creates a draft from a template, filling its signer roles in order. Nothing is sent. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/templates/{id}/documents`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    },
    "signers": {
      "items": {
        "additionalProperties": false,
        "properties": {
          "access_code": {
            "description": "Optional code shared with the signer outside email.",
            "type": "string"
          },
          "email": {
            "format": "email",
            "type": "string"
          },
          "name": {
            "maxLength": 120,
            "type": "string"
          },
          "role": {
            "description": "cc gets the finished copy and never signs. Default signer.",
            "enum": [
              "signer",
              "cc"
            ]
          }
        },
        "required": [
          "name",
          "email"
        ],
        "type": "object"
      },
      "maxItems": 10,
      "minItems": 1,
      "type": "array"
    },
    "title": {
      "maxLength": 200,
      "type": "string"
    }
  },
  "required": [
    "id",
    "signers"
  ],
  "type": "object"
}
```

## create_webhook

**Add a webhook.** Registers an https URL for events such as document.completed. Returns the signing secret once. Send an `Idempotency-Key` header so a retry can't repeat the work.

`POST /v1/webhooks`

```json
{
  "additionalProperties": false,
  "properties": {
    "events": {
      "description": "Only these events. Leave out for all.",
      "items": {
        "type": "string"
      },
      "type": "array"
    },
    "url": {
      "type": "string"
    }
  },
  "required": [
    "url"
  ],
  "type": "object"
}
```

## list_webhooks

**List webhooks.** Lists active webhooks.

`GET /v1/webhooks`

```json
{
  "additionalProperties": false,
  "properties": {},
  "required": [],
  "type": "object"
}
```

## delete_webhook

**Remove a webhook.** Stops sending events to a webhook. Send an `Idempotency-Key` header so a retry can't repeat the work.

`DELETE /v1/webhooks/{id}`

```json
{
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "type": "object"
}
```

