# API Overview

This document contains an overview of DocStudio API capabilities and common integration workflows.

{% hint style="info" %}
**Looking for user documentation?**

If you want to learn how to use DocStudio in the interface, open the user documentation. It explains how to sign in, create and send envelopes, work with templates, sign documents, manage mailboxes, and configure account settings.

[Open DocStudio Knowledge Base](https://support.docstudio.com/)
{% endhint %}

### What you can do with the API

{% columns %}
{% column %}

* authenticate requests
* create templates
* create and send envelopes
* fill envelope fields
* upload files and external documents
  {% endcolumn %}

{% column %}

* search envelopes and mailboxes
* check envelope status
* read audit trail data
* manage account domains
* import dictionary data
* embed widgets on external pages
  {% endcolumn %}
  {% endcolumns %}

### Start an integration

Authenticate requests before calling the API. Start with [Authentication and Application tokens](/introduction/authentication-and-application-tokens), then follow [Send your first envelope](/introduction/send-your-first-envelope). Keep tokens secure, review [API token security](/introduction/api-token-security) before deploying an integration.

### Build envelopes

Use templates to define documents, fields, participants, and workflow order. Reuse template identifiers when building envelope XML.

{% columns %}
{% column %}

* [templates and reusable IDs](/guides/templates-and-reusable-ids)
* [XML payloads](/guides/xml-payloads)
* [envelope fields](/guides/envelope-fields)
  {% endcolumn %}

{% column %}

* [files and external documents](/guides/files-and-external-documents)
* [metadata](/guides/envelope-metadata)
* [send envelope request details](/api-reference/send-envelope)
  {% endcolumn %}
  {% endcolumns %}

### Find and monitor

Find recipient mailboxes before sending an envelope. After sending, search, filter, and track envelope processing.

{% columns %}
{% column %}

* [search mailboxes and contacts](/api-reference/search-mailboxes-and-contacts)
* [pagination, filtering, and sorting](/guides/list-responses)
  {% endcolumn %}

{% column %}

* [check envelope status](/api-reference/check-envelope-status)
  {% endcolumn %}
  {% endcolumns %}

### Reference and operations

Use API reference pages for endpoint parameters, request formats, responses, and status codes.

{% columns %}
{% column %}

* [create templates](/api-reference/create-template)
* [upload attachments](/api-reference/upload-attachments)
* [fill envelopes](/api-reference/fill-envelope)
* [account domains](/api-reference/account-domains)
  {% endcolumn %}

{% column %}

* [dictionaries](/api-reference/dictionaries)
* [dictionary CSV import](/guides/import-dictionary-csv)
* [envelope callbacks](/guides/envelope-callbacks)
* [Simple File Send Widget](/guides/simple-file-send-widget)
  {% endcolumn %}
  {% endcolumns %}

Use [Swagger UI](https://api.docstudio.com/swagger-ui/index.html) for the complete API definition.


# Core concepts

This document contains the main DocStudio API concepts and their relationships.

{% hint style="info" %}
This page explains the main DocStudio API concepts before working with endpoints and examples. DocStudio API is built around document workflows.
{% endhint %}

### How the main concepts work together

A typical DocStudio API workflow starts with a template. The template defines the reusable document structure, fields, recipient roles, signature places, and workflow order. Follow this workflow:

1. Choose or create a [template](/guides/templates-and-reusable-ids).
2. Read the template UUID, version, role IDs, document IDs, and field names.
3. Create an envelope from the template.
4. Assign recipient mailboxes to template roles.
5. [Send the envelope](/api-reference/send-envelope) and save its UUID.
6. Track its status, fill active fields, and download completed documents.

An envelope is the document workflow sent to recipients. Use its UUID to track status, download files, and get audit trail data.

### Key identifiers

Save these values when building an envelope request:

* template UUID
* template version
* role ID
* document ID
* field name
* mailbox UUID
* envelope UUID

### Account

An account is the main workspace where users, mailboxes, templates, domains, and document workflows are managed.

Corporate account integrations can also use API endpoints to manage account domains and create corporate users in bulk. For example, an integration can download an XLSX example file, fill it with user data, roles, permissions, and mailbox assignments, and upload it to create users in bulk.

### Mailbox

A mailbox is the API context for document actions. Use the sender mailbox to send an envelope. Use recipient mailboxes to assign participants to roles.

Some requests require a mailbox UUID in the header or path. Use it to find recipients, search envelopes, and check status. The mailbox context defines the available access.

Use [Search Mailboxes and Contacts](/api-reference/search-mailboxes-and-contacts) to find mailbox UUIDs. Use [Check Envelope Status](/api-reference/check-envelope-status) to track envelopes.

```xml
<flow>
  <roles>
    <role id="{roleId}" mailboxUuid="{mailboxUuid}"/>
  </roles>
</flow>
```

In this example, `roleId` comes from the template flow. The `mailboxUuid` identifies the mailbox assigned to that role.

### Template

A template is a reusable document structure. It defines document content, fields, roles, signatures, and workflow order. Reuse its data when creating or sending an envelope.

Reference the template with `templateUuid` and `templateVersion` in envelope requests.

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  ...
  </envelope>
```

These values connect the envelope to the exact template version. A wrong template version may cause request rejection or field validation errors.

Use [Working with templates and reusable IDs](/guides/templates-and-reusable-ids) to work with template structures and fields.

### Envelope

An envelope is a document workflow created from a template. It contains the documents, field values, recipients, workflow data, metadata, and status information needed to process the document.

Many envelope endpoints use XML inside the JSON `data` field. The XML describes the envelope structure, recipients, documents, and field values.

```json
{
  "data": "<envelope templateUuid=\"{templateUuid}\" templateVersion=\"{templateVersion}\">...</envelope>"
}
```

Use [Send Envelope](/api-reference/send-envelope) to create and send envelopes. Use [Fill Envelope](/api-reference/fill-envelope) to fill active fields. Follow [Send your first envelope](/introduction/send-your-first-envelope) to download completed documents.

### Recipient role

A recipient role defines who participates in the envelope workflow and what that participant must do. Roles are defined in the template flow. Each role has an ID, type, title, and order.

Role order controls when the recipient becomes active. A role may fill or sign fields after the previous role completes its step. A template role becomes an envelope participant after the request assigns its mailbox.

```xml
<role id="{roleIdFromTemplate}" mailboxUuid="{recipientMailboxUuid}"/>
```

Assign real mailboxes to template roles when sending an envelope. This connects the template role to the recipient mailbox.

### Document

A document is part of a template or envelope. It can be a structured DocStudio document or an uploaded external file. Each document has a document ID.

Use the correct document ID when sending field values. This identifies the document that contains those fields. Send field values inside that document.

```xml
<documents>
  <document id="{documentId}">
    <field name="Customer name">ACME Ltd</field>
    <field name="Signing date">2026-07-15</field>
  </document>
</documents>
```

Match `documentId` and field names with the template structure. DocStudio validates field values against template field settings.

### Field

A field defines data that users can enter, select, upload, calculate, copy, or sign. DocStudio supports these field types:

{% columns %}
{% column %}

* text
* number
* currency
* number to text
* date
* dropdown
  {% endcolumn %}

{% column %}

* choice
* checkbox
* file
* dictionary
* lookup
  {% endcolumn %}

{% column %}

* dynamic table
* duplicate
* formula
* autonumber
* signature
  {% endcolumn %}
  {% endcolumns %}

Different field types can require different value formats. For example, a text field can use a simple value, a file field must reference an uploaded attachment, and a dynamic table uses field groups and fieldsets.

```xml
<field name="Text field">Text value</field>

<field name="File field" attachmentUuid="{attachmentUuid}">agreement.pdf</field>

<fieldgroup name="Table">
  <fieldset index="0">
    <field name="Row value">First row</field>
  </fieldset>
</fieldgroup>
```

Field configuration belongs to the template. Send or fill field values later in envelope requests. Use exact field names from the template structure.

### Metadata

Metadata is extra envelope data outside document content. It can store external IDs, flags, references, and other business-specific values for later processing.

```json
{
  "customerId": "C-1024",
  "approved": true,
  "externalReference": null
}
```

Use metadata to connect external records with DocStudio envelopes. It can store a customer ID, order ID, CRM record ID, department, campaign, or internal process reference.

Store metadata as key-value pairs. Add it to envelopes and envelope forms. Envelopes created from a form can inherit the same values.

### Envelope form link

An envelope form link lets users create envelopes from a shared link. The form uses a template with predefined fields and roles. After users submit required fields, DocStudio creates a new envelope.

Envelope form links can use metadata and callbacks. This supports public or semi-public intake flows.

### Audit trail

Audit trail data records envelope history and participant actions. It can be used to inspect what happened during envelope processing, track completion details, or store document workflow history in an external system.

### Dictionary

A dictionary is a predefined dataset for dictionary and lookup fields in templates. Use dictionaries for controlled values, such as customers, products, departments, regions, or other business-specific lists.

Import dictionary data from CSV files through [Dictionaries](/api-reference/dictionaries).

### Widget

A widget is an embeddable DocStudio flow for an external web page. The [Simple File Send Widget](/guides/simple-file-send-widget) lets users send files for signing without signing in to DocStudio.

Use widgets to expose a limited DocStudio workflow outside the main platform interface.

### Status

Envelope status shows the envelope's place in the workflow. Status values help integrations decide what to do next. Common envelope statuses include:

* DRAFT
* WAITING
* COMPLETED
* EXPIRED
* CANCELLED

Use mailbox and envelope status endpoints to search, filter, and track envelopes.

### Before you send an envelope

Confirm the template, mailbox, role, document, and field used by your request. Most envelope requests depend on template identifiers and mailbox context.

Choose a template first. Read its identifiers. Assign the correct mailbox UUIDs to roles. Then send or fill the envelope using the same template structure.


# Authentication and Application tokens

This document explains how to authenticate DocStudio API requests with application and temporary authorization tokens.

{% hint style="info" %}
Use application tokens for server-side integrations, backend services, automation, and long-running API access. Use `/api/login` for testing or short-lived sessions that require user credentials.
{% endhint %}

### Choose a token type

| Token type                    | Use for                                                                             |
| ----------------------------- | ----------------------------------------------------------------------------------- |
| Application token             | Server-side integrations, backend services, automation, and long-running API access |
| Temporary authorization token | Testing, short-lived sessions, or requests that use user credentials                |

### Authentication header

Use the same header format for both token types.

```
Authorization: Bearer {token}
```

The token identifies the caller. Endpoint permissions still control access to a mailbox, account, envelope, template, dictionary, domain, or attachment.

### Manage application tokens

Use application tokens without sending a user password in every request. Store them only in secure server-side storage.

Do not expose token values in client-side code, mobile applications, repositories, logs, screenshots, tickets, shared documents, or frontend environment variables.

Application token endpoints return an application token object.

#### List application tokens

| Method | Endpoint        |
| ------ | --------------- |
| `GET`  | `/api/v1/token` |

**Response**

Returns an array of application token objects.

#### Create application token

| Method | Endpoint        |
| ------ | --------------- |
| `POST` | `/api/v1/token` |

**Request body**

```json
{
  "name": "string",
  "expireAt": "2026-07-21T13:42:40.621Z"
}
```

| Field      | Type      | Required | Description                    |
| ---------- | --------- | -------- | ------------------------------ |
| `name`     | string    | Yes      | Application token name         |
| `expireAt` | date-time | Yes      | Token expiration date and time |

**Response**

Returns an application token object. Copy and store the returned token value securely.

#### Revoke application token

| Method   | Endpoint             |
| -------- | -------------------- |
| `DELETE` | `/api/v1/token/{id}` |

**Path parameters**

| Parameter | Type | Required | Description          |
| --------- | ---- | -------- | -------------------- |
| `id`      | UUID | Yes      | Application token ID |

**Response**

Returns `200 OK`.

#### Configuration restriction

Application token methods can be disabled by configuration. The API then returns `405 Method disabled by configuration`.

```json
{
  "code": 0,
  "message": "string",
  "messageLocalized": "string",
  "messageArgs": [
    "string"
  ],
  "data": "string"
}
```

| Field              | Type    | Description                                 |
| ------------------ | ------- | ------------------------------------------- |
| `code`             | integer | Error code                                  |
| `message`          | string  | Error message                               |
| `messageLocalized` | string  | Localized error message                     |
| `messageArgs`      | array   | Dynamic arguments used to build the message |
| `data`             | any     | Additional error data                       |

{% hint style="info" %}
This response schema applies to disabled application token methods only.
{% endhint %}

### Temporary authorization tokens

Use `/api/login` to get a temporary authorization token with user credentials. The token expires after 3 hours.

Use application tokens for long-running integrations.

| Method | Endpoint     |
| ------ | ------------ |
| `POST` | `/api/login` |

#### Request body

```json
{
  "login": "string",
  "password": "string"
}
```

| Field      | Type   | Required | Description   |
| ---------- | ------ | -------- | ------------- |
| `login`    | string | Yes      | User login    |
| `password` | string | Yes      | User password |

#### Response

```json
{
  "token": "string",
  "deviceId": "string"
}
```

| Field      | Type   | Description                                |
| ---------- | ------ | ------------------------------------------ |
| `token`    | string | Temporary authorization token              |
| `deviceId` | string | Device ID returned with the login response |

Use the returned `token` value in the `Authorization` header.

```
Authorization: Bearer {authorization-token}
```

### Resolve authentication and access errors

| Code                      | Meaning                                              | Action                                                             |
| ------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------ |
| `401 Not authorized`      | The request is not authenticated                     | Check the header, token value, and token expiration                |
| `403 Forbidden`           | The token cannot access the resource or action       | Check access to the required account, mailbox, or requested object |
| `90035 Not a token owner` | The current user cannot access the application token | Use a token from the correct user and account                      |

### Checklist

1. Confirm that the `Authorization` header uses the `Bearer {token}` format.
2. Confirm that the token value is valid and has not expired.
3. Confirm that the token and requested resource use the expected account and mailbox.

### How to respond to an exposed token

1. Stop using the exposed token.
2. Create a new token and update the integration.
3. Revoke the exposed token and remove it from unsafe locations.

### Related topics

* [API token security](/introduction/api-token-security)
* [Send your first envelope](/introduction/send-your-first-envelope)
* [Authorization](/api-reference/authorization)


# API token security

This document explains how to store, use, and replace DocStudio API tokens securely.

{% hint style="info" %}
API tokens provide access to DocStudio API, so they must be stored and used carefully. Treat every token as a secret value.
{% endhint %}

### Scope

These security rules apply to any token used with DocStudio API, including:

* application tokens
* authorization tokens returned by the /api/login endpoint

Application tokens are usually used by integrations, backend services, automation scripts, and server-to-server workflows. Authorization tokens returned by /api/login are temporary and expire after 3 hours, but they must still be protected while they are valid.

### Store tokens securely

Store API tokens only in secure server-side storage. Do not hardcode tokens directly in source code or configuration files that can be shared, copied, or committed to a repository.

Use secure storage such as:

{% columns %}
{% column %}

* environment variables on a protected server
* encrypted CI/CD variables
* secret managers
  {% endcolumn %}

{% column %}

* protected backend configuration
* secure infrastructure-level secrets storage
  {% endcolumn %}
  {% endcolumns %}

Example environment variable:

```dotenv
DOCSTUDIO_API_TOKEN={token}
```

The exact storage method depends on your infrastructure, but the rule is the same: the token must be available only to the trusted backend service that sends API requests to DocStudio.

### Use tokens only on the server side

Do not use DocStudio API tokens in client-side code, public frontend applications, mobile applications, or static websites. Users, browser tools, proxies, and other software can inspect client-side code. Treat every token stored there as exposed.

Do not put tokens in:

{% columns %}
{% column %}

* JavaScript frontend code
* mobile application code
* browser local storage
* browser session storage
  {% endcolumn %}

{% column %}

* cookies available to client-side scripts
* public configuration files
* static website assets
* frontend environment variables included in a public build
  {% endcolumn %}
  {% endcolumns %}

If a frontend or mobile application needs to start a DocStudio API action, send the request to your backend first. The backend should add the DocStudio API token and call DocStudio API from a protected server-side environment.

### Do not expose tokens

Never share tokens in places where other users, systems, or third-party tools can access them.

Do not include tokens in:

{% columns %}
{% column %}

* public repositories
* private repositories with broad access
* screenshots
* screen recordings
* logs
* error messages
* browser console output
  {% endcolumn %}

{% column %}

* support tickets
* chat messages
* shared documents
* test reports
* API examples in documentation
* monitoring tools without secret masking
  {% endcolumn %}
  {% endcolumns %}

When you write examples, always replace real tokens with placeholders.

Correct example:

```http
Authorization: Bearer {token}
```

### Protect the Authorization header

DocStudio API tokens are sent in the Authorization header.

```http
Authorization: Bearer {token}
```

Make sure your application does not print this header in logs, error traces, analytics events, or monitoring tools. If request logging is enabled, mask the Authorization header before the request is stored.

Recommended masked format:

```http
Authorization: Bearer ***
```

### Use separate tokens for separate integrations

Do not reuse the same token for every system, environment, or integration. Separate tokens make it easier to control access and replace only the affected token if something goes wrong.

Use separate tokens for:

{% columns %}
{% column %}

* production environments
* staging or testing environments
* different backend services
  {% endcolumn %}

{% column %}

* different automation jobs
* different external integrations
  {% endcolumn %}
  {% endcolumns %}

For example, do not use the same token for a production CRM integration and a local developer test script. If the test script exposes the token, the production integration should not be affected.

### Use the minimum required access

Create and use tokens from a user or account context that has only the access required by the integration. If an integration only needs to send envelopes from a specific mailbox, do not use a token connected to a user with unnecessary access to unrelated mailboxes or account settings.

Authentication proves who sends the request, but endpoint permissions still define what the token can access. A valid token can still receive a 403 Forbidden response if the token owner does not have access to the requested mailbox, envelope, template, account, domain, dictionary, or other resource.

### Replace tokens when needed

Replace tokens regularly according to your internal security policy. You should also replace a token immediately if there is any chance that it was exposed.

Rotate a token when:

{% columns %}
{% column %}

* a developer with token access leaves the project
* a token was shared in a chat, ticket, screenshot, or document
* a token was committed to a repository
* a token appeared in logs or monitoring tools
  {% endcolumn %}

{% column %}

* a token was used on an unsafe device
* an integration is moved to a new environment
* your internal security policy requires scheduled rotation
  {% endcolumn %}
  {% endcolumns %}

To replace a token, create a new token, update the integration, test the new token, and stop using the old token.

### Respond to an exposed token

If a token is exposed, treat it as compromised even if you do not see suspicious activity.

{% hint style="danger" %}
Replace an exposed token immediately. Do not wait for suspicious activity or an integration failure.
{% endhint %}

1. Stop using the exposed token.
2. Create a new token in DocStudio.
3. Update the integration to use the new token.
4. Test the integration with the new token.
5. Remove the exposed value from repositories, logs, tickets, screenshots, documents, or other unsafe places.
6. Check whether any unexpected API activity happened while the token was exposed.

### Local development

For local development, store tokens in a local environment file that is not committed to the repository.

For example, use a local .env file:

```dotenv
DOCSTUDIO_API_TOKEN={token}
```

Add local environment files to .gitignore before adding token values.

Example .gitignore entry:

```gitignore
.env
.env.local
```

Do not send local environment files to other people. If another developer needs access, they should create or receive their own token through the approved process.

### CI/CD and automation

For CI/CD pipelines and automation jobs, store tokens as protected secret variables. Do not write tokens directly in pipeline files, deployment scripts, Dockerfiles, or build logs.

Make sure that:

* secret variables are available only to the required jobs
* secret values are masked in logs
* pull requests from untrusted branches cannot print secrets
* deployment logs do not expose request headers
* failed jobs do not print full API request configuration

### Common mistakes

Avoid these common token security mistakes:

{% columns %}
{% column %}

* hardcoding tokens in source code
* committing .env files to a repository
* using production tokens in local test scripts
* sharing one token across all integrations
* sending tokens in chat messages or support tickets
  {% endcolumn %}

{% column %}

* recording videos with visible tokens
* logging the full Authorization header
* storing tokens in browser local storage
* using tokens directly in frontend code
* forgetting to replace exposed tokens
  {% endcolumn %}
  {% endcolumns %}

### Security checklist

Before using a token in an integration, check that:

{% columns %}
{% column %}

* The token is stored in secure server-side storage.
* The token is not hardcoded in source code.
* The token is not available in frontend or mobile code.
  {% endcolumn %}

{% column %}

* The Authorization header is masked in logs.
* The token is not included in screenshots, tickets, or shared documents.
* The token belongs to the correct user or account.
  {% endcolumn %}

{% column %}

* The token owner has only the access required by the integration.
* Production and test environments use separate tokens.
* There is a process for replacing exposed tokens.
  {% endcolumn %}
  {% endcolumns %}

### Related topics

* [Authentication and application tokens](/introduction/authentication-and-application-tokens)
* [Send your first envelope](/introduction/send-your-first-envelope)
* [Authorization](/api-reference/authorization)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)


# Send your first envelope

This document explains how to send, track, and download your first envelope with DocStudio API.

{% hint style="info" %}
Use the envelope UUID to retrieve the envelope, check its status, and download completed documents. For full contracts, response schemas, and status codes, use the linked API reference pages.
{% endhint %}

### Before you start

Prepare the identifiers used by the template and envelope flow. Do not create role IDs, document IDs, or field names manually. Reuse values from the template structure.

You need:

* API token
* sender and recipient mailbox UUIDs
* existing template with its UUID and version
* role IDs, document IDs, and field names from the template

Read:

* [Authentication and application tokens](/introduction/authentication-and-application-tokens) to get a token.
* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids) to find template identifiers.

A basic envelope sending flow usually looks like this:

1. Get or create an API token.
2. Choose the template that will be used to create the envelope.
3. Read reusable identifiers from the template structure.
4. Find or prepare mailbox UUIDs for recipients.
5. Build the envelope XML.
6. Send the envelope.
7. Save the returned envelope UUID.
8. [Retrieve the envelope and check its status](/api-reference/check-envelope-status).
9. Download the completed envelope archive if needed.

### Step 1 Authenticate the request

DocStudio API requests require a token in the `Authorization` header. Use an application token for long-running integrations and a temporary authorization token only for testing or short-lived user sessions.

```
Authorization: Bearer {token}
```

{% hint style="info" %}
Use the same token format in the send request and in follow-up requests, such as retrieving the envelope by UUID.
{% endhint %}

### Step 2 Build the envelope XML

The envelope is sent as **XML** inside the JSON `data` field. The XML must reference the template UUID and template version, assign mailbox UUIDs to template roles, and send field values under the correct document IDs and field names.

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  <flow>
    <roles>
      <role id="{roleId}" mailboxUuid="{recipientMailboxUuid}" />
    </roles>
  </flow>
  <documents>
    <document id="{documentId}">
      <field name="Customer name">ACME Ltd</field>
      <field name="Contract amount">1000</field>
    </document>
  </documents>
</envelope>
```

Escape reserved XML characters before putting the XML into the JSON request body. The `data` value must be a string, so line breaks and quotes must be valid for JSON.

### Step 3 Send the envelope

Use this endpoint to create and send the envelope.

| Method | Endpoint                |
| ------ | ----------------------- |
| `POST` | `/api/v1/envelope/send` |

#### Headers

<table><thead><tr><th width="143.4443359375">Header</th><th width="176.4444580078125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td>Use <code>application/json</code></td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>Sender mailbox UUID used as the mailbox context</td></tr></tbody></table>

#### Request body:

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "data": "<envelope templateUuid=\"{templateUuid}\" templateVersion=\"{templateVersion}\">...</envelope>"
}
```

#### Request body fields

<table><thead><tr><th width="96.77777099609375">Field</th><th width="81.5555419921875">Type</th><th width="106.666748046875">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>uuid</code></td><td>UUID</td><td>No</td><td>Envelope UUID when the flow already has an envelope identifier</td></tr><tr><td><code>data</code></td><td>string</td><td>Yes</td><td>Envelope XML string</td></tr><tr><td><code>metadata</code></td><td>object</td><td>No</td><td>Custom key-value metadata added to the envelope</td></tr></tbody></table>

{% hint style="info" %}
Add `metadata` only when the envelope requires custom key-value data.
{% endhint %}

Response `201 Created`:

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

**Save the returned `uuid`**. This is the envelope UUID used for follow-up requests, including retrieving the envelope, checking status, downloading documents, and reading audit trail data.

### Step 4 Retrieve the envelope

Use the returned envelope UUID to retrieve the envelope and check its current status. Send the request in the context of the mailbox that was used to send the envelope.

<table><thead><tr><th width="293">Method</th><th>Endpoint</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/v1/mailbox/{mailboxUuid}?UUID={envelopeUuid}</code></td></tr></tbody></table>

#### Headers

<table><thead><tr><th>Header</th><th>Required</th><th width="250">Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td>Use <code>application/json</code></td></tr><tr><td><code>mailboxUuid</code></td><td>Yes</td><td>UUID of the current mailbox</td></tr></tbody></table>

#### Path parameters

| Parameter     | Type | Required | Description                                     |
| ------------- | ---- | -------- | ----------------------------------------------- |
| `mailboxUuid` | UUID | Yes      | UUID of the mailbox used to access the envelope |

#### Query parameters

<table><thead><tr><th width="121">Parameter</th><th width="134">Type</th><th width="108">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>UUID</code></td><td>UUID</td><td>Yes</td><td>UUID of the envelope returned by the send request</td></tr></tbody></table>

#### Request example

```http
GET /api/v1/mailbox/{senderMailboxUuid}?UUID={envelopeUuid}
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {senderMailboxUuid}
```

The endpoint returns `200 OK` with the matching envelope data. Check the `status` field before attempting to download the completed envelope documents.

### Step 5 Download the completed archive

After the envelope is complete, download the archive if you need the final documents. Use the envelope UUID with the download endpoint.

{% hint style="warning" %}
Do not download the archive before the document files are ready. If the file is not ready yet, wait and retry according to the endpoint response and retry guidance.
{% endhint %}

### Troubleshoot the first send request

If validation fails, check the template and mailbox first, then:

* Confirm the token can access the sender mailbox.
* Confirm that template UUID, version, role IDs, document IDs, and field names match.
* Confirm that XML is valid and field values follow template rules.

### Related topics

{% columns %}
{% column %}

* [Authentication and application tokens](/introduction/authentication-and-application-tokens)
* [Core concepts](/introduction/core-concepts)
* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids)
  {% endcolumn %}

{% column %}

* [Send Envelope](/api-reference/send-envelope)
* [Check Envelope Status](/api-reference/check-envelope-status)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)
  {% endcolumn %}
  {% endcolumns %}


# Automation Overview

This document contains an overview of DocStudio Automations and available automation bricks.

### Automations

DocStudio Automations allow you to create and run workflows that perform a sequence of predefined operations automatically. An automation contains a name, an active state, and a workflow consisting of at least two connected bricks.

{% hint style="info" %}
A **brick** is an individual workflow component that performs a predefined operation. Each brick has its own type, configuration, and position in the execution sequence.
{% endhint %}

#### Workflow structure

Each brick has a unique ID and a type that determines the operation it performs. The `next` property specifies which brick or bricks are executed next, allowing the workflow to follow a linear sequence or branch into multiple execution paths.

<figure><img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2FvuB4TTEY1PQ0JMF7Wr3m%2Fautomation-workflow-structure-hq.png?alt=media&amp;token=5fe18de5-3267-4871-b645-61a598516800" alt=""><figcaption></figcaption></figure>

The `config` object contains the settings required by the selected brick type. Depending on the type, these settings can include input files, transformation expressions, filters, connection parameters, processing rules, output file names, and other operation-specific values. The configuration supported by each brick type is defined by its `configSchema`.

Brick types that connect to external systems or services may also require stored credentials. In this case, the brick references the required credentials using `credentialsId`.

#### Passing data between bricks

Some brick types expose named output parameters that can be used by subsequent bricks. When an output parameter matches a configuration field required by the next brick, its value is passed automatically.

<figure><img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2Fco4fX1SqViqIfVulzTcF%2Fdata-passed-between-bricks-hq.png?alt=media&amp;token=0047d293-3ab1-4b6b-a01d-8ec75e6c49f9" alt=""><figcaption></figcaption></figure>

In this example, `envelope-trigger` provides the `envelope` and `mailbox` output parameters. Because `envelope-label-assignee` requires parameters with the same names, their values are supplied automatically, and only `label` must be specified in its `config`.

### Available bricks

The following bricks are currently available for building automation workflows:

<table><thead><tr><th width="231.272705078125">Name</th><th>Purpose</th></tr></thead><tbody><tr><td><code>webhook-sender</code></td><td>Sends data to a configured webhook URL</td></tr><tr><td><code>json2xml-converter</code></td><td>Converts JSON data to XML</td></tr><tr><td><code>google-document-ai</code></td><td>Processes documents using Google Document AI</td></tr><tr><td><code>envelope-flow-resolver</code></td><td>Resolves an envelope flow and replaces recipient emails with available auto-deposit mailboxes</td></tr><tr><td><code>sftp-uploader</code></td><td>Uploads a file through SFTP</td></tr><tr><td><code>parameter-extractor</code></td><td>Extracts values from input data using XPath or JSONPath expressions</td></tr><tr><td><code>envelope-initiator</code></td><td>Initiates an envelope using data from a source file</td></tr><tr><td><code>api-caller</code></td><td>Sends a GET or POST request to an external API</td></tr><tr><td><code>jsonata-converter</code></td><td>Transforms JSON data using a JSONata expression</td></tr><tr><td><code>sftp-receiver</code></td><td>Receives files through SFTP and filters them using a configured pattern</td></tr><tr><td><code>vchasno-callback-checker</code></td><td>Checks a Vchasno callback using the configured document type and configuration ID</td></tr><tr><td><code>envelope-trigger</code></td><td>Selects envelopes based on configured filters and provides the matching envelope and mailbox</td></tr><tr><td><code>xsd-validator</code></td><td>Validates input against an XSD schema</td></tr><tr><td><code>xslt-converter</code></td><td>Transforms XML data using an XSLT map</td></tr><tr><td><code>if-condition</code></td><td>Evaluates a condition using XPath or JSONPath</td></tr><tr><td><code>sch-validator</code></td><td>Validates input using a Schematron schema</td></tr><tr><td><code>as2-sender</code></td><td>Sends data to an external system through AS2</td></tr><tr><td><code>as2-receiver</code></td><td>Receives data through AS2</td></tr><tr><td><code>envelope-saver</code></td><td>Saves an envelope</td></tr><tr><td><code>gemini</code></td><td>Processes data using a configured Gemini model and prompt</td></tr><tr><td><code>openai</code></td><td>Processes data using a configured OpenAI model and prompt</td></tr><tr><td><code>document-extractor</code></td><td>Extracts a document from an envelope</td></tr><tr><td><code>webhook-receiver</code></td><td>Receives data through a webhook</td></tr><tr><td><code>envelope-approver</code></td><td>Approves an envelope</td></tr><tr><td><code>envelope-label-assignee</code></td><td>Assigns a label to an envelope</td></tr><tr><td><code>eancom2xml-converter</code></td><td>Converts EANCOM data to XML</td></tr><tr><td><code>envelope-filler</code></td><td>Fills an envelope</td></tr><tr><td><code>excel2xml-converter</code></td><td>Converts Excel data to XML</td></tr><tr><td><code>envelope-delegator</code></td><td>Delegates an envelope to another mailbox</td></tr><tr><td><code>envelope-sender</code></td><td>Sends an envelope</td></tr></tbody></table>


# Create an Automation

This document explains how to create and verify a DocStudio Automation.

### Before you begin

To create an automation, you need:

* an account ID
* a bearer token for API authorization
* at least two automation types for the workflow
* credentials for automation types that access external services

You can retrieve the currently available automation types and their configuration schemas using:

```http
GET /api/v1/automation/account/{accountId}/brick-types
```

Use the returned `configSchema` for the selected type to determine which configuration fields it supports.

### Workflow structure

An automation contains the following properties:

```json
{
  "name": "Automation name",
  "active": true,
  "workflow": []
}
```

<table><thead><tr><th width="304.20001220703125">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td>Automation name</td></tr><tr><td><code>active</code></td><td>Whether the automation is active</td></tr><tr><td><code>workflow</code></td><td>Workflow items performed by the automation</td></tr></tbody></table>

The `workflow` array contains the operations performed by the automation. A workflow must contain at least two items.

Each workflow item uses the following structure:

```json
{
  "id": "uuid",
  "type": "automation-type",
  "description": "Description",
  "config": {},
  "credentialsId": "uuid",
  "next": []
}
```

<table><thead><tr><th width="149.79998779296875">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>UUID generated for the workflow item</td></tr><tr><td><code>type</code></td><td>Automation type, such as <code>envelope-trigger</code></td></tr><tr><td><code>description</code></td><td>Optional description of the operation</td></tr><tr><td><code>config</code></td><td>Configuration for the selected automation type, defined by its <code>configSchema</code></td></tr><tr><td><code>credentialsId</code></td><td>ID of stored credentials, included only when the selected type requires credentials</td></tr><tr><td><code>next</code></td><td>IDs of workflow items that receive this item's output</td></tr></tbody></table>

Use `x` and `y` to set an item's position on the workflow canvas. They do not affect execution.

### Passing data between automation types

Automation types can expose named output parameters. Downstream workflow items receive them automatically when parameter names match.

For example, `envelope-trigger` provides:

```
envelope
mailbox
```

The `envelope-label-assignee` type requires `envelope`, `mailbox`, and `label`. When it follows `envelope-trigger`, the `envelope` and `mailbox` values are supplied automatically, so only `label` needs to be specified in its `config`.

### Create an automation

The following example creates an automation that detects envelopes with the `WAITING` status and assigns the `AutoProcessed` label to them.

#### Get the available automation types

Send:

```http
GET /api/v1/automation/account/{accountId}/brick-types
```

Find `envelope-trigger` and `envelope-label-assignee` in the response and use their `configSchema` definitions when configuring the workflow.

#### Build the workflow

Use the following payload:

```json
{
  "name": "Catch envelopes in 'Waiting for you' status and assign a label to them",
  "active": true,
  "workflow": [
    {
      "id": "11111111-1111-1111-1111-111111111111",
      "type": "envelope-trigger",
      "description": "Catch envelopes in 'Waiting for you' status",
      "config": {
        "status": [
          "WAITING"
        ]
      },
      "next": [
        "22222222-2222-2222-2222-222222222222"
      ]
    },
    {
      "id": "22222222-2222-2222-2222-222222222222",
      "type": "envelope-label-assignee",
      "description": "Assign label",
      "config": {
        "label": "AutoProcessed"
      },
      "next": []
    }
  ]
}
```

The `next` value in `envelope-trigger` contains the ID of `envelope-label-assignee`. This makes label assignment the next operation. The final operation uses an empty `next` array.

#### Create the automation

Send the workflow using:

```http
POST /api/v1/automation/account/{accountId}
```

A successful request returns `201 Created` with the automation ID:

```json
{
  "id": "<automation-uuid>"
}
```

#### Trigger the automation

Perform the action that matches the configured trigger. For this example, an envelope must enter a status matched by the `envelope-trigger` configuration.

The example uses:

```json
{
  "status": [
    "WAITING"
  ]
}
```

Supported envelope status values:

{% columns %}
{% column %}

* `DRAFT`
* `SENT`
* `WAITING`
  {% endcolumn %}

{% column %}

* `COMPLETED`
* `CANCELLED`
  {% endcolumn %}

{% column %}

* `EXPIRED`
* `ON_APPROVAL`
  {% endcolumn %}
  {% endcolumns %}

When the trigger finds a matching envelope, the workflow continues to `envelope-label-assignee`. The first run creates the `AutoProcessed` label if it does not exist.

#### Verify the execution

Creating an automation successfully does not confirm that its workflow has executed successfully. After triggering it, retrieve the automation executions:

```http
GET /api/v1/automation/account/{accountId}/executions
```

Find the corresponding execution and check its execution state.

A completed execution has state `SUCCEED`.

If the execution state is `FAILED`, retrieve its execution log:

```http
GET /api/v1/automation/account/{accountId}/execution/{traceId}/log
```

The log identifies the failed workflow item and describes the error.

### Related topics

* [Automation types](/automation-types)
* [Automation Overview](/automation-overview)


# Automation Examples

Examples of DocStudio Automations that notify chat services and approve vacation requests.

{% hint style="info" %}
The following examples demonstrate how multiple automation types can be combined into workflows for common integration and business-process scenarios.
{% endhint %}

### Send a Chat Notification When an Envelope Is Completed

This example sends a notification when an envelope reaches the `COMPLETED` status. The workflow detects the envelope, builds a JSON message, and sends it through an HTTP request.

The workflow uses the following automation types:

<figure><img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2FGjZJK0WacNIPCSmMxFCB%2Fimage.png?alt=media&amp;token=9ef29e38-7e5c-4e2c-9e21-6636617ce736" alt=""><figcaption></figcaption></figure>

#### Build the notification message

The `xslt-converter` transforms `envelope.xml` into the JSON body sent to the external service. The following XSLT creates a Google Chat message containing the envelope subject and status:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="/envelope">
    <xsl:text>{"text": "Envelope \"</xsl:text>
    <xsl:value-of select="info/subject"/>
    <xsl:text>\" is now </xsl:text>
    <xsl:value-of select="state/status"/>
    <xsl:text>"}</xsl:text>
  </xsl:template>
</xsl:stylesheet>
```

The generated Google Chat message has the following format:

```json
{
  "text": "Envelope \"000\" is now COMPLETED"
}
```

#### Configure the target service

Use a Google Chat incoming-webhook URL with the Google Chat message above.

For Telegram, use the `sendMessage` endpoint and include the target `chat_id`:

```xml
<xsl:text>{"chat_id": "-100123456789", "text": "Envelope \"</xsl:text>
<xsl:value-of select="info/subject"/>
<xsl:text>\" is now </xsl:text>
<xsl:value-of select="state/status"/>
<xsl:text>"}</xsl:text>
```

Use the Telegram API URL in this format:

```
https://api.telegram.org/bot<bot-token>/sendMessage
```

{% hint style="warning" %}
Webhook URLs and Telegram bot tokens are secrets. Do not commit production values or include them in shared automation payloads.
{% endhint %}

#### Automation payload

```json
{
  "name": "Notify chat on envelope completion",
  "active": true,
  "workflow": [
    {
      "id": "11111111-1111-1111-1111-111111111111",
      "type": "envelope-trigger",
      "description": "Catch completed envelopes",
      "config": {
        "status": [
          "COMPLETED"
        ]
      },
      "next": [
        "44444444-4444-4444-4444-444444444444"
      ]
    },
    {
      "id": "44444444-4444-4444-4444-444444444444",
      "type": "xslt-converter",
      "description": "Build chat message JSON from envelope fields",
      "config": {
        "filename": "message.json",
        "map": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:output method=\"text\"/><xsl:template match=\"/envelope\"><xsl:text>{\"text\": \"Envelope \\\"</xsl:text><xsl:value-of select=\"info/subject\"/><xsl:text>\\\" is now </xsl:text><xsl:value-of select=\"state/status\"/><xsl:text>\"}</xsl:text></xsl:template></xsl:stylesheet>"
      },
      "next": [
        "22222222-2222-2222-2222-222222222222"
      ]
    },
    {
      "id": "22222222-2222-2222-2222-222222222222",
      "type": "api-caller",
      "description": "POST to Google Chat / Telegram",
      "config": {
        "url": "<google-chat-webhook-url-or-telegram-sendMessage-url>",
        "method": "post",
        "contentType": "application/json",
        "timeout": 5000,
        "retries": 3,
        "successCode": 200
      },
      "next": []
    }
  ]
}
```

Set `contentType` to `application/json`. The request then uses the expected content type. For Telegram, use the Telegram URL and XSLT shown above.

#### Verify the notification

Complete an envelope that matches the trigger. Then retrieve the execution and confirm its state is `SUCCEED`.

If the request fails, retrieve the execution log. Check the `api-caller` operation for the response from the chat service.

### Auto-Approve or Reject a Vacation Request Based on an External Balance

This example checks an employee's available vacation balance using an external REST API. When a vacation request reaches the approver's mailbox, the automation retrieves the available balance, compares it with the requested number of days, and automatically approves or rejects the request.

The workflow uses the following automation types:

<figure><img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2Fnj4Xlx5w1VZ2lsDzu4vW%2FChatGPT%20Image%2025%20%D0%B0%D0%B2%D0%B3.%202026%20%D0%B3.%2C%2011_52_41.png?alt=media&amp;token=fa1586a7-6e03-4aa5-b043-5d4f89a36914" alt=""><figcaption></figcaption></figure>

#### Build the balance request

The `xslt-converter` creates the request body for the external service using values from the vacation request envelope. The exact XPath expressions depend on how the required fields are represented in `envelope.xml`.

The resulting request must contain the information required by the external service to identify the employee and determine the requested number of vacation days.

#### Check the vacation balance

The `api-caller` sends the generated request to the external HR or leave-management API:

```json
{
  "url": "https://hr.example.com/api/vacation-balance",
  "method": "post",
  "contentType": "application/json",
  "filename": "balance-response.json"
}
```

The response must provide both the available vacation balance and the requested number of days so that the following conditions can evaluate the result.

#### Approve or reject the request

Two `if-condition` operations process the API response. Both are direct children of `api-caller`.

The first condition checks whether the available balance is sufficient:

```json
{
  "executor": "jsonpath",
  "expression": "$[?(@.balance >= @.requested)]"
}
```

When this condition matches, the workflow continues to `envelope-approver`, which approves the pending request:

```json
{
  "id": "approve",
  "type": "envelope-approver",
  "description": "Sufficient balance — approve on behalf of this approver mailbox, sending the envelope forward",
  "config": {},
  "next": []
}
```

The second condition checks the opposite case:

```json
{
  "executor": "jsonpath",
  "expression": "$[?(@.balance < @.requested)]"
}
```

When the available balance is insufficient, the workflow continues to `envelope-rejecter`. The request is rejected automatically with a predefined rejection reason:

```json
{
  "id": "reject",
  "type": "envelope-rejecter",
  "description": "Insufficient balance — reject on behalf of this approver mailbox",
  "config": {
    "rejectionReason": "Insufficient vacation balance"
  },
  "next": []
}
```

#### Automation payload

```json
{
  "name": "Vacation request auto-approval",
  "active": true,
  "workflow": [
    {
      "id": "trigger",
      "type": "envelope-trigger",
      "description": "Catch vacation request envelopes awaiting this mailbox's approval",
      "config": {
        "template": [
          "<vacation-request-template-uuid>"
        ],
        "status": [
          "WAITING"
        ]
      },
      "next": [
        "build-request"
      ]
    },
    {
      "id": "build-request",
      "type": "xslt-converter",
      "description": "Build the balance-check request body from envelope fields",
      "config": {
        "filename": "balance-request.json",
        "map": "<xslt stylesheet — see 'Build the balance request' above>"
      },
      "next": [
        "call-balance-api"
      ]
    },
    {
      "id": "call-balance-api",
      "type": "api-caller",
      "description": "Call external HR/leave-management API (must echo back requestedDays)",
      "config": {
        "url": "https://hr.example.com/api/vacation-balance",
        "method": "post",
        "contentType": "application/json",
        "filename": "balance-response.json"
      },
      "next": [
        "if-sufficient",
        "if-insufficient"
      ]
    },
    {
      "id": "if-sufficient",
      "type": "if-condition",
      "description": "balance >= requested",
      "config": {
        "executor": "jsonpath",
        "expression": "$[?(@.balance >= @.requested)]"
      },
      "next": [
        "approve"
      ]
    },
    {
      "id": "if-insufficient",
      "type": "if-condition",
      "description": "balance < requested — exact logical complement of if-sufficient",
      "config": {
        "executor": "jsonpath",
        "expression": "$[?(@.balance < @.requested)]"
      },
      "next": [
        "reject"
      ]
    },
    {
      "id": "approve",
      "type": "envelope-approver",
      "description": "Sufficient balance — approve on behalf of this approver mailbox, sending the envelope forward",
      "config": {},
      "next": []
    },
    {
      "id": "reject",
      "type": "envelope-rejecter",
      "description": "Insufficient balance — reject on behalf of this approver mailbox",
      "config": {
        "rejectionReason": "Insufficient vacation balance"
      },
      "next": []
    }
  ]
}
```

The automation must run for the mailbox that holds the pending approver role. Both `envelope-approver` and `envelope-rejecter` act on that mailbox's pending approval step, just as the approver would when processing the request manually.

The example uses a static `Insufficient vacation balance` rejection reason. A dynamic reason can be used if the external API already returns an appropriate message that can be passed to the rejection operation.

### AI Review of a Membership Application

This example uses AI to review a membership application and automatically write the generated result back into the envelope. The workflow extracts the applicant's answer, builds an AI prompt, sends it to OpenAI, converts the AI response into XML, and fills the `aiSummary` field in the envelope.

The workflow uses the following automation types:

<figure><img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2FGExxWCirKGNxxIAU7c65%2Fimage.png?alt=media&amp;token=f03e0ba8-251a-485d-89db-dfeaa6666335" alt=""><figcaption></figcaption></figure>

#### Template structure

The example template uses two roles and two fields on the same document:

* **Role 0 — applicant** fills `applicationText`.
* **Role 1 — assignee** owns the empty `aiSummary` field that is populated by the automation.

When the applicant sends the envelope with `applicationText` completed, the envelope moves to `WAITING`. The automation catches the envelope when Role 1 becomes active.

#### Build the AI prompt

Use `parameter-extractor` with the `xpath` executor to build a prompt from the value of `applicationText`.

```json
{
  "executor": "xpath",
  "outputParams": [
    "prompt"
  ],
  "expressions": [
    "concat('Summarize this membership application in one sentence: ', //field[@name=\"applicationText\"])"
  ]
}
```

The `prompt` output parameter is passed directly to the next `openai` operation. Because the parameter name matches the `prompt` input expected by `openai`, the `prompt` property can be omitted from the OpenAI operation configuration.

#### Configure the AI operation

The `openai` automation type requires a stored OpenAI credential. Create it first:

```
POST /api/v1/automation/account/{accountId}/credentials
```

```json
{
  "name": "openai-membership-review",
  "type": "openai",
  "data": {
    "apiKey": "<real-key>"
  }
}
```

A successful request returns the credential ID:

```json
{
  "id": "<credential-uuid>"
}
```

Use this value as `credentialsId` in the `openai` workflow item.

The `openai` operation can then be configured as follows:

```json
{
  "type": "openai",
  "config": {
    "model": "gpt-4o",
    "filename": "ai-response.json"
  },
  "credentialsId": "<stored-openai-credential-id>"
}
```

The same workflow can use `gemini` instead of `openai`. The credential type, `credentialsId`, and automation type must be changed accordingly.

#### Convert the AI response

The AI response is JSON, while `envelope-filler` ultimately requires an XML fill payload. Use `json2xml-converter` before the XSLT transformation.

For an OpenAI response with the following shape:

```json
{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "Test AI response text"
      }
    }
  ]
}
```

`json2xml-converter` produces XML in which the response text can be selected with:

```
/root/choices/message/text()
```

Use this XPath in the following `xslt-converter` operation when building the envelope fill payload.

#### Build the envelope fill payload

The `xslt-converter` must create the XML structure expected by the envelope fill operation. The generated payload includes the target field and places the AI response into `aiSummary`.

```xml
<envelope templateUuid="<template-uuid>" templateVersion="<template-version>">
  <info>
    <subject>Membership application</subject>
    <message></message>
    <forwarding delegation="false" sharing="false"/>
  </info>
  <flow>
    <roles>
      <role id="0" mailboxUuid="<applicant-mailbox-uuid>"/>
      <role id="1" mailboxUuid="<automation-mailbox-uuid>"/>
    </roles>
  </flow>
  <documents>
    <document id="0">
      <field name="aiSummary">
        <xsl:value-of select="/root/choices/message/text()"/>
      </field>
    </document>
  </documents>
</envelope>
```

The template UUID, template version, and role mailbox UUIDs are static values for the template used by this automation. The AI-generated response is inserted dynamically into the `aiSummary` field.

#### Automation payload

```json
{
  "name": "AI review of membership application",
  "active": true,
  "workflow": [
    {
      "id": "trigger",
      "type": "envelope-trigger",
      "description": "Catch membership applications awaiting this mailbox's review",
      "config": {
        "template": [
          "<membership-application-template-uuid>"
        ],
        "status": [
          "WAITING"
        ]
      },
      "next": [
        "build-prompt"
      ]
    },
    {
      "id": "build-prompt",
      "type": "parameter-extractor",
      "description": "Build the AI prompt from the applicant's answer",
      "config": {
        "executor": "xpath",
        "outputParams": [
          "prompt"
        ],
        "expressions": [
          "concat('Summarize this membership application in one sentence: ', //field[@name=\"applicationText\"])"
        ]
      },
      "next": [
        "ask-ai"
      ]
    },
    {
      "id": "ask-ai",
      "type": "openai",
      "description": "Generate a summary from the membership application",
      "config": {
        "model": "gpt-4o",
        "filename": "ai-response.json"
      },
      "credentialsId": "<stored-openai-credential-id>",
      "next": [
        "to-xml"
      ]
    },
    {
      "id": "to-xml",
      "type": "json2xml-converter",
      "description": "Convert the AI response from JSON to XML",
      "config": {},
      "next": [
        "build-fill"
      ]
    },
    {
      "id": "build-fill",
      "type": "xslt-converter",
      "description": "Build the envelope fill payload from the AI response",
      "config": {
        "filename": "fill.xml",
        "map": "<xslt stylesheet using /root/choices/message/text() to populate aiSummary>"
      },
      "next": [
        "fill-field"
      ]
    },
    {
      "id": "fill-field",
      "type": "envelope-filler",
      "description": "Write the AI response into aiSummary and complete the assignee step",
      "config": {},
      "next": []
    }
  ]
}
```

When the workflow completes successfully, `envelope-filler` writes the generated text into `aiSummary`. In the verified scenario, Role 1 is the last active role, so filling the field completes the envelope and moves it from `WAITING` to `COMPLETED`.

### Related topics

* [Create an Automation](/create-an-automation)
* [Credentials](/credentials)
* [Automation Executions and Logs](/automation-executions-and-logs)
* [Envelope automation types](/automation-types/envelope)
* [Integration automation types](/automation-types/integration)
* [Validation and Logic automation types](/automation-types/validation-and-logic)


# Credentials

This document explains how to manage credentials for DocStudio Automations.

Some automation types need stored credentials to access external systems or services. Create credentials before adding the type to a workflow. Then set `credentialsId` to the credential ID.

### Get available credential types

Retrieve the credential types available for the account:

```http
GET /api/v1/automation/account/{accountId}/credential-types
```

The response includes schemas for types used by available automation types. Use the schema to identify required credential values.

### Create credentials

Create a stored credential:

```http
POST /api/v1/automation/account/{accountId}/credentials
```

Provide the configuration required by the selected credential type. A successful request returns the created credential ID.

Add the credential ID to the workflow item:

```json
{
  "id": "11111111-1111-1111-1111-111111111111",
  "type": "automation-type",
  "config": {},
  "credentialsId": "<credential-uuid>",
  "next": []
}
```

Add `credentialsId` only when the selected automation type requires stored credentials.

### List stored credentials

Retrieve the stored credentials available for the account:

```http
GET /api/v1/automation/account/{accountId}/credentials
```

### Delete credentials

Delete a stored credential:

```http
DELETE /api/v1/automation/account/{accountId}/credentials/{id}
```

Use the ID of the credential to remove. This operation removes the selected stored credential.

### Related topics

* [Create an Automation](/create-an-automation)
* [Automation types](/automation-types)


# Automation Executions and Logs

This document explains how to inspect automation executions, diagnose failed operations, and reprocess them.

Use this guide after an automation trigger runs. It helps you inspect the execution, diagnose a failed operation, and retry it when appropriate.

### Before you begin

You need an account ID and a bearer token for API authorization. You also need the automation to have run at least once.

Retrieve `traceId` from the execution list. Retrieve `spanId` from the log of the selected execution.

### View automation executions

Use the following endpoint to retrieve past automation executions:

```
GET /api/v1/automation/account/{accountId}/executions
```

Find the execution for the trigger that you want to inspect. Check its `state` before requesting the detailed log.

```
SUCCEED
```

An execution with state `SUCCEED` completed successfully. If its state is `FAILED`, use its `traceId` to retrieve the execution log.

### View an execution log

Use the following endpoint to retrieve the detailed log for an execution:

```
GET /api/v1/automation/account/{accountId}/execution/{traceId}/log
```

The log describes the individual workflow operations. It identifies the failed operation and its error.

Use the failed operation's `spanId` in subsequent requests. It identifies the operation without retrying the full workflow.

### Download a file from an execution

Some workflow operations can produce file artifacts during execution. Use the following endpoint to download a file associated with a specific operation:

```
GET /api/v1/automation/account/{accountId}/execution/{traceId}/log/{spanId}/file
```

Use the execution `traceId` and the required operation's `spanId`. Download the artifact when it helps diagnose the operation result.

### Reprocess a failed operation

Use the following endpoint to retry a failed workflow operation:

```
POST /api/v1/automation/account/{accountId}/execution/{traceId}/log/{spanId}/reprocess
```

Use the execution `traceId` and the failed operation's `spanId`. This request reprocesses the selected operation, rather than the entire workflow.

### Related topics

* [Create an Automation](/create-an-automation)
* [Credentials](/credentials)
* [Automation types](/automation-types)


# Automation types

* [Envelope](/automation-types/envelope)
* [Data Transformation and Processing](/automation-types/data-transformation-and-processing)
* [Validation and Logic](/automation-types/validation-and-logic)
* [Integration](/automation-types/integration)
* [AI](/automation-types/ai)


# Envelope

{% hint style="info" %}
**Envelope** type — perform operations related to envelopes and their processing.\
Use it to find, fill, approve, delegate or initiate envelopes, resolve recipients, save or send envelopes, assign labels, and extract documents from envelopes.
{% endhint %}

### envelope-flow-resolver

Replaces emails with auto-deposit mailboxes and checks if all mailboxes exist and are active.

```json
{
  "type": "envelope-flow-resolver",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Replaces emails with auto-deposit mailboxes and checks if all mailboxes exist and are active\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"}},\"required\":[\"mailbox\",\"envelope\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### envelope-initiator

Initiates an envelope using data from a source file.

```json
{
  "type": "envelope-initiator",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Initiates the envelope using data from the source file\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"},\"map\":{\"description\":\"Template XPath to Source XPath/JsonPath mapping\",\"type\":\"object\"}},\"required\":[\"mailbox\",\"envelope\",\"map\"]}",
  "multipleInput": false,
  "outputParam": [
    "envelopeMetadata"
  ]
}
```

### envelope-trigger

Finds envelopes using the configured envelope filters and provides the matching envelope and mailbox.

```json
{
  "type": "envelope-trigger",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Envelope Trigger\",\"type\":\"object\",\"properties\":{\"template\":{\"description\":\"Set of template UUIDs associated with the envelope\",\"type\":\"array\",\"items\":{\"format\":\"uuid\",\"type\":\"string\"}},\"sendDateFrom\":{\"format\":\"date-time\",\"description\":\"Start date for envelope send date filter\",\"type\":\"string\"},\"metadata\":{\"description\":\"Envelope metadata key-value pairs\",\"additionalProperties\":{\"type\":\"string\"},\"type\":\"object\"},\"createDateTo\":{\"format\":\"date-time\",\"description\":\"End date for envelope creation date filter\",\"type\":\"string\"},\"expireDateFrom\":{\"format\":\"date-time\",\"description\":\"Start date for envelope expiration date filter\",\"type\":\"string\"},\"subject\":{\"description\":\"Subject of the envelope\",\"type\":\"string\"},\"createDateFrom\":{\"format\":\"date-time\",\"description\":\"Start date for envelope creation date filter\",\"type\":\"string\"},\"expireDateTo\":{\"format\":\"date-time\",\"description\":\"End date for envelope expiration date filter\",\"type\":\"string\"},\"label\":{\"description\":\"Set of labels associated with the envelope\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"receiveDateTo\":{\"format\":\"date-time\",\"description\":\"End date for envelope receive date filter\",\"type\":\"string\"},\"form\":{\"description\":\"Set of form UUIDs to filter envelopes by\",\"type\":\"array\",\"items\":{\"format\":\"uuid\",\"type\":\"string\"}},\"receiveDateFrom\":{\"format\":\"date-time\",\"description\":\"Start date for envelope receive date filter\",\"type\":\"string\"},\"sendDateTo\":{\"format\":\"date-time\",\"description\":\"End date for envelope send date filter\",\"type\":\"string\"},\"sender\":{\"description\":\"Set of sender UUIDs to filter envelopes by\",\"type\":\"array\",\"items\":{\"format\":\"uuid\",\"type\":\"string\"}},\"recipient\":{\"description\":\"Set of recipient UUIDs to filter envelopes by\",\"type\":\"array\",\"items\":{\"format\":\"uuid\",\"type\":\"string\"}},\"templateVersion\":{\"description\":\"Set of template version UUIDs associated with the envelope\",\"type\":\"array\",\"items\":{\"format\":\"uuid\",\"type\":\"string\"}},\"status\":{\"description\":\"Set of statuses to filter envelopes by\",\"type\":\"array\",\"items\":{\"type\":\"string\"}}}}",
  "multipleInput": false,
  "outputParam": [
    "envelope",
    "mailbox"
  ]
}
```

### envelope-saver

Saves an envelope in the specified mailbox.

```json
{
  "type": "envelope-saver",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Envelope Saver\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"}},\"required\":[\"mailbox\",\"envelope\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### document-extractor

Extracts a specified document from an envelope.

```json
{
  "type": "document-extractor",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Document Extractor\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"},\"document\":{\"description\":\"ID of the document in the envelope\",\"type\":\"string\"}},\"required\":[\"mailbox\",\"envelope\",\"document\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### envelope-approver

Approves an envelope in the specified mailbox.

```json
{
  "type": "envelope-approver",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Envelope Approver\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"}},\"required\":[\"mailbox\",\"envelope\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### envelope-label-assignee

Assigns a label to an envelope.

```json
{
  "type": "envelope-label-assignee",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Assign Envelope Label\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"},\"label\":{\"description\":\"The name of the label\",\"type\":\"string\"}},\"required\":[\"mailbox\",\"envelope\",\"label\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### envelope-filler

Fills an envelope in the specified mailbox.

```json
{
  "type": "envelope-filler",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Envelope Filler\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"}},\"required\":[\"mailbox\",\"envelope\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### envelope-delegator

Delegates an envelope to another mailbox.

```json
{
  "type": "envelope-delegator",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Assign Envelope Label\",\"type\":\"object\",\"properties\":{\"envelope\":{\"format\":\"uuid\",\"description\":\"ID of the envelope in the mailbox\",\"type\":\"string\"},\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"},\"delegateTo\":{\"format\":\"uuid\",\"description\":\"Delegate mailbox ID\",\"type\":\"string\"}},\"required\":[\"mailbox\",\"envelope\",\"delegateTo\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### envelope-sender

Sends an envelope from the specified mailbox.

```json
{
  "type": "envelope-sender",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Envelope Sender\",\"type\":\"object\",\"properties\":{\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"}},\"required\":[\"mailbox\"]}",
  "multipleInput": false,
  "outputParam": [
    "envelope"
  ]
}
```


# Data Transformation and Processing

{% hint style="info" %}
**Data transformation and processing** type — convert data between formats, transform structured data, and extract specific values from source content.\
Use it to prepare data before it is passed to another automation step or external system.
{% endhint %}

### json2xml-converter

Converts JSON data to XML.

```json
{
  "type": "json2xml-converter",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"JSON to XML Converter\",\"type\":\"object\",\"properties\":{}}",
  "multipleInput": false,
  "outputParam": []
}
```

### parameter-extractor

Extracts parameters from input data using XPath or JSONPath expressions.

```json
{
  "type": "parameter-extractor",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Parameter Extractor\",\"type\":\"object\",\"properties\":{\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"},\"executor\":{\"description\":\"Type of executor\",\"type\":\"string\",\"enum\":[\"xpath\",\"jsonpath\"]},\"outputParams\":{\"minItems\":1,\"uniqueItems\":true,\"description\":\"Set of output parameter names\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"expressions\":{\"minItems\":1,\"description\":\"Set of expressions for each parameter\",\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"executor\",\"outputParams\",\"expressions\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### jsonata-converter

Transforms JSON data using a JSONata expression.

```json
{
  "type": "jsonata-converter",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"JSONata Converter\",\"type\":\"object\",\"properties\":{\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"},\"expression\":{\"description\":\"Conversion expression on JSONata\",\"type\":\"string\"},\"filename\":{\"description\":\"File name for output file\",\"type\":\"string\"}},\"required\":[\"expression\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### xslt-converter

Transforms XML data using an XSLT map.

```json
{
  "type": "xslt-converter",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"XSLT Converter\",\"type\":\"object\",\"properties\":{\"mailbox\":{\"format\":\"uuid\",\"description\":\"ID of the mailbox\",\"type\":\"string\"},\"filename\":{\"description\":\"File name for output file\",\"type\":\"string\"},\"map\":{\"description\":\"XSLT map\",\"type\":\"string\"}},\"required\":[\"map\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### eancom2xml-converter

Converts EANCOM data to XML.

```json
{
  "type": "eancom2xml-converter",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"EANCOM to XML Converter\",\"type\":\"object\",\"properties\":{}}",
  "multipleInput": false,
  "outputParam": []
}
```

### excel2xml-converter

Converts Excel data to XML.

```json
{
  "type": "excel2xml-converter",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Excel to XML Converter\",\"type\":\"object\",\"properties\":{}}",
  "multipleInput": false,
  "outputParam": []
}
```


# Validation and Logic

{% hint style="info" %}
**Validation and logic** type — validate structured data and evaluate conditions during an automation process.\
Use it to verify that input data matches a required schema or to control further processing based on XPath or JSONPath expressions.
{% endhint %}

### xsd-validator

Validates input data against an XSD schema.

```json
{
  "type": "xsd-validator",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"XSD Validator\",\"type\":\"object\",\"properties\":{\"xsd\":{\"description\":\"XSD file or URL\",\"type\":\"string\"}},\"required\":[\"xsd\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### if-condition

Evaluates a condition using XPath or JSONPath.

```json
{
  "type": "if-condition",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"If Condition\",\"type\":\"object\",\"properties\":{\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"},\"expression\":{\"description\":\"Condition expression\",\"type\":\"string\"},\"executor\":{\"description\":\"Type of executor\",\"type\":\"string\",\"enum\":[\"xpath\",\"jsonpath\"]}},\"required\":[\"executor\",\"expression\"]}",
  "multipleInput": false,
  "outputParam": [
    "ifConditionResult"
  ]
}
```

### sch-validator

Validates input data using a Schematron schema.

```json
{
  "type": "sch-validator",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Schematron Validator\",\"type\":\"object\",\"properties\":{\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"},\"sch\":{\"description\":\"SCH file or URL\",\"type\":\"string\"}},\"required\":[\"sch\"]}",
  "multipleInput": false,
  "outputParam": []
}
```


# Integration

{% hint style="info" %}
**Integration** type — exchange data with external systems and services.\
Use it to send or receive data through webhooks, APIs, SFTP, and AS2, as well as process integration-specific callbacks.
{% endhint %}

### webhook-sender

Sends data to a configured webhook endpoint.

```json
{
  "type": "webhook-sender",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Callback\",\"type\":\"object\",\"properties\":{\"retries\":{\"default\":3,\"description\":\"Number of retries\",\"maximum\":10,\"type\":\"integer\",\"minimum\":0},\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"},\"url\":{\"format\":\"uri\",\"description\":\"URL of receiver\",\"type\":\"string\"},\"timeout\":{\"default\":5000,\"description\":\"Timeout in ms\",\"maximum\":60000,\"type\":\"integer\",\"minimum\":100},\"successCode\":{\"default\":200,\"description\":\"Success code\",\"type\":\"integer\"}},\"required\":[\"url\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### sftp-uploader

Uploads a file through SFTP.

```json
{
  "type": "sftp-uploader",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"SFTP Uploader\",\"type\":\"object\",\"properties\":{\"path\":{\"description\":\"Path with a filename (expression can be used)\",\"type\":\"string\"},\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"}},\"required\":[\"path\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### api-caller

Sends a GET or POST request to an external API.

```json
{
  "type": "api-caller",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"API caller\",\"type\":\"object\",\"properties\":{\"retries\":{\"default\":3,\"description\":\"Number of retries\",\"maximum\":10,\"type\":\"integer\",\"minimum\":0},\"filename\":{\"description\":\"File name for output file\",\"type\":\"string\"},\"method\":{\"description\":\"POST or GET method\",\"type\":\"string\",\"enum\":[\"post\",\"get\"]},\"contentType\":{\"description\":\"Content-Type header\",\"type\":\"string\"},\"url\":{\"format\":\"uri\",\"description\":\"URL of receiver\",\"type\":\"string\"},\"timeout\":{\"default\":5000,\"description\":\"Timeout in ms\",\"maximum\":60000,\"type\":\"integer\",\"minimum\":100},\"successCode\":{\"default\":200,\"description\":\"Success code\",\"type\":\"integer\"}},\"required\":[\"url\",\"method\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### sftp-receiver

Receives files through SFTP and filters them using a configured matching pattern.

```json
{
  "type": "sftp-receiver",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"SFTP Receiver\",\"type\":\"object\",\"properties\":{\"pattern\":{\"default\":\"(.*)\",\"description\":\"File matching pattern\",\"type\":\"string\"},\"patternSource\":{\"default\":\"name\",\"description\":\"File matching pattern source: name, content or attribute\",\"type\":\"string\"}},\"required\":[\"pattern\",\"patternSource\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### vchasno-callback-checker

Checks a Vchasno callback using the configured document type and configuration ID.

```json
{
  "type": "vchasno-callback-checker",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Vchasno callback checker\",\"type\":\"object\",\"properties\":{\"documentType\":{\"description\":\"Connector document type\",\"type\":\"string\"},\"configurationId\":{\"format\":\"uuid\",\"description\":\"ID of the configuration\",\"type\":\"string\"}}}",
  "multipleInput": false,
  "outputParam": []
}
```

### as2-sender

Sends data to an external system through AS2.

```json
{
  "type": "as2-sender",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"AS2 Sender\",\"type\":\"object\",\"properties\":{\"algorithmCrypt\":{\"description\":\"Encryption algorithm\",\"type\":\"string\",\"enum\":[\"3des\",\"cast5\",\"idea\",\"rc2\",\"aes128-cbc\",\"aes192-cbc\",\"aes256-cbc\",\"aes128-gcm\",\"aes192-gcm\",\"aes256-gcm\"]},\"senderId\":{\"description\":\"ID of sender\",\"type\":\"string\"},\"receiverCertificate\":{\"description\":\"Certificate of receiver (Base64 or URL)\",\"type\":\"string\"},\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"},\"receiverId\":{\"description\":\"ID of receiver\",\"type\":\"string\"},\"filename\":{\"description\":\"File name (expression can be used)\",\"type\":\"string\"},\"algorithmSign\":{\"description\":\"Signing algorithm\",\"type\":\"string\",\"enum\":[\"md5\",\"sha-1\",\"sha-256\",\"sha-512\",\"sha2_256\",\"sha2_512\",\"rsassa-pss-sha-256\",\"rsassa-pss-sha-512\",\"rsassa-pss-sha3-256\",\"rsassa-pss-sha3-512\"]},\"senderEmail\":{\"format\":\"email\",\"description\":\"e-mail of sender\",\"type\":\"string\"},\"messageId\":{\"description\":\"Message ID (expression can be used)\",\"type\":\"string\"},\"receiverUrl\":{\"format\":\"uri\",\"description\":\"URL of receiver\",\"type\":\"string\"}},\"required\":[\"senderId\",\"senderEmail\",\"receiverId\",\"receiverUrl\",\"receiverCertificate\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### as2-receiver

Receives data through AS2.

```json
{
  "type": "as2-receiver",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"AS2 Receiver\",\"type\":\"object\",\"properties\":{}}",
  "multipleInput": false,
  "outputParam": [
    "receiver"
  ]
}
```

### webhook-receiver

Receives data through a webhook.

```json
{
  "type": "webhook-receiver",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Web Hook\",\"type\":\"object\",\"properties\":{}}",
  "multipleInput": false,
  "outputParam": []
}
```


# AI

{% hint style="info" %}
**AI** type —  process documents or input data using supported external AI and document processing services.
{% endhint %}

### google-document-ai

Processes documents using Google Document AI.

```json
{
  "type": "google-document-ai",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Google Document AI\",\"type\":\"object\",\"properties\":{\"inputFilename\":{\"description\":\"Input filename\",\"type\":\"string\"},\"filename\":{\"description\":\"File name for output file\",\"type\":\"string\"},\"project\":{\"description\":\"Google Cloud project ID\",\"type\":\"string\"},\"location\":{\"description\":\"Google Cloud processor location\",\"type\":\"string\"},\"processor\":{\"description\":\"Google Document AI processor ID\",\"type\":\"string\"}},\"required\":[\"project\",\"location\",\"processor\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### gemini

Processes input using a configured Gemini model and prompt.

```json
{
  "type": "gemini",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"Gemini\",\"type\":\"object\",\"properties\":{\"filename\":{\"description\":\"File name for output file\",\"type\":\"string\"},\"temperature\":{\"default\":\"0.5\",\"description\":\"Temperature\",\"type\":\"string\"},\"model\":{\"default\":\"gemini-2.0-flash\",\"description\":\"Model\",\"type\":\"string\"},\"prompt\":{\"description\":\"Prompt\",\"type\":\"string\"}},\"required\":[\"prompt\",\"model\"]}",
  "multipleInput": false,
  "outputParam": []
}
```

### openai

Processes input using a configured OpenAI model and prompt.

```json
{
  "type": "openai",
  "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"additionalProperties\":false,\"title\":\"OpenAI\",\"type\":\"object\",\"properties\":{\"filename\":{\"description\":\"File name for output file\",\"type\":\"string\"},\"temperature\":{\"default\":\"0.5\",\"description\":\"Temperature\",\"type\":\"string\"},\"model\":{\"default\":\"gpt-4o\",\"description\":\"Model\",\"type\":\"string\"},\"prompt\":{\"description\":\"Prompt\",\"type\":\"string\"}},\"required\":[\"prompt\",\"model\"]}",
  "multipleInput": false,
  "outputParam": []
}
```


# Templates and reusable IDs

This document explains how to find, reuse, and validate template and API identifiers in DocStudio integrations.

DocStudio API uses templates as the source for envelope structure. When you send an envelope from a template, the request must reuse identifiers from that template instead of creating new ones manually.

### How templates work in API flows

A template is a reusable document structure.\
It defines:

{% columns %}
{% column %}

* documents
* fields
* recipient roles
  {% endcolumn %}

{% column %}

* signature places
* workflow order
* other
  {% endcolumn %}
  {% endcolumns %}

When sending an envelope from a template, reuse the template workflow. Provide only data for this envelope: recipient mailboxes, field values, uploaded files, metadata, and other envelope data.

A typical template-based flow looks like this:

1. Choose or create a template.
2. Read the template structure.
3. Save the reusable identifiers from the template.
4. Find mailbox UUIDs for recipients.
5. Build the envelope XML with template identifiers.
6. Send the envelope.
7. Save the returned envelope UUID.

{% hint style="warning" %}
Use the template UUID, version, role IDs, document IDs, and field names from the same template version. Do not create or mix these values manually.
{% endhint %}

### Reusable identifiers

Reusable identifiers are values that connect API requests with existing DocStudio objects. They tell DocStudio which template, document, role, field, mailbox, attachment, or envelope the request uses.

Common reusable identifiers include:

{% columns %}
{% column %}

* template UUID
* template version
* role ID
* mailbox UUID
* document ID
* field name
* field group name
  {% endcolumn %}

{% column %}

* attachment UUID
* envelope UUID
* account UUID
* domain UUID
* dictionary UUID
* column UUID
  {% endcolumn %}
  {% endcolumns %}

Collect each identifier from its source:

{% columns %}
{% column %}
**Template**

* template UUID and version
* role IDs
* document IDs
* field and field group names
  {% endcolumn %}

{% column %}
**API responses**

* mailbox UUIDs from mailbox data
* attachment UUIDs from upload responses
* envelope UUIDs from send responses
  {% endcolumn %}
  {% endcolumns %}

{% hint style="info" %}
Use account, domain, dictionary, and column UUIDs only for their respective API flows.
{% endhint %}

### Template UUID and template version

The **template UUID** identifies the template, the **template version** identifies its exact structure version.

Use both values in the root envelope element.

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  ...
</envelope>
```

Get the template UUID and version from the template structure or response. Keep these values paired. After updating a template, use the current version.

{% hint style="warning" %}
Do not combine a template UUID with another template's version.

Do not use an old version when the envelope needs the current structure.
{% endhint %}

### Role ID

Roles are defined in the template flow. Each template role must have an `id`, `title`, and `type`. The optional `order` attribute controls the role position in the flow.

Valid template role:

```xml
<flow type="manual">
  <roles>
    <role id="customer" title="Customer" type="signer" order="1" />
  </roles>
</flow>
```

Supported `type` values are `sender`, `assignee`, `copy`, `signer`, and `approver`.

When you create or send an envelope, reuse the role `id` from the selected template version and assign a recipient mailbox. Do not recreate the template role or change its ID.

```xml
<flow>
  <roles>
    <role id="customer" mailboxUuid="{recipientMailboxUuid}" />
  </roles>
</flow>
```

The role ID connects the envelope participant to the role defined in the template. If the ID does not exist in the selected template version, DocStudio cannot assign the participant to the workflow.

{% hint style="warning" %}
DocStudio cannot assign the participant to the workflow if the role ID does not exist in the selected template version.
{% endhint %}

### Mailbox UUID

Mailbox UUIDs identify mailboxes that can send, receive, or process envelopes. Many API requests use a mailbox UUID as the sender context, recipient assignment, path parameter, or request header.

Use mailbox UUIDs when you need to:

* assign recipients to template roles
* search mailbox data
* check envelope status
* download envelope documents from a mailbox context
* perform actions from a specific mailbox

Example recipient assignment:

```xml
<role id="{roleId}" mailboxUuid="{recipientMailboxUuid}"/>
```

The token owner must have access to the mailbox used in the request. A valid token can still receive a 403 Forbidden error if the user or integration does not have access to the selected mailbox.

### Document ID

Documents are defined inside the template. Each document has an ID that must be reused when you send field values in an envelope request.

Example:

```xml
<documents>
  <document id="{documentId}">
    <field name="Customer name">ACME Ltd</field>
  </document>
</documents>
```

The document ID tells DocStudio which document contains the field. If the request uses the wrong document ID, field values may not be applied or the request may fail validation.

Use document IDs from the same template version that you reference in the envelope request.

### Field names

Field names identify fields inside template documents. When you send field values, use the exact field names from the template structure.

Example:

```xml
<field name="Customer name">ACME Ltd</field>
<field name="Signing date">2026-07-15</field>
```

Field names are case-sensitive and must match the template field names. Do not rename fields in the API request, even if the new name looks clearer.

Incorrect field names are one of the most common reasons why envelope data is not applied correctly.

### Field group names

Field group names are used when the template contains grouped fields or dynamic tables. The request must use the same field group names that exist in the template structure.

Example:

```xml
<fieldgroup name="Products">
  <fieldset index="0">
    <field name="Product name">Service plan</field>
    <field name="Quantity">1</field>
  </fieldset>
</fieldgroup>
```

Use field groups when the template expects repeated or grouped data. Do not invent new group names in the envelope request.

### Attachment UUIDs

Attachment UUIDs are returned after a file is uploaded to DocStudio. Use attachment UUIDs when a field or document must reference an uploaded file.

Example file field:

```xml
<field name="Attachment" attachmentUuid="{attachmentUuid}">agreement.pdf</field>
```

The attachment UUID must come from the file upload response. Do not use a local file path, file name, or external file URL instead of the attachment UUID.

### Envelope UUID

The envelope UUID identifies the envelope after it is created or sent.

Response example:

```json
{
  "uuid": "89499ba2-287d-404c-87b0-342dc5b01b6a"
}
```

Save the envelope UUID. You need it to check envelope status, download documents, get audit trail data, or perform follow-up actions.

The envelope UUID is not available before the envelope is created. It is returned by the send or create operation.

### Additional account and dictionary identifiers

#### Account and domain UUIDs

Account and domain UUIDs are used in account administration flows, such as managing corporate users and account domains.

For example, account domain endpoints can use an account UUID to identify the account and a domain UUID to identify a specific domain.

Use these identifiers only in account-level API flows. They are not the same as mailbox UUIDs, template UUIDs, or envelope UUIDs.

#### Dictionary and column UUIDs

Dictionaries and dictionary columns have their own UUIDs. These identifiers are used when templates contain dictionary or lookup fields.

Use dictionary UUIDs and column UUIDs when the API request needs to reference a specific dictionary or dictionary column. Do not replace them with dictionary names unless the endpoint explicitly supports that.

### Combine identifiers in an envelope request

A send envelope request combines identifiers from different sources.

Use [Working with XML payloads](/guides/xml-payloads) for the complete XML structure and escaping rules.

Example:

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  <flow>
    <roles>
      <role id="{roleId}" mailboxUuid="{recipientMailboxUuid}"/>
    </roles>
  </flow>
  <documents>
    <document id="{documentId}">
      <field name="Customer name">ACME Ltd</field>
      <field name="Attachment" attachmentUuid="{attachmentUuid}">agreement.pdf</field>
    </document>
  </documents>
</envelope>
```

In this example:

{% columns %}
{% column %}

* `templateUuid` comes from the template
* `templateVersion` comes from the template
* `roleId` comes from the template flow
* `recipientMailboxUuid` comes from mailbox data
  {% endcolumn %}

{% column %}

* `documentId` comes from the template document
* `Customer name` comes from the template field name
* `Attachment` comes from the template file field name
* `attachmentUuid` comes from the file upload response
  {% endcolumn %}
  {% endcolumns %}

Each value has a different source. Mixing values from different templates, versions, accounts, or mailboxes can cause validation errors or access errors.

### Get reusable identifiers

Use the template structure to get:

{% columns %}
{% column %}

* template UUID
* template version
* role IDs
* document IDs
  {% endcolumn %}

{% column %}

* field names
* field group names
* field types
* field validation settings
  {% endcolumn %}
  {% endcolumns %}

Use mailbox endpoints or account data to get:

* sender mailbox UUID
* recipient mailbox UUIDs
* mailbox names and aliases

Use file upload endpoints to get:

* attachment UUID
* uploaded file name
* uploaded file size

Use the send envelope response to get:

* envelope UUID

Use account endpoints to get:

* account UUID
* domain UUID
* corporate user-related identifiers

Use dictionary endpoints or dictionary configuration to get:

* dictionary UUID
* dictionary column UUID

### Recommended workflow

Before building a request, collect all required identifiers and check that they belong to the same flow.

Recommended preparation checklist:

1. Select the template.
2. Read the current template version.
3. Copy role IDs from the selected template version.
4. Copy document IDs from the selected template version.
5. Copy field names from the selected documents.
6. Find recipient mailbox UUIDs.
7. Upload files if the envelope needs file fields.
8. Save attachment UUIDs from upload responses.
9. Build the envelope XML.
10. Send the request.
11. Save the returned envelope UUID.

This preparation reduces validation errors and makes the integration easier to debug.

### Store identifiers safely

Avoid hardcoding template versions, role IDs, document IDs, field names, or mailbox UUIDs directly in source code if these values can change.

For stable production integrations, it can be acceptable to store known identifiers in secure configuration. However, the integration should still be reviewed when the template changes.

If a template is updated, check whether the reusable identifiers used by the integration are still valid.

### Handle template changes

When a template changes, the template version can also change. If your integration sends envelopes from that template, make sure the request uses the correct template version and structure.

After a template update, check:

{% columns %}
{% column %}

* whether the template version changed
* whether role IDs are still the same
* whether document IDs are still the same
* whether required fields were added or removed
  {% endcolumn %}

{% column %}

* whether field names changed
* whether field validation rules changed
* whether dynamic tables or field groups changed
  {% endcolumn %}
  {% endcolumns %}

If the integration still uses old identifiers, the send request can fail or apply data incorrectly.

### Common mistakes

Common reusable identifier mistakes include:

{% columns %}
{% column %}

* using a template UUID from one template and a template version from another template
* using role IDs copied from an old template version
* assigning a mailbox UUID to the wrong role
* using a mailbox UUID that the token owner cannot access
* sending field values to the wrong document ID
* using field names that do not exist in the selected template
  {% endcolumn %}

{% column %}

* changing field names manually in the API request
* using a file name instead of an attachment UUID
* using an envelope UUID where the endpoint expects a mailbox UUID
* using a mailbox UUID where the endpoint expects an account UUID
* reusing identifiers from a test environment in production
* reusing production identifiers in a staging or local test environment
  {% endcolumn %}
  {% endcolumns %}

### Troubleshooting checklist

If a request fails or does not apply data correctly, check the identifiers first.

{% columns %}
{% column %}

* the template UUID and template version are correct
* the role IDs and document IDs belong to the selected template version
* each role has the correct mailbox UUID
* the token owner can access the selected mailbox
* field names and field group names match the template exactly
  {% endcolumn %}

{% column %}

* attachment UUIDs come from successful upload responses
* the envelope UUID was copied from the send response
* account UUIDs are used only for account-level endpoints
* dictionary UUIDs and column UUIDs match the selected dictionary configuration
* the integration is not mixing identifiers from different environments
  {% endcolumn %}
  {% endcolumns %}

### Related topics

{% columns %}
{% column width="33.33333333333333%" %}

* [Working with XML payloads](/guides/xml-payloads)
* [Send your first envelope](/introduction/send-your-first-envelope)
* [Send Envelope](/api-reference/send-envelope)
  {% endcolumn %}

{% column width="33.33333333333333%" %}

* [Search Mailboxes and Contacts](/api-reference/search-mailboxes-and-contacts)
* [Upload Attachments](/api-reference/upload-attachments)
  {% endcolumn %}

{% column %}

* [Create Template](/api-reference/create-template)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)
  {% endcolumn %}
  {% endcolumns %}


# Template Structure API

This document contains the template object structure, including the template information block and the XML stored in the data field.

Use this page to understand the template object returned by the API and the XML stored in the `data` field. Reuse the same template UUID, version, role IDs, document IDs, and field names in [Create Template](broken://spaces/cOltVL8GwCu4tL8RwTDW/pages/2zIRCHJBmubs0Xs05d0x), [Send Envelope](/api-reference/send-envelope), and [Fill Envelope](/api-reference/fill-envelope).

### Overview

The template object has two parts:

1. Template object fields.
2. Template XML in the `data` field.

The template object fields describe the template metadata. The `data` field stores the full template XML structure.

### Template object example

```json
{
  "access": "account",
  "archive": false,
  "categories": [0],
  "createdAt": "2026-06-04T10:00:00.000Z",
  "data": "<template>...</template>",
  "dataCreatedAt": "2026-06-04T10:00:00.000Z",
  "dataModifiedAt": "2026-06-04T10:00:00.000Z",
  "description": "Template description",
  "modifiedAt": "2026-06-04T10:00:00.000Z",
  "name": "Template name",
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "version": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

### Template object fields

<table><thead><tr><th width="140.20001220703125">Argument</th><th width="106.20001220703125">Format</th><th>Description</th></tr></thead><tbody><tr><td>access</td><td>string</td><td><p>Template access level:</p><p><strong>Mailbox</strong> — available only for the mailbox where it was created.</p><p><strong>Account</strong> — available for all account mailboxes where it was created.</p><p><strong>Public</strong> — available system-wide by UUID.</p></td></tr><tr><td>archive</td><td>boolean</td><td><p><strong>true</strong> — the template was deleted and moved to the archive.</p><p><strong>false</strong> — the template is active and available.</p></td></tr><tr><td>categories</td><td>Int(10)</td><td>Digit that corresponds to the category ID where the template is located</td></tr><tr><td>createdAt</td><td>string</td><td>Template creation date</td></tr><tr><td>dataCreatedAt</td><td>string</td><td>Template version creation date</td></tr><tr><td>modifiedAt</td><td>string</td><td>Template update date</td></tr><tr><td>dataModifiedAt</td><td>string</td><td>Template version update date</td></tr><tr><td>name</td><td>string</td><td>Template name</td></tr><tr><td>description</td><td>string</td><td>Template description</td></tr><tr><td>uuid</td><td>binary(16)</td><td>Template UUID (Universally Unique Identifier)</td></tr><tr><td>version</td><td>binary(16)</td><td>Template version UUID (Universally Unique Identifier)</td></tr></tbody></table>

{% hint style="info" %}
Treat `archive`, `createdAt`, `modifiedAt`, `dataCreatedAt`, and `dataModifiedAt` as response metadata. Do not build request logic around these values.
{% endhint %}

### Reusable identifiers

Use these values later in envelope requests:

* `uuid` — template UUID
* `version` — template version UUID
* `role id` — recipient role identifier
* `document id` — document identifier inside the template
* `field name` — field identifier used when sending values

### data field

{% hint style="info" %}
The `data` field contains template XML.
{% endhint %}

```xml
<template>
    <info>
        <name>TEST template</name>
        <description>TEST template</description>
        <subject/>
        <message/>
        <expire/>
    </info>
    <documents>
        <document id="ef247568-559a-4ec1-9ecc-6b44c9fb8215">
            <info>
                <title>New document</title>
            </info>
            <body>
                <div class="editor-div">
                    <field type="text" name="TEST template 1" roleId="fd8cb669-db1d-41e1-8f6c-2ad3f8fa981a" placeholder="TEST template 1"/>
                    <field type="number" name="TEST template 2" roleId="3f29b3a8-3baa-4218-80b1-5a0bb85af247" placeholder="TEST template 2" precision="0"/>
                </div>
            </body>
        </document>
        <document type="singleAttachment" id="43d47e65-011d-4890-9eaf-c1c6d860b3b2">
            <info>
                <title>New External Document 1</title>
            </info>
            <body>
                <field type="attachment" name="990f11c1-48de-4ac8-8479-a5989d5f08dc" roleId="fd8cb669-db1d-41e1-8f6c-2ad3f8fa981a" attachmentType="all"/>
            </body>
        </document>
    </documents>
    <signatures>
        <signature name="Test signer" roleId="348c486d-2901-4ecd-be0c-9a7e6c2ae2a2" documentId="ef247568-559a-4ec1-9ecc-6b44c9fb8215"/>
        <signature name="Test signer" roleId="348c486d-2901-4ecd-be0c-9a7e6c2ae2a2" documentId="43d47e65-011d-4890-9eaf-c1c6d860b3b2"/>
    </signatures>
    <flow>
        <roles>
            <role id="fd8cb669-db1d-41e1-8f6c-2ad3f8fa981a" title="Sender" type="sender" order="0"/>
            <role id="3f29b3a8-3baa-4218-80b1-5a0bb85af247" title="Assignee" type="assignee" order="1"/>
            <role id="348c486d-2901-4ecd-be0c-9a7e6c2ae2a2" title="Test signer" type="signer" order="2"/>
        </roles>
    </flow>
</template>
```

### How template XML is organized

The template XML contains these main blocks:

* `info` — template-level settings
* `documents` — structured and external documents
* `signatures` — signature placements
* `flow` — recipient roles and their order

#### Info

<table><thead><tr><th width="114.4000244140625">Argument</th><th>Description</th></tr></thead><tbody><tr><td>name</td><td>Template name</td></tr><tr><td>description</td><td>Template short description</td></tr><tr><td>subject</td><td>Envelope subject. You can provide it in the template or in the envelope</td></tr><tr><td>message</td><td>Envelope short message. You can provide it in the template or in the envelope</td></tr><tr><td>expire</td><td>Envelope expiration date — how many days after creation the envelope expires</td></tr></tbody></table>

#### Structured document info

| Argument    | Description         |
| ----------- | ------------------- |
| document id | Document identifier |
| title       | Document name       |

**Body**

This block contains static data such as text and tables, plus [dynamic fields](/guides/envelope-fields).

#### External document info

<table><thead><tr><th width="141.60003662109375">Argument</th><th>Description</th></tr></thead><tbody><tr><td>document type</td><td>Document type. This attribute is provided only for an external document. It can be <code>&#x3C;type="singleAttachment"></code></td></tr><tr><td>document id</td><td>Document identifier</td></tr><tr><td>title</td><td>Document name</td></tr></tbody></table>

**Body**

This block contains an [attachment field](/guides/files-and-external-documents) by default.

#### Signatures

| Argument    | Description         |
| ----------- | ------------------- |
| name        | Signature name      |
| role id     | Role identifier     |
| document id | Document identifier |

#### Flow

<table><thead><tr><th width="359">Argument</th><th>Description</th></tr></thead><tbody><tr><td>role id</td><td>Role identifier</td></tr><tr><td>title</td><td>Role name in the flow</td></tr><tr><td>type</td><td>Role type. Can be <code>sender</code>, <code>assignee</code>, or <code>signer</code></td></tr><tr><td>order</td><td>Role order number</td></tr></tbody></table>

### Related topics

* [Create Template](/api-reference/create-template)
* [Template Dynamic Fields API](broken://spaces/cOltVL8GwCu4tL8RwTDW/pages/wVbsBPDRRCULvm2TEDbj)
* [XML payloads](/guides/xml-payloads)


# XML payloads

This document explains how to build, escape, and validate XML payloads for DocStudio API requests.

{% hint style="info" %}
Some DocStudio API endpoints use XML payloads to describe templates, envelopes, documents, recipient roles, and field values.
{% endhint %}

### When XML payloads are used

DocStudio uses XML payloads when a request needs to describe a document or an envelope structure.\
XML is used because templates and envelopes can contain:

* documents
* fields
* roles
* field groups
* dynamic tables
* attachments
* workflow settings

Common API operations that can use XML payloads include:

{% columns %}
{% column %}

* creating a template
* creating and sending an envelope from a template
* filling fields in an existing envelope
* passing document field values
  {% endcolumn %}

{% column %}

* assigning recipient mailboxes to template roles
* referencing uploaded files in file fields
* working with dynamic tables and field groups
  {% endcolumn %}
  {% endcolumns %}

Not every API endpoint uses XML. Many endpoints use JSON, query parameters, path parameters, or file upload formats.

{% hint style="info" %}
Always check the API reference for the exact request format required by the endpoint.
{% endhint %}

### Send XML in the JSON data field

Use the readable XML form while preparing the payload. Send the same XML as a JSON string in the `data` field.

{% tabs %}
{% tab title="Readable XML" %}

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  <info>
    <subject>Envelope subject</subject>
    <message>Envelope message</message>
  </info>
</envelope>
```

{% endtab %}

{% tab title="JSON request body" %}

```json
{
  "data": "<envelope templateUuid=\"{templateUuid}\" templateVersion=\"{templateVersion}\"><info><subject>Envelope subject</subject><message>Envelope message</message></info></envelope>"
}
```

{% endtab %}
{% endtabs %}

### Main parts of an envelope XML payload

A basic envelope XML payload usually contains:

* envelope attributes
* envelope information
* workflow roles
* documents
* field values

**Example**:

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  <info>
    <subject>Envelope subject</subject>
    <message>Envelope message</message>
  </info>
  <flow>
    <roles>
      <role id="{roleId}" mailboxUuid="{mailboxUuid}"/>
    </roles>
  </flow>
  <documents>
    <document id="{documentId}">
      <field name="Customer name">ACME Ltd</field>
      <field name="Signing date">2026-07-15</field>
    </document>
  </documents>
</envelope>
```

#### Envelope attributes

The root envelope element connects the new envelope to a specific template and template version.

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  ...
</envelope>
```

Use values from the template structure:

* `templateUuid` identifies the template.
* `templateVersion` identifies the exact template version.

{% hint style="warning" %}
Use `templateUuid`, `templateVersion`, role IDs, document IDs, and field names from the same template version. Do not create or mix these values manually.
{% endhint %}

#### Envelope information

The info block contains general envelope information, such as the subject and message.

```xml
<info>
  <subject>Envelope subject</subject>
  <message>Envelope message</message>
</info>
```

Use this block to define what recipients see when they receive or open the envelope. The exact available properties depend on the endpoint and envelope settings.

#### Workflow roles

The flow block assigns real recipient mailboxes to roles from the template.

```xml
<flow>
  <roles>
    <role id="{roleId}" mailboxUuid="{mailboxUuid}"/>
  </roles>
</flow>
```

The `id` value comes from the template role. The `mailboxUuid` value identifies the mailbox assigned to that role in the envelope.

{% hint style="info" %}
The role defines what the participant must do, and the mailbox UUID defines who receives or processes that role.

If the role ID is copied from the wrong template or the mailbox UUID does not belong to an accessible mailbox, the request can fail or the envelope can be sent to the wrong participant.
{% endhint %}

#### Documents

The documents block contains the documents included in the envelope and the field values that must be applied to those documents.

```xml
<documents>
  <document id="{documentId}">
    <field name="Customer name">ACME Ltd</field>
    <field name="Signing date">2026-07-15</field>
  </document>
</documents>
```

{% hint style="info" %}

* The `documentId` must match the document ID from the template structure.
* Field names must match the field names from that document.
  {% endhint %}

Use the exact field names from the template. A different XML field name may prevent the value from being applied or cause a validation error.

#### Field values

Field values are passed inside field elements.

```xml
<field name="Customer name">ACME Ltd</field>
```

{% hint style="info" %}
Different field types can require different value formats:

* Text fields use plain text
* Date fields use a supported date format
* File fields reference an uploaded attachment
  {% endhint %}

File field example:

```xml
<field name="Attachment" attachmentUuid="{attachmentUuid}">agreement.pdf</field>
```

Do not use a local file path or file name as the **attachment identifier**, the `attachmentUuid` value must come from a previous file upload response.

#### Dynamic tables and field groups

Dynamic tables and grouped fields use nested field group structures.

Use field groups when the template contains repeatable table rows or grouped field sets.

**Example**:

```xml
<fieldgroup name="Products">
  <fieldset index="0">
    <field name="Product name">Service plan</field>
    <field name="Quantity">1</field>
    <field name="Price">100</field>
  </fieldset>
  <fieldset index="1">
    <field name="Product name">Support package</field>
    <field name="Quantity">2</field>
    <field name="Price">50</field>
  </fieldset>
</fieldgroup>
```

Each `fieldset` is one repeated row. Its `index` sets the row position.

Use field group and field names exactly as they appear in the template. Do not add names to the envelope request.

### Escape XML and JSON values

If a field value contains reserved characters, they must be escaped so the XML remains valid.

Use these XML escapes:

* `&amp;` for `&`
* `&lt;` for `<`
* `&gt;` for `>`
* `&quot;` for `"`
* `&apos;` for `'`

**Example**:

```xml
<field name="Company">ACME &amp; Partners</field>
```

If reserved characters are not escaped, the API may reject the request because the XML is not valid.

#### Escape JSON values

When XML is sent **inside** a JSON string, JSON escaping rules also apply. This means quotation marks inside XML attributes must be escaped.

**Readable XML**:

```xml
<role id="{roleId}" mailboxUuid="{mailboxUuid}"/>
```

**XML inside JSON**:

```json
{
  "data": "<role id=\"{roleId}\" mailboxUuid=\"{mailboxUuid}\"/>"
}
```

If you build requests in code, use a reliable XML builder and JSON serializer when possible. Avoid manually concatenating large XML strings if the integration can generate XML and serialize JSON safely.

### Do not send system-generated values

Some values are generated by DocStudio and should not be sent manually in XML payloads.

For example, DocStudio generates the following values:

* envelope status
* creation date
* completion data
* active role state
* other system-managed values

The platform controls these values.

Send only the values that the endpoint expects and that your integration needs to provide. Do not copy system-generated values from an existing envelope and try to reuse them in a new request.

### Get required values

Before building an envelope XML payload, collect the reusable identifiers from the correct sources.

Use the template structure to get:

{% columns %}
{% column %}

* template UUID
* template version
* role IDs
* document IDs
  {% endcolumn %}

{% column %}

* field names
* field group names
* field types
* validation settings
  {% endcolumn %}
  {% endcolumns %}

Use **mailbox endpoints** or **existing account data** to get:

* sender mailbox UUID
* recipient mailbox UUIDs
* mailbox context required by the endpoint

Use **file upload endpoints** to get:

* attachment UUIDs
* uploaded file metadata

Use the **send envelope response** to get:

* envelope UUID

{% hint style="info" %}
The envelope UUID is returned after the envelope is created or sent.

**Save it** because you will need it to check status, download documents, or get audit trail data.
{% endhint %}

### Common mistakes

Most XML payload issues happen when the request contains incorrect identifiers, invalid XML, or values that do not match the template configuration.

Common mistakes include:

{% columns %}
{% column %}

* using a template UUID from one template and role IDs from another template
* using an outdated template version
* creating role IDs, document IDs, or field names manually
* using a mailbox UUID that the token owner cannot access
* sending field values for fields that do not exist in the selected document
* using the wrong field value format
  {% endcolumn %}

{% column %}

* forgetting to escape XML reserved characters
* forgetting to escape quotation marks when XML is placed inside JSON
* sending XML that is not wrapped in the JSON data field
* using a file name instead of an attachment UUID for file fields
* copying system-generated envelope values into a new request
  {% endcolumn %}
  {% endcolumns %}

### Troubleshooting checklist

If an XML payload fails validation, check these points first:

{% columns %}
{% column %}

* The XML is valid and well-formed.
* The XML is passed as a string inside the JSON data field.
* Quotation marks are escaped correctly in the JSON string.
* Reserved XML characters are escaped in field values.
* The template UUID and template version are correct.
* Role IDs and document IDs match the selected template version.
* Mailbox UUIDs are correct and accessible.
  {% endcolumn %}

{% column %}

* Field names match the template exactly.
* Field values match the expected field types and validation rules.
* File fields use valid attachment UUIDs.
* Dynamic table and field group names match the template.
* The request does not include values that DocStudio generates automatically.
  {% endcolumn %}
  {% endcolumns %}

### Related topics

{% columns %}
{% column %}

* [Send your first envelope](/introduction/send-your-first-envelope)
* [Send Envelope](/api-reference/send-envelope)
* [Create Template](/api-reference/create-template)
  {% endcolumn %}

{% column %}

* [Fill Envelope](/api-reference/fill-envelope)
* [Upload Attachments](/api-reference/upload-attachments)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)
  {% endcolumn %}
  {% endcolumns %}


# Envelope Structure

This document contains the envelope XML structure, including the fields you can include in the request body.

Use this XML inside the `data` field of envelope API requests. Send only the fields your request needs.

{% hint style="info" %}
The platform generates some envelope properties automatically.
{% endhint %}

### Example

```xml
<envelope templateUuid="1997a1b4-88e3-4f58-88ca-fcd2c6fb5869" templateVersion="4a303734-a118-44a2-aedf-67df61612628">
    <info>
        <subject>Sales agreement</subject>
        <message>Please review the attached data.</message>
        <forwarding delegation="true" sharing="true"/>
    </info>
    <flow>
        <roles>
            <role id="74266bb8-91ad-4e35-9d98-5862fc59cf3e" mailboxUuid="8dcde243-a918-444a-ac7d-44ac88554769"/>
            <role id="a09d90c7-46c1-4f59-8d76-e7975dd8fab6" mailboxUuid="8dcde243-a918-444a-ac7d-44ac88554769"/>
        </roles>
    </flow>
    <documents>
        <document id="16c545db-1002-4efb-a4de-b46bc5ed4885">
            <field name="Text">text</field>
            <field name="Number">10</field>
            <field name="Currency">10.20</field>
            <field name="Date">2024-01-11</field>
            <field name="Dictionary" recordUuid="76d0b4a4-114f-45a6-9039-d654c90a2df2">Record name</field>
            <field name="Signature">data:image/png;base64,iVBORw...K5CYII=</field>
            <field name="File" attachmentUuid="dc317260-adf3-4231-8eaa-588759d7b6f7">agreement.pdf</field>
            <field name="Checkbox">1</field>
            <field name="Dropdown">2</field>
            <field name="Dropdown 2">
                <value>1</value>
                <value>2</value>
            </field>
            <field name="1234">Choice</field>
            <fieldgroup name="Table">
                <fieldset index="0">
                    <field name="Text 2">1</field>
                </fieldset>
                <fieldset index="1">
                    <field name="Text 2">2</field>
                </fieldset>
            </fieldgroup>
        </document>
    </documents>
</envelope>
```

### Envelope root

<table><thead><tr><th width="158">Attribute</th><th width="85">Type</th><th width="107">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>templateUuid</code></td><td>UUID</td><td>yes</td><td>Template ID used to create the envelope</td></tr><tr><td><code>templateVersion</code></td><td>UUID</td><td>yes</td><td>Template version ID used for validation</td></tr></tbody></table>

### Info block

Use `<info>` to define envelope-level communication settings, including the subject, message, expiration, and forwarding options.

<table><thead><tr><th width="214">Element or attribute</th><th width="90">Type</th><th width="108">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>subject</code></td><td>string</td><td>depends</td><td>Envelope subject</td></tr><tr><td><code>message</code></td><td>string</td><td>no</td><td>Short message for recipients</td></tr><tr><td><code>expire</code></td><td>integer</td><td>no</td><td>Number of days before the envelope expires</td></tr><tr><td><code>forwarding/@delegation</code></td><td>boolean</td><td>no</td><td>Allow delegation</td></tr><tr><td><code>forwarding/@sharing</code></td><td>boolean</td><td>no</td><td>Allow sharing</td></tr></tbody></table>

### Flow block

Use `<flow>` to define recipients and map template roles to mailbox IDs.

<table><thead><tr><th width="174">Element or attribute</th><th width="82">Type</th><th width="107">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>role/@id</code></td><td>UUID</td><td>yes</td><td>Role ID from the template</td></tr><tr><td><code>role/@mailboxUuid</code></td><td>UUID</td><td>yes</td><td>Mailbox ID assigned to that role</td></tr></tbody></table>

### Documents block

Use `<documents>` to send field values for each template document, including standard fields, dictionary references, file attachments, and table rows.

<table><thead><tr><th width="206">Element or attribute</th><th width="81">Type</th><th width="106">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>document/@id</code></td><td>UUID</td><td>yes</td><td>Document ID from the template</td></tr><tr><td><code>field/@name</code></td><td>string</td><td>yes</td><td>Template field name</td></tr><tr><td><code>field</code> value</td><td>string</td><td>depends</td><td>Field value, validated by the template</td></tr><tr><td><code>field/@recordUuid</code></td><td>UUID</td><td>depends</td><td>Dictionary record ID</td></tr><tr><td><code>field/@attachmentUuid</code></td><td>UUID</td><td>depends</td><td>Uploaded attachment ID</td></tr><tr><td><code>fieldgroup/@name</code></td><td>string</td><td>yes</td><td>Dynamic table name</td></tr><tr><td><code>fieldset/@index</code></td><td>integer</td><td>yes</td><td>Zero-based row index</td></tr></tbody></table>

### Dynamic field formats

#### Text, Number, Currency, Date, and single-select Dropdown

```xml
<field name="string">value</field>
```

* `name` — field name from the template
* value — field value

The platform validates the value against the template rules.

#### Multi-select Dropdown

```xml
<field name="string">
    <value>1</value>
    <value>2</value>
</field>
```

Use one `<value>` element for each selected option.

#### Dictionary

```xml
<field name="string" recordUuid="UUID">value</field>
```

* `name` — dictionary field name
* `recordUuid` — dictionary record ID
* value — record label, if needed

If you send both `recordUuid` and text, they must match.

#### Signature

```xml
<field name="string">data:image/png;base64,...</field>
```

Send the signature as a Base64 data URL.

#### File

```xml
<field name="string" attachmentUuid="UUID">filename.ext</field>
```

Upload the file first, then send the returned attachment ID. Use [Upload Attachments](/api-reference/upload-attachments) to get `attachmentUuid`.

#### Checkbox

```xml
<field name="string">1</field>
```

Send `1` to mark the checkbox as selected. Skip the field when it is optional and unchecked.

#### Choice

```xml
<field name="group-name">option-name</field>
```

* `name` — radio group name
* value — selected option name inside that group

#### Duplicate, Lookup, and Autonumber

Do not send these fields manually. The platform fills them automatically.

#### Dynamic table

```xml
<fieldgroup name="string">
    <fieldset index="0">
        <field name="Text 2">1</field>
    </fieldset>
    <fieldset index="1">
        <field name="Text 2">2</field>
    </fieldset>
</fieldgroup>
```

Add one `<fieldset>` for each row you need. Use a zero-based `index` for each row.

### Platform-generated fields

You may also encounter envelope properties generated by the platform.

* `created`
* `status`
* `date`
* `roleId`
* `active`
* `completed`

Treat these fields as system data unless an endpoint requires them.

### Related topics

* [Fill Envelope](/api-reference/fill-envelope)
* [Envelope fields](/guides/envelope-fields)


# Envelope fields

This document explains how to configure template fields and send valid field values in DocStudio envelopes.

### Configure fields and send values

{% columns %}
{% column %}

#### Configure in the template

Set the field type, name, role, validation, options, and placement.
{% endcolumn %}

{% column %}

#### Send in the envelope

Reuse the document ID and field name. Send only the field value.
{% endcolumn %}
{% endcolumns %}

Fields are configured in the template. The template defines the field type, field name, role, validation rules, placeholder, search behavior, and other settings.

Example template field:

```xml
<field
  type="text"
  name="customer_name"
  placeholder="Enter customer name"
  roleId="fd8cb669-db1d-41e1-8f6c-2ad3f8fa981a"
  optional="false"
  search="true"
  multilines="false"
  min="1"
  max="128"
/>
```

When you send or fill an envelope, you do not recreate the full field configuration. You reuse the field name from the template and pass the field value.

Example envelope field value:

```xml
<field name="customer_name">ACME Ltd</field>
```

{% hint style="warning" %}
Use the document ID and field name from the same template version. Do not recreate template field configuration in an envelope request.
{% endhint %}

### Field names

Field names connect envelope values with template fields. When you pass a value in an envelope request, DocStudio uses the field name to find the matching field in the selected document.

Example:

```xml
<field name="Customer name">ACME Ltd</field>
```

Use the exact field name from the template structure. Do not rename fields in the envelope request, even if the new name looks clearer. Field names must match the template field names and should stay unique within one document.

Use field names with 1 to 128 characters. Do not use `&`, `"`, `<`, or `>`.

### Role assignment

Most fields are assigned to a recipient role with `roleId`. The role defines which participant can fill, select, upload, or sign that field.

Example:

```xml
<field
  type="text"
  name="customer_name"
  roleId="{roleId}"
/>
```

The `roleId` comes from the template flow. When you send the envelope, the same role is assigned to a real recipient mailbox in the envelope flow.

Example:

```xml
<flow>
  <roles>
    <role id="{roleId}" mailboxUuid="{recipientMailboxUuid}"/>
  </roles>
</flow>
```

If a field is assigned to one role, another role should not try to fill it unless the workflow allows that action. When a fill request fails, check whether the current mailbox is assigned to the active role that owns the field.

### Common field attributes

Field attributes define field behavior in the template and envelope. Exact attributes depend on the field type.

{% columns %}
{% column %}

* `type` — field type
* `name` — field name used in envelope requests
* `roleId` — recipient role that fills the field
* `placeholder` — text shown in the template and envelope
* `optional` — whether a recipient can leave the field empty
* `search` — whether the field value is searchable
  {% endcolumn %}

{% column %}

* `min` and `max` — validation limits
* `precision` — supported number precision
* `dictionaryUuid` — source dictionary
* `columnUuid` — dictionary or lookup column
* `attachmentUuid` — uploaded file identifier in envelope values
  {% endcolumn %}
  {% endcolumns %}

Use only attributes supported by the selected field type.

### XML schemas

Use the **Template XSD** to check the supported field types and configuration attributes used in template XML. It defines field types, role assignments, validation settings, generated fields, PDF placement attributes, and other template configuration.

Use the **Envelope XSD** to validate the XML sent when an envelope is created or filled. Envelope XML reuses the document IDs and field names from the template and provides the values that must be applied to them.

**Download**:

{% file src="/files/z0bsTne1H8PQBnqabHG7" %}

{% file src="/files/xcomGoNpuIpbN4DBaKLM" %}

### Field types

Use field types that match the required value or template behavior:

{% columns %}
{% column %}

* text
* number
* currency
* date
* dropdown
* number-to-text
  {% endcolumn %}

{% column %}

* choice
* checkbox
* file
* dictionary
* lookup
* initials
  {% endcolumn %}

{% column %}

* dynamic table
* duplicate
* formula
* autonumber
* signature
  {% endcolumn %}
  {% endcolumns %}

Some fields accept values. Others generate or derive values from template configuration.

### Simple input fields

Simple input fields collect values such as text, numbers, currency amounts, and dates.

Use text fields for plain text. Configure single-line or multiline input and character limits.

Example envelope value:

```xml
<field name="customer_name">ACME Ltd</field>
```

Use number fields for numeric values. Configure formatting, precision, trailing zeros, and numeric limits.

Example envelope value:

```xml
<field name="invoice_amount">1250.50</field>
```

Use currency fields for monetary values. Currency fields use precision `2` and trailing zeros.

Example envelope value:

```xml
<field name="payment_amount">1250.50</field>
```

Use date fields for date or date-time values. Send dates in a format supported by the field configuration, such as `2019-12-31T23:59:59+02:00` or `2019-12-31T23:59:59Z`.

Example envelope value:

```xml
<field name="signing_date">2026-07-15T10:00:00Z</field>
```

### Selection fields

Selection fields let users choose one or more predefined values.

Dropdown fields define a list of options inside the template. The field can also allow custom values or multiple selected values if configured, but `allowCustomValue` and `multiSelect` must not be used together.

Template example:

```xml
<field
  type="dropdown"
  name="country"
  placeholder="Select country"
  roleId="{roleId}"
  optional="false"
  search="true"
>
  <option>USA</option>
  <option>Germany</option>
  <option>Japan</option>
</field>
```

Envelope value example:

```xml
<field name="country">Germany</field>
```

Choice fields work as radio button groups. In the template, each option is a separate field with `type="radio"`, the same `name`, and a different `value`.

Template example:

```xml
<field
  type="radio"
  name="approval"
  value="approved"
  roleId="{roleId}"
  search="true"
/>

<field
  type="radio"
  name="approval"
  value="rejected"
  roleId="{roleId}"
  search="true"
/>
```

Only one option can be selected in the envelope.

Checkbox fields are used when the recipient must select or confirm a checkbox value.

Template example:

```xml
<field
  type="checkbox"
  name="accept_terms"
  roleId="{roleId}"
  search="true"
  optional="false"
/>
```

Use the checkbox field reference for the exact accepted value format when sending or filling checkbox values through the API.

### File fields

File fields let a recipient or integration attach a file to a field. API integrations must upload the file first, then use the returned uploaded file identifier in the envelope XML.

Upload response example:

```json
{
  "attachmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "filename": "contract.pdf",
  "filesize": 0
}
```

Envelope field value example:

```xml
<field name="File" attachmentUuid="3fa85f64-5717-4562-b3fc-2c963f66afa6">contract.pdf</field>
```

Use `attachmentId` from the upload response as `attachmentUuid` in the envelope XML. Use the returned filename as the field value. Do not use a local file path, external file URL, or filename as a replacement for `attachmentUuid`.

### Number-to-text fields

A Number to text field displays the value of a Number, Currency, or Formula field as words. It is generated automatically and cannot be filled directly by a recipient or integration.

In template XML, Number to text is represented by the `number-to-text` element rather than a regular `field` element. The required attributes are `name`, `relatedTo`, and `language`; `currency` is optional.

```xml
<field
  type="money"
  name="Contract amount"
  roleId="customer"
  precision="2"
/>

<number-to-text
  name="Contract amount in words"
  relatedTo="Contract amount"
  currency="USD"
  language="en"
/>
```

Fill only the source field in the envelope XML. DocStudio generates and updates the Number to text value automatically.

```xml
<field name="Contract amount">1000.00</field>
```

### Dictionary fields

Dictionary fields let users select values from a predefined dataset. They are useful when field values must come from controlled business data, such as customers, departments, products, regions, or other reference lists.

Template example:

```xml
<field
  type="select-dictionary"
  name="customer"
  placeholder="Select customer"
  roleId="{roleId}"
  optional="false"
  allowCustomValue="false"
  search="true"
  dictionaryUuid="{dictionaryUuid}"
  columnUuid="{columnUuid}"
/>
```

A dictionary field uses `dictionaryUuid` to reference the source dictionary and `columnUuid` to define which dictionary column is displayed as text. If the template uses dictionary fields, make sure the dictionary and column UUIDs belong to the expected dictionary configuration.

### Lookup fields

Lookup fields show related data from a dictionary field in the same document. They display a value from a selected dictionary column.

Template example:

```xml
<lookup
  name="customer_city"
  placeholder="Select city"
  optional="false"
  allowCustomValue="false"
  search="true"
  documentId="{documentId}"
  relatedTo="customer"
  columnUuid="{columnUuid}"
/>
```

Use lookup fields to provide related values from a selected dictionary entry.

### Dynamic tables and grouped fields

Dynamic tables use repeated field groups. Use them when an envelope needs a variable number of rows.

Example:

```xml
<fieldgroup name="Products">
  <fieldset index="0">
    <field name="Product name">Service plan</field>
    <field name="Quantity">1</field>
    <field name="Price">100</field>
  </fieldset>
  <fieldset index="1">
    <field name="Product name">Support package</field>
    <field name="Quantity">2</field>
    <field name="Price">50</field>
  </fieldset>
</fieldgroup>
```

Each `fieldset` represents one repeated group or table row. The `index` identifies the repeated set position. Use the exact field group name and field names from the template structure.

### Generated and calculated fields

Some fields should not be filled manually in envelope requests because DocStudio calculates, copies, or generates their values from template configuration or other fields.

This group can include:

* duplicate fields
* formula fields
* autonumber fields
* lookup fields, when the value is derived from a related dictionary field

Use these fields in the template when the value must be generated or derived automatically. In envelope requests, fill the source fields that control the generated value, not the generated field itself, unless the field reference explicitly says otherwise.

{% hint style="warning" %}
Do not fill duplicate, formula, autonumber, or derived lookup fields manually. Send values only for their source fields.
{% endhint %}

### Signature fields

Signature fields define where and how a recipient signs. In the API field reference, the signature field type is `einksign`.

Signature field values can use Base64 PNG data and have image size limits. Use the signature field reference for the exact value requirements before sending or filling signature data through the API.

Example template field:

```xml
<field
  type="einksign"
  name="signature"
  roleId="{roleId}"
/>
```

Do not treat a signature field as a regular text field. It has its own format and validation rules.

### PDF fields

Uploaded PDF templates can also use dynamic fields. For PDF templates, fields require additional placement attributes so DocStudio knows where to render the field on the PDF page.

PDF field placement can include:

* `x`
* `y`
* `width`
* `height`
* `page`

Example:

```xml
<field
  type="text"
  name="customer_name"
  roleId="{roleId}"
  x="69.05625"
  y="257.61597"
  width="30.69167"
  height="7.9375"
  page="0"
/>
```

Use PDF field attributes only when the field must be placed on an uploaded PDF template. For regular structured templates, field placement is handled by the template structure.

### Initials fields

An Initials field collects a recipient’s initials instead of a full electronic signature. In template XML, use a regular `field` element with `type="initials"` and assign it to the role that must complete the field.

```xml
<field
  type="initials"
  name="Customer initials"
  roleId="customer"
/>
```

For a field placed on a PDF, use the PDF placement attributes defined in the Template XSD, including `page`, `x`, `y`, `width`, and `height`. The assigned recipient completes the field when processing the envelope.

### Searchable fields

Some fields support the `search` attribute. When `search="true"`, the field value can be available in envelope search.

Example:

```xml
<field
  type="text"
  name="customer_name"
  roleId="{roleId}"
  search="true"
/>
```

Use searchable fields for values that must be found later. Do not make every field searchable.

### Optional and required fields

The `optional` attribute controls whether a recipient can leave a field empty. If a required field does not receive a value, the envelope may not move forward until the active participant fills it.

Example required field:

```xml
<field
  type="text"
  name="customer_name"
  roleId="{roleId}"
  optional="false"
/>
```

Example optional field:

```xml
<field
  type="text"
  name="comment"
  roleId="{roleId}"
  optional="true"
/>
```

Use required fields for mandatory values. Use optional fields for values that may be unavailable.

### Field validation

Field validation is defined in the template and applied when the envelope is sent or filled. Validation can depend on the field type and configuration.

Examples:

{% columns %}
{% column %}

* text fields can validate character count
* number and currency fields can validate numeric range
* date fields can validate allowed date offsets
* dropdown fields can validate allowed options
  {% endcolumn %}

{% column %}

* dictionary fields can validate dictionary values
* file fields can validate uploaded attachment references
* signature fields can validate signature format and size
  {% endcolumn %}
  {% endcolumns %}

If the API request sends a value that does not match the field configuration, DocStudio can reject the request or return a validation error.

### Send field values in envelope XML

When you send an envelope, field values are placed inside the document that contains those fields.

Example:

```xml
<documents>
  <document id="{documentId}">
    <field name="customer_name">ACME Ltd</field>
    <field name="invoice_amount">1250.50</field>
    <field name="signing_date">2026-07-15T10:00:00Z</field>
  </document>
</documents>
```

The document ID and field names must come from the same template version. Do not mix field values from one template with document IDs from another template.

Use one payload to combine values for different field types:

```xml
<documents>
  <document id="{documentId}">
    <field name="customer_name">ACME Ltd</field>
    <field name="signing_date">2026-07-15T10:00:00Z</field>
    <field name="customer">ACME Ltd</field>
    <field name="File" attachmentUuid="{attachmentId}">contract.pdf</field>
  </document>
</documents>
```

### Validation checklist

If field values are not applied or validation fails, check these points:

{% columns %}
{% column %}

* The field exists in the selected template version.
* The field name matches the template exactly.
* The field is placed under the correct document ID.
* The field belongs to the expected recipient role.
* The current mailbox can fill the field at this workflow step.
* The field value matches the field type.
* Required fields are not empty.
  {% endcolumn %}

{% column %}

* Number, currency, date, and text values match validation rules.
* Dropdown or choice values match allowed options.
* Dictionary fields use the correct dictionary and column UUIDs.
* File fields use valid uploaded attachment UUIDs.
* Dynamic table field groups use the correct group name and fieldset indexes.
* PDF fields include placement attributes for uploaded PDF templates.
* Reserved XML characters are escaped correctly.
  {% endcolumn %}
  {% endcolumns %}

### Related topics

{% columns %}
{% column %}

* [Working with XML payloads](/guides/xml-payloads)
* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids)
* [Send your first envelope](/introduction/send-your-first-envelope)
  {% endcolumn %}

{% column %}

* [Fill Envelope](/api-reference/fill-envelope)
* [Upload Attachments](/api-reference/upload-attachments)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)
  {% endcolumn %}
  {% endcolumns %}


# Files and external documents

This document explains how to upload files and use them in DocStudio envelopes.

### Upload attachment

Use this endpoint to upload a new attachment.

| Method | Endpoint                      |
| ------ | ----------------------------- |
| `POST` | `/api/v1/envelope/attachment` |

### Headers

<table><thead><tr><th width="189.4444580078125">Header</th><th width="116.7777099609375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td>Use <code>multipart/form-data</code></td></tr><tr><td><code>Mailbox</code></td><td>No</td><td>Mailbox context header with the current mailbox UUID</td></tr></tbody></table>

### Query parameters

| Parameter | Type   | Required | Description                                                          |
| --------- | ------ | -------- | -------------------------------------------------------------------- |
| `type`    | string | No       | Uploaded file type: `all`, `document`, `file`, `image`, or `archive` |

Use `type` to specify the uploaded file category. Omit the parameter when no category is needed.

| Value      | Description              |
| ---------- | ------------------------ |
| `all`      | All supported file types |
| `document` | Document files           |
| `file`     | Files                    |
| `image`    | Image files              |
| `archive`  | Archive files            |

### Request body

The endpoint accepts `multipart/form-data`. The uploaded file must be passed in the required `file` field.

| Field  | Type   | Required | Description    |
| ------ | ------ | -------- | -------------- |
| `file` | binary | Yes      | File to upload |

```http
POST /api/v1/envelope/attachment?type=document
Authorization: Bearer {token}
Content-Type: multipart/form-data
Mailbox: {mailboxUuid}

file=@contract.pdf
```

### Response

The endpoint returns `201 Created` with information about the uploaded attachment.

```json
{
  "filename": "contract.pdf",
  "attachmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "filesize": 204800,
  "contentType": "application/pdf",
  "updatedPdf": "string"
}
```

<table><thead><tr><th width="161.2222900390625">Field</th><th width="163">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>filename</code></td><td>string</td><td>Uploaded file name</td></tr><tr><td><code>attachmentId</code></td><td>UUID</td><td>Uploaded attachment ID</td></tr><tr><td><code>filesize</code></td><td>integer</td><td>Uploaded file size in bytes</td></tr><tr><td><code>contentType</code></td><td>string</td><td>Uploaded file content type</td></tr><tr><td><code>updatedPdf</code></td><td>byte string</td><td>Updated PDF data, when included in the response</td></tr></tbody></table>

Save the `attachmentId` value from the response. This value is the uploaded file identifier that must be used later in envelope XML.

### Status codes

| Code | Description                      |
| ---- | -------------------------------- |
| 201  | Attachment uploaded successfully |

### Use the uploaded file in envelope XML

Pass `response.attachmentId` to the `attachmentUuid` attribute in envelope XML.

<table><thead><tr><th width="187.888916015625">Upload response field</th><th width="198.888916015625">Envelope XML attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>attachmentId</code></td><td><code>attachmentUuid</code></td><td>Uploaded file ID returned by the upload endpoint and used as the uploaded file reference in envelope XML</td></tr><tr><td><code>filename</code></td><td>Field value</td><td>Uploaded file name, used as the field value when the template expects a visible file name</td></tr></tbody></table>

#### External document

Use this structure for an external document.

```xml
<document id="{documentId}" attachmentUuid="{attachmentId}" />
```

#### File upload field

Use this structure for a file upload field.

```xml
<document id="{documentId}">
  <field name="File" attachmentUuid="{attachmentId}">contract.pdf</field>
</document>
```

The field name must match the field name in the selected template. The document ID must also belong to the same template version that is used in the envelope request.

{% hint style="warning" %}
Use `multipart/form-data` and include the required `file` field. Pass the returned `attachmentId` to `attachmentUuid`. Do not use a local path, external URL, or generated UUID.
{% endhint %}

### Related topics

{% columns %}
{% column %}

* [Authentication and application tokens](/introduction/authentication-and-application-tokens)
* [Working with XML payloads](/guides/xml-payloads)
* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids)
  {% endcolumn %}

{% column %}

* [Working with envelope fields](/guides/envelope-fields)
* [Send your first envelope](/introduction/send-your-first-envelope)
* [Send Envelope](/api-reference/send-envelope)
  {% endcolumn %}
  {% endcolumns %}


# Envelope metadata

This document explains how to add, manage, display, and use envelope metadata.

### Metadata object format

Use metadata to store integration data with an envelope. Metadata does not become document content.

```json
{
  "customerId": "C-1024",
  "approved": true,
  "externalReference": null
}
```

| Rule                  | Value                       |
| --------------------- | --------------------------- |
| Key length            | 1–32 characters             |
| Value length          | 0–128 characters            |
| Supported value types | `string`, `boolean`, `null` |

Use document fields for values that appear in or are validated by the document.

### Add metadata when sending an envelope

Add metadata to the `POST /api/v1/envelope/send` request body with envelope XML in `data`.

```json
{
  "data": "<envelope templateUuid=\"{templateUuid}\" templateVersion=\"{templateVersion}\">...</envelope>",
  "metadata": {
    "customerId": "C-1024",
    "crmRecordId": "CRM-77551",
    "priority": true
  }
}
```

### Update envelope metadata

Add new metadata keys or overwrite existing values.

| Method | Endpoint                         |
| ------ | -------------------------------- |
| `PUT`  | `/api/v1/envelope/{id}/metadata` |

Headers:

<table><thead><tr><th width="143.2222900390625">Header</th><th width="147.8887939453125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td>Use <code>application/json</code></td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>Mailbox context header with the current mailbox UUID</td></tr></tbody></table>

Path parameters:

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id`      | UUID | Yes      | Envelope ID |

Request body:

```json
{
  "customerId": "C-1024",
  "approved": true,
  "externalReference": null
}
```

### Status codes

| Code | Description                   |
| ---- | ----------------------------- |
| 200  | Metadata updated successfully |

The response body is empty.

### Delete envelope metadata

Delete selected metadata keys with one or more `key` parameters. Omit `key` to delete all metadata.

| Method   | Endpoint                         |
| -------- | -------------------------------- |
| `DELETE` | `/api/v1/envelope/{id}/metadata` |

Headers:

<table><thead><tr><th width="188.888916015625">Header</th><th width="107.8887939453125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>Mailbox context header with the current mailbox UUID</td></tr></tbody></table>

Path parameters:

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id`      | UUID | Yes      | Envelope ID |

Query parameters:

<table><thead><tr><th width="115.888916015625">Parameter</th><th width="138.888916015625">Type</th><th width="106">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>key</code></td><td>array of strings</td><td>No</td><td>Metadata key or keys to delete; omit this parameter to delete all envelope metadata</td></tr></tbody></table>

Delete selected metadata keys:

```http
DELETE /api/v1/envelope/{id}/metadata?key=customerId&key=approved
Authorization: Bearer {token}
Mailbox: {mailboxUuid}
```

Delete all envelope metadata:

```http
DELETE /api/v1/envelope/{id}/metadata
Authorization: Bearer {token}
Mailbox: {mailboxUuid}
```

### Status codes

| Code | Description                   |
| ---- | ----------------------------- |
| 200  | Metadata deleted successfully |

The response body is empty.

### Read envelope metadata

There is no separate `GET metadata` endpoint. Retrieve the envelope and read its `metadata` object.

```json
{
  "envelope": {
    "uuid": "89499ba2-287d-404c-87b0-342dc5b01b6a",
    "status": "WAITING",
    "metadata": {
      "customerId": "C-1024",
      "crmRecordId": "CRM-77551",
      "priority": true
    }
  }
}
```

Use the returned values to match the envelope with records in an external system.

### Display metadata in envelope details

Add this element to the template info section:

```xml
<metadata show="true" />
```

Metadata appears in envelope details only when this element is present and metadata is not empty.

### Metadata in envelope forms and callbacks

Envelopes created from a form inherit its metadata. Callbacks can include this metadata for envelopes created from forms.

### What not to store in metadata

Do not store secrets, credentials, document content, files, or large data blocks in metadata.

{% columns %}
{% column %}

* API tokens
* passwords
* private keys
* access credentials
* full personal records
  {% endcolumn %}

{% column %}

* large text blocks
* document content
* files or Base64 file data
* values longer than the supported limit
* data that should be stored in a document field instead
  {% endcolumn %}
  {% endcolumns %}

{% hint style="warning" %}
Use a valid JSON object that follows metadata rules. Add `<metadata show="true" />` to display metadata. A delete request without `key` removes all envelope metadata.
{% endhint %}

### Related topics

* [Send Envelope](/api-reference/send-envelope)
* [Check Envelope Status](/api-reference/check-envelope-status)
* [Working with XML payloads](/guides/xml-payloads)
* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids)


# Envelope callbacks

This document contains the endpoint reference for creating and managing envelope callbacks.

### Create callback

| Method | Endpoint                        |
| ------ | ------------------------------- |
| `POST` | `/api/v1/envelope/callback/add` |

Headers:

<table><thead><tr><th width="152.6666259765625">Header</th><th width="134.5555419921875">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td>Use <code>application/json</code></td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>Mailbox context header with the current mailbox UUID</td></tr></tbody></table>

Request body:

```json
{
  "url": "string",
  "retries": 3,
  "timeout": 5000,
  "successCode": 200,
  "login": "string",
  "password": "string",
  "filter": {
    "label": [
      "string"
    ],
    "status": [
      "DRAFT"
    ],
    "subject": "string",
    "createDateFrom": "2026-07-21T15:58:42.779Z",
    "createDateTo": "2026-07-21T15:58:42.779Z",
    "receiveDateFrom": "2026-07-21T15:58:42.779Z",
    "receiveDateTo": "2026-07-21T15:58:42.779Z",
    "expireDateFrom": "2026-07-21T15:58:42.779Z",
    "expireDateTo": "2026-07-21T15:58:42.779Z",
    "sendDateFrom": "2026-07-21T15:58:42.779Z",
    "sendDateTo": "2026-07-21T15:58:42.779Z",
    "template": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "templateVersion": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "sender": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "form": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "metadata": {
      "externalId": "CRM-1024"
    }
  }
}
```

Request body fields:

<table><thead><tr><th width="132">Field</th><th width="90.333251953125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>url</code></td><td>string</td><td>Callback URL</td></tr><tr><td><code>retries</code></td><td>integer</td><td>Number of callback retry attempts, default: <code>3</code>, maximum: <code>10</code></td></tr><tr><td><code>timeout</code></td><td>integer</td><td>Request timeout in milliseconds, default: <code>5000</code></td></tr><tr><td><code>successCode</code></td><td>integer</td><td>HTTP response code that DocStudio treats as successful, default: <code>200</code></td></tr><tr><td><code>login</code></td><td>string</td><td>Login for Basic authentication, when the callback URL requires it</td></tr><tr><td><code>password</code></td><td>string</td><td>Password for Basic authentication, when the callback URL requires it</td></tr><tr><td><code>filter</code></td><td>object</td><td>Envelope filter that defines which envelopes trigger the callback</td></tr></tbody></table>

The request body is required. The Swagger schema does not mark individual body fields as required.

### Filter fields

Use the `filter` object to limit when the callback is sent. For envelope form callbacks, use the `form` array and pass one or more form UUIDs. If the callback must trigger only for completed envelopes created from a specific form, combine `form` with `status: ["COMPLETED"]`.

<table><thead><tr><th width="179">Field</th><th width="165.111083984375">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>label</code></td><td>array of strings</td><td>Label UUID or name</td></tr><tr><td><code>status</code></td><td>array of strings</td><td>Envelope status; supported values: <code>DRAFT</code>, <code>SENT</code>, <code>WAITING</code>, <code>COMPLETED</code>, <code>CANCELLED</code>, <code>EXPIRED</code>, <code>ON_APPROVAL</code></td></tr><tr><td><code>subject</code></td><td>string</td><td>Envelope subject</td></tr><tr><td><code>createDateFrom</code></td><td>date-time</td><td>Creation date from</td></tr><tr><td><code>createDateTo</code></td><td>date-time</td><td>Creation date to</td></tr><tr><td><code>receiveDateFrom</code></td><td>date-time</td><td>Receive date from</td></tr><tr><td><code>receiveDateTo</code></td><td>date-time</td><td>Receive date to</td></tr><tr><td><code>expireDateFrom</code></td><td>date-time</td><td>Expiration date from</td></tr><tr><td><code>expireDateTo</code></td><td>date-time</td><td>Expiration date to</td></tr><tr><td><code>sendDateFrom</code></td><td>date-time</td><td>Envelope sending date from</td></tr><tr><td><code>sendDateTo</code></td><td>date-time</td><td>Envelope sending date to</td></tr><tr><td><code>template</code></td><td>array of UUIDs</td><td>Template IDs</td></tr><tr><td><code>templateVersion</code></td><td>array of UUIDs</td><td>Template version IDs</td></tr><tr><td><code>sender</code></td><td>array of UUIDs</td><td>Sender mailbox IDs</td></tr><tr><td><code>form</code></td><td>array of UUIDs</td><td>Form IDs, used to target envelopes created from selected forms</td></tr><tr><td><code>metadata</code></td><td>object</td><td>Metadata key-value pairs used as callback filter criteria</td></tr></tbody></table>

### Create callback for a form

Use this structure when the callback must be sent only for envelopes created from a specific envelope form. Replace `{formUuid}` with the actual form UUID and set the required target status for your integration.

```json
{
  "url": "https://example.com/docstudio/callback",
  "retries": 3,
  "timeout": 5000,
  "successCode": 200,
  "filter": {
    "status": [
      "COMPLETED"
    ],
    "form": [
      "{formUuid}"
    ]
  }
}
```

This callback matches envelopes created from the selected form with the `COMPLETED` status.

### Create callback response

The endpoint returns `201 Created` with the created callback configuration. Save the returned `id`; it is the callback UUID used by callback management endpoints.

```json
{
  "url": "string",
  "retries": 3,
  "timeout": 5000,
  "successCode": 200,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "authType": "NONE",
  "filter": {
    "label": [
      "string"
    ],
    "status": [
      "DRAFT"
    ],
    "subject": "string",
    "createDateFrom": "2026-07-21T15:58:42.780Z",
    "createDateTo": "2026-07-21T15:58:42.780Z",
    "receiveDateFrom": "2026-07-21T15:58:42.780Z",
    "receiveDateTo": "2026-07-21T15:58:42.780Z",
    "expireDateFrom": "2026-07-21T15:58:42.780Z",
    "expireDateTo": "2026-07-21T15:58:42.780Z",
    "sendDateFrom": "2026-07-21T15:58:42.780Z",
    "sendDateTo": "2026-07-21T15:58:42.780Z",
    "template": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "templateVersion": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "sender": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "form": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "metadata": {
      "externalId": "CRM-1024"
    }
  }
}
```

Response fields:

<table><thead><tr><th width="178.66650390625">Field</th><th width="143.4444580078125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>url</code></td><td>string</td><td>Callback URL</td></tr><tr><td><code>retries</code></td><td>integer</td><td>Number of retry attempts</td></tr><tr><td><code>timeout</code></td><td>integer</td><td>Request timeout in milliseconds</td></tr><tr><td><code>successCode</code></td><td>integer</td><td>HTTP response code treated as successful</td></tr><tr><td><code>id</code></td><td>UUID</td><td>Envelope callback ID</td></tr><tr><td><code>authType</code></td><td>string</td><td>Authentication type; supported values: <code>NONE</code>, <code>BASIC</code></td></tr><tr><td><code>filter</code></td><td>object</td><td>Envelope filter used by the callback</td></tr></tbody></table>

### Status codes

| Code | Description                   |
| ---- | ----------------------------- |
| 201  | Callback created successfully |

### List callbacks

| Method | Endpoint                         |
| ------ | -------------------------------- |
| `GET`  | `/api/v1/envelope/callback/list` |

Headers:

<table><thead><tr><th width="150.111083984375">Header</th><th width="158">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>Mailbox context header with the current mailbox UUID</td></tr></tbody></table>

The response is an array of callback objects in the [create callback response](#create-callback-response) format.

### Status codes

| Code | Description                     |
| ---- | ------------------------------- |
| 200  | Callbacks returned successfully |

### Callback payload example

<table><thead><tr><th width="298.4444580078125">Method</th><th>Endpoint</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/v1/envelope/callback/callbackRequestPayload</code></td></tr></tbody></table>

Response:

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "DRAFT",
  "subject": "string",
  "label": [
    "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  ],
  "receiveDate": "2026-07-21T16:00:22.093Z",
  "expireDate": "2026-07-21T16:00:22.093Z",
  "template": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sender": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "mailbox": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

Payload fields:

| Field         | Type           | Description              |
| ------------- | -------------- | ------------------------ |
| `uuid`        | UUID           | Envelope UUID            |
| `status`      | string         | Envelope status          |
| `subject`     | string         | Envelope subject         |
| `label`       | array of UUIDs | Envelope labels          |
| `receiveDate` | date-time      | Envelope receive date    |
| `expireDate`  | date-time      | Envelope expiration date |
| `template`    | UUID           | Template UUID            |
| `sender`      | UUID           | Sender mailbox UUID      |
| `mailbox`     | UUID           | Current mailbox UUID     |

### Status codes

| Code | Description                       |
| ---- | --------------------------------- |
| 200  | Callback payload example returned |

{% hint style="warning" %}
Make sure the envelope matches the callback filter. Return the configured `successCode` before the configured `timeout`.
{% endhint %}

### Related topics

* [Metadata](/guides/envelope-metadata)
* [Check Envelope Status](/api-reference/check-envelope-status)
* [Working with XML payloads](/guides/xml-payloads)


# List responses

This document explains how to paginate, filter, sort, and search list responses in DocStudio API.

{% hint style="info" %}
This guide focuses on mailbox envelope lists and mailbox search. Use the API reference for each endpoint's complete parameter list and response schema.
{% endhint %}

### Use pagination for mailbox envelope lists

Pagination processes a large result set in smaller pages. Request one page, process its records, and then request the next page.

Use pagination when you synchronize or process envelopes regularly. Avoid loading an entire mailbox in one request.

#### Pagination parameters

Use these query parameters where the endpoint supports them:

* `limit` — maximum records in one response
* `offset` — records to skip before returning the page

Start with a moderate page size, such as `20`, `50`, or `100`. Confirm supported limits in the endpoint reference.

#### Request the first page

```http
GET /api/v1/mailbox/{mailboxUuid}?limit=20&offset=0
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {mailboxUuid}
```

This request returns the first page with up to 20 records.

Request the next page with the same `limit` and an increased `offset`.

```http
GET /api/v1/mailbox/{mailboxUuid}?limit=20&offset=20
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {mailboxUuid}
```

### Process pages safely

Use response metadata to decide whether another page exists.

```json
{
  "totalElements": 57,
  "sizeRequested": 20,
  "numberOfElements": 20,
  "data": []
}
```

Use these values like this:

* `totalElements` — total matching records
* `sizeRequested` — page size accepted by the server
* `numberOfElements` — records in the current response
* `data` — returned records

Stop when `data` is empty or `numberOfElements` is smaller than `sizeRequested`.

Follow this flow:

1. Send the first request with `limit=20` and `offset=0`.
2. Process the returned records.
3. Send the next request with `limit=20` and `offset=20`.
4. Continue increasing `offset` by `limit`.
5. Stop when the response is empty or shorter than `sizeRequested`.

{% hint style="warning" %}
Offset pagination does not create a fixed data snapshot. New or changed envelopes can cause duplicates or skipped records. Save processed envelope UUIDs and deduplicate results during synchronization.
{% endhint %}

### Filter and sort envelope lists

Keep every filter and the sorting direction unchanged during one pagination run. Changing them can return unexpected records or skip matching envelopes.

Use `scope=inbox` for received envelopes. Use `scope=outbox` for sent envelopes.

Use `sort=desc` to process newer results first. Use `sort=asc` to process older results first.

Use specific filters when possible. The mailbox endpoint supports filters for status, archive state, sender, template, labels, subject, and date periods. It also supports `q` where text search is appropriate.

```http
GET /api/v1/mailbox/{mailboxUuid}?scope=outbox&status=COMPLETED&template={templateUuid}&archived=false&limit=50&offset=0&sort=desc
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {mailboxUuid}
```

Use this pattern to synchronize completed, unarchived envelopes from one template.

{% hint style="info" %}
Check the [Check Envelope Status](/api-reference/check-envelope-status) reference for supported filter values and date-period formats.
{% endhint %}

#### Encode query values

Encode spaces and special characters in query values. Use an HTTP client or URL builder that encodes parameters automatically.

```http
GET /api/v1/mailbox/{mailboxUuid}?q=Sales%20agreement&limit=20&offset=0
```

### Search mailboxes and contacts

Use mailbox search before assigning a recipient to a template role. The required `q` parameter searches mailbox UUIDs, aliases, names, and contact names.

```http
GET /api/v1/mailbox/search?q=john.doe@example.com
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {mailboxUuid}
```

Save the returned mailbox UUID and use it when you assign a recipient role.

Do not use mailbox search to check envelope status. Use the mailbox envelope endpoint for envelope lists and status checks.

### Get one envelope

Pass `UUID` when you already know the envelope UUID and need full envelope data with its template.

```http
GET /api/v1/mailbox/{mailboxUuid}?UUID={envelopeUuid}
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {mailboxUuid}
```

`mailboxUuid` identifies the target mailbox and current mailbox context. `envelopeUuid` identifies the requested envelope.

{% hint style="warning" %}
Do not use an envelope UUID where a mailbox UUID is required. Do not use mailbox search when you need an envelope.
{% endhint %}

### Synchronize envelope lists

Use this pattern for regular polling:

1. Set stable filters, sorting, `limit`, and `offset`.
2. Request one page of envelopes.
3. Process only envelope UUIDs that were not processed already.
4. Increase `offset` by `limit` and request the next page.
5. Stop when the page is empty or shorter than `sizeRequested`.
6. Retry temporary request failures with the same query parameters.

Avoid requesting very large pages unless the endpoint supports your required size.

### Troubleshoot list requests

{% columns %}
{% column %}
Check pagination and filters:

* The `limit` value is supported by the endpoint.
* The `offset` matches the requested page.
* Filters and sorting remain stable.
* Query values are URL-encoded.
* The requested status and scope are supported.
  {% endcolumn %}

{% column %}
Check identifiers and access:

* The token owner can access the mailbox.
* The path mailbox UUID is correct.
* The `mailboxUuid` header has the correct context.
* Template, label, sender, and envelope UUIDs use the correct environment.
* `UUID` is used only for one known envelope.
  {% endcolumn %}
  {% endcolumns %}

### Related topics

{% columns %}
{% column %}

* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids)
* [Working with envelope fields](/guides/envelope-fields)
* [Metadata](/guides/envelope-metadata)
  {% endcolumn %}

{% column %}

* [Send your first envelope](/introduction/send-your-first-envelope)
* [Check Envelope Status](/api-reference/check-envelope-status)
* [Search Mailboxes and Contacts](/api-reference/search-mailboxes-and-contacts)
  {% endcolumn %}
  {% endcolumns %}


# API versioning

This document explains how to use DocStudio API versions safely and maintain compatible integrations.

DocStudio API endpoints can include a version in the request URL. Many platform endpoints use the `/api/v1` path. The version separates API contracts and helps maintain integrations when behavior changes.

Use this guidance before changing templates, payloads, or production integration logic. This page does not define a release policy. Check the API reference and **Swagger UI** for endpoint behavior, parameters, schemas, and available operations.

### Use the current contract as the source of truth

Use [Swagger UI](https://api.docstudio.com/swagger-ui/index.html) for the current endpoint contract and documented routes.

Verify request formats, headers, response schemas, and supported values before each release. Do not infer these details from another endpoint or an older integration.

### API version in endpoint URLs

Many DocStudio API endpoints use `/api/v1` in the request path. Check the documented path before implementing each request.

```http
POST /api/v1/envelope/send
GET /api/v1/mailbox/{mailboxUuid}
POST /api/v1/template
POST /api/v1/envelope/attachment
```

The `v1` segment identifies the API version. Use the path documented in the API reference or **Swagger UI**. Do not remove or change the version unless your environment documents another version.

Not every endpoint follows the same path pattern. The authorization endpoint uses `/api/login`, not `/api/v1/login`.

```http
POST /api/login
```

Check each endpoint URL before implementation. Do not infer a URL from another endpoint or its version.

### Use documented endpoints only

Use public endpoints from the API reference or **Swagger UI**. Do not use internal routes, browser requests from **DevTools**, temporary backend endpoints, or undocumented test URLs.

Undocumented routes can change without warning or require different permissions. They can also return unstable responses or disappear after platform updates.

When you add a new API call to an integration, save these details in your integration documentation:

{% columns %}
{% column %}

* endpoint URL
* HTTP method
* required headers
* path parameters
* query parameters
  {% endcolumn %}

{% column %}

* request body format
* expected response fields
* expected status codes
* required mailbox or account context
  {% endcolumn %}
  {% endcolumns %}

This record makes future reviews faster after product or API changes. Keep it with the integration configuration and release notes.

### Request compatibility

Request compatibility means sending the format required by an endpoint. Send JSON when required. Build valid XML before passing it through the JSON `data` field.

Upload binary files in the required format. Do not wrap them in JSON unless the endpoint requires it. Small format changes can break rigid integrations.

The upload response returns `attachmentId`. Pass this value as `attachmentUuid` in envelope XML. Use the same mailbox context for file upload and the following envelope request.

Use [Uploading files and external documents](/guides/files-and-external-documents) for the upload flow and file-field rules.

Before changing request logic, check:

{% columns %}
{% column %}

* endpoint URL
* HTTP method
* required headers
* path and query parameters
  {% endcolumn %}

{% column %}

* request body format
* required XML attributes
* accepted enum values
* mailbox or account context
  {% endcolumn %}
  {% endcolumns %}

### Response compatibility

Response compatibility means safely reading the data your integration needs. Read fields required for the flow. Ignore unrelated fields unless they affect business logic.

Avoid parsing that fails only because a response contains an additional field. Test the integration after API or template changes.

Use stable identifiers and business-relevant values. Save the envelope UUID after sending an envelope. Use it for status checks, downloads, audit trails, and follow-up actions.

```json
{
  "uuid": "89499ba2-287d-404c-87b0-342dc5b01b6a"
}
```

Store `uuid` because it identifies the created envelope. Use it for later requests instead of an informational response field.

### Distinguish response fields from envelope metadata

Some responses include object fields such as creation dates, archive state, or template update timestamps. Use these fields for display, debugging, or synchronization when needed.

Do not treat these object fields as core business logic without a clear requirement. The reusable values for envelope requests are the template UUID, template version, role IDs, document IDs, and field names.

Use these template values in envelope requests:

* `uuid` for the template UUID
* `version` for the template version
* role IDs, document IDs, and field names from the template

Reuse the template identifiers and field structure for template-based envelope requests. Do not substitute response fields for required template identifiers.

Envelope metadata is different from object fields returned in an API response. Use envelope metadata for external references and automation data. Follow [Metadata](/guides/envelope-metadata) for its format, limits, and security rules.

### Distinguish API and template versions

API and template versions are different concepts. The API version is part of an endpoint path, such as `/api/v1`.

The template version identifies a template structure. Keep both versions explicit in integration configuration.

```xml
<envelope templateUuid="{templateUuid}" templateVersion="{templateVersion}">
  ...
</envelope>
```

The template version validates envelope data against the selected template. Keep role IDs, document IDs, field names, field groups, and validation rules aligned with that version.

Refresh this identifier set after each template update. Do not combine values from different template versions.

### Treat template changes as compatibility changes

Template-based integrations depend on template structure. A template update can break an envelope flow even when the endpoint stays unchanged.

A template change can affect:

{% columns %}
{% column %}

* template version
* role IDs, order, and types
* document IDs
* field names and types
* required fields
  {% endcolumn %}

{% column %}

* field validation rules
* dynamic table structure
* dictionary configuration
* signature field configuration
* external document configuration
  {% endcolumn %}
  {% endcolumns %}

Review the integration before using an updated template in production. Verify its template UUID and template version.

Verify role IDs, document IDs, field names, and field values. Keep every identifier aligned with the selected template version.

### Update templates safely

Update templates through a controlled flow. Test each change before production use.

{% stepper %}
{% step %}

#### Test the template structure

Update the template in a test environment or mailbox. Read the updated structure and compare its reusable identifiers.

Check required fields, field names, document IDs, and role IDs. Update the integration configuration where needed.
{% endstep %}

{% step %}

#### Test the envelope flow

Send a test envelope from the updated template. Check field values and recipient role assignments.

Complete the flow when required. Check statuses, downloads, audit trails, metadata, and callbacks used by the integration.
{% endstep %}
{% endstepper %}

Do not update a production template without testing it. Template changes often cause request validation errors and incorrect field mapping.

### Identify potentially compatible changes

Some changes are usually easier for integrations to handle because they do not require existing requests to change.

Examples of potentially backward-compatible changes:

* adding an optional response field or request parameter
* adding an optional filter or metadata key
* adding a new endpoint without changing existing endpoints
* updating examples without changing endpoint behavior

Test every affected flow. Compatibility depends on response parsing, schema validation, and unknown-value handling.

Do not treat a change as safe without a completed test flow. Integration behavior determines the actual compatibility impact.

### Identify potentially breaking changes

A breaking change can cause an integration to fail, send incorrect data, lose access, or process a response incorrectly. Its impact depends on the requests and automation used by the integration.

#### API contract changes

Check these changes before updating API client code:

{% columns %}
{% column %}

* removing an endpoint
* changing an endpoint URL or HTTP method
* changing required fields or headers
* changing authentication or permissions
* changing accepted enum values or response fields
  {% endcolumn %}

{% column %}

* changing request body or XML structure
* changing field value formats
* changing file upload behavior
* changing pagination behavior
  {% endcolumn %}
  {% endcolumns %}

#### Template structure changes

Check these changes before sending an envelope from an updated template:

* changing the template version without updating integration identifiers
* renaming or removing template fields
* changing document IDs, role IDs, or role order
* changing required fields, validation rules, or field groups

#### Runtime configuration changes

Check these changes before deployment:

* changing mailbox or account access
* changing callback endpoint configuration
* changing statuses used by follow-up automation
* mixing template or environment identifiers

Treat these changes carefully before production release. Update the integration and run test requests.

Verify the complete workflow from authentication through the final follow-up action. Do not rely on endpoint-level testing alone.

### Handle unknown fields and values safely

Integrations should be strict enough to detect real errors, but flexible enough to ignore data they do not use. If a response contains an unknown field, the integration should not fail unless that field conflicts with the expected processing logic.

For enum-like values such as statuses, roles, domain statuses, or verification methods, handle known values explicitly and log unknown values safely. Do not silently process an unknown status as if it were a completed or successful state.

Example approach:

* process known success states
* process known waiting, error, and cancellation states
* log unknown values and pause automatic processing

This is safer than assuming that every unfamiliar value means success. Review the logged value before enabling automatic processing.

### Keep environments separate

Do not mix identifiers between environments. Template UUIDs, template versions, mailbox UUIDs, envelope UUIDs, dictionary UUIDs, account UUIDs, and domain UUIDs can be different between staging, testing, and production.

A request can fail or affect the wrong data if an integration uses production identifiers in staging or staging identifiers in production.

Store environment-specific values separately:

{% columns %}
{% column %}

* base API URL
* API token
* account UUID
* mailbox UUIDs
* template UUIDs
  {% endcolumn %}

{% column %}

* template versions
* dictionary UUIDs
* callback URLs
* metadata keys
  {% endcolumn %}
  {% endcolumns %}

Review these values before deployment. The request format can be correct while identifiers target the wrong environment.

Environment mix-ups are therefore difficult to debug. Keep each environment configuration isolated.

Keep the mailbox context consistent within one integration flow. This is required when an uploaded attachment is referenced by a later envelope request.

Record the mailbox context with the attachment identifier. Check both values before sending the envelope.

### Use configuration for reusable identifiers

Do not scatter reusable identifiers across source code. Store stable integration values in configuration so they can be reviewed and updated without changing unrelated code.

Good candidates for configuration include:

{% columns %}
{% column %}

* base API URL
* mailbox UUIDs
* template UUIDs
* expected template version
* dictionary UUIDs
  {% endcolumn %}

{% column %}

* callback endpoint URLs
* metadata keys
* polling filters
* page size
  {% endcolumn %}
  {% endcolumns %}

Do not store API tokens in unsafe configuration files. Store tokens in secure server-side secret storage, not in source code or public configuration.

Limit access to token storage to the services that need it. Rotate a token immediately after suspected exposure.

### Confirm callback contracts separately

This guide covers compatibility rules for callback-based integrations. Callbacks are currently documented for envelope forms.

Confirm the request method, headers, payload schema, authentication, signature validation, and retry behavior in [Swagger UI](https://api.docstudio.com/swagger-ui/index.html). Follow [Envelope callbacks](/guides/envelope-callbacks) for the form lifecycle and callback processing flow.

### Test compatibility before production release

Before releasing integration changes to production, test the complete workflow that the integration uses.

Minimum test checklist:

{% columns %}
{% column %}

* Authenticate successfully.
* Use documented endpoint paths.
* Use the correct API version.
* Use the correct mailbox or account.
* Upload required attachments.
  {% endcolumn %}

{% column %}

* Send or fill the envelope.
* Check field values.
* Check recipient roles.
* Save the envelope UUID.
* Check envelope status.
  {% endcolumn %}

{% column %}

* Download the archive when required.
* Read audit trails when required.
* Check metadata and callbacks when used.
* Confirm error handling.
  {% endcolumn %}
  {% endcolumns %}

Testing one endpoint is insufficient for most integrations. Test connected template-based envelope flows together.

### Document integration assumptions

Maintain a short internal note for every integration. This is especially important for templates, metadata, callbacks, file uploads, and mailbox polling.

Document these assumptions:

{% columns %}
{% column %}

* endpoints and API version
* template and version strategy
* expected role IDs
* expected document IDs
* expected field names
  {% endcolumn %}

{% column %}

* mailbox UUIDs
* metadata keys
* statuses triggering follow-up actions
* errors stopping the flow
* expected callbacks
  {% endcolumn %}

{% column %}

* environment-specific values
* deployment configuration
* ownership of template updates
  {% endcolumn %}
  {% endcolumns %}

This note clarifies what can break after platform or template changes. It also defines the required regression tests.

### Avoid common mistakes

Common versioning and compatibility mistakes include:

{% columns %}
{% column %}

* using undocumented browser routes
* assuming identical URL structures
* removing `/api/v1` from a documented path
* changing versions without **Swagger UI**
* confusing API and template versions
  {% endcolumn %}

{% column %}

* retaining old template identifiers
* renaming fields filled by the integration
* using optional metadata as core logic
* failing on unknown optional fields
* accepting unknown statuses as successful
  {% endcolumn %}

{% column %}

* mixing staging and production identifiers
* testing authentication only
* skipping the complete envelope flow
  {% endcolumn %}
  {% endcolumns %}

### Troubleshoot compatibility issues

If an integration stops working after an API, template, or configuration change, check these points first:

{% columns %}
{% column %}

* The endpoint URL and HTTP method match the API reference.
* The API version and required headers are correct.
* The request body and XML remain valid.
* The mailbox and account belong to the correct environment.
* Uploaded files pass `attachmentId` as `attachmentUuid`.
* The integration handles changed response fields safely.
* The returned error code matches the request failure.
  {% endcolumn %}

{% column %}

* The template UUID and version are correct.
* Role and document IDs match the template version.
* Field names still exist in the selected document.
* Required fields and validation rules are satisfied.
* Unknown statuses and enum values are logged.
* The full workflow passed after the change.
  {% endcolumn %}
  {% endcolumns %}

Use [Common API Error Codes](/error-codes/error-handling-and-api-error-codes) to interpret documented error responses. Keep request and response logs without tokens or other secrets.

Record the endpoint, status code, and correlation data needed for investigation. Remove sensitive values before sharing logs.

### Related topics

{% columns %}
{% column %}

* [API overview](/)
* [Core concepts](/introduction/core-concepts)
* [Authentication and application tokens](/introduction/authentication-and-application-tokens)
  {% endcolumn %}

{% column %}

* [Working with XML payloads](/guides/xml-payloads)
* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids)
* [Uploading files and external documents](/guides/files-and-external-documents)
  {% endcolumn %}

{% column %}

* [Pagination, filtering, and sorting](/guides/list-responses)
* [Envelope callbacks](/guides/envelope-callbacks)
* [Send your first envelope](/introduction/send-your-first-envelope)
  {% endcolumn %}
  {% endcolumns %}


# Import Dictionary CSV

This document explains how to import a dictionary CSV file, including the upload step and the import confirmation request.

### Step 1 Upload the CSV file

```http
POST /api/v1/upload/dictionary/{dictionaryUuid}
Authorization: Bearer {token}
Mailbox: {mailboxUuid}
Content-Type: multipart/form-data
```

<table><thead><tr><th width="147">Parameter</th><th width="120">Location</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>dictionaryUuid</code></td><td>Path</td><td>Yes</td><td>UUID of the target dictionary</td></tr><tr><td><code>Mailbox</code></td><td>Header</td><td>Yes</td><td>Current mailbox UUID</td></tr><tr><td><code>file</code></td><td>Form data</td><td>Yes</td><td>CSV file to import</td></tr></tbody></table>

```bash
curl --request POST \
  --url "https://api.docstudio.com/api/v1/upload/dictionary/{dictionaryUuid}" \
  --header "Authorization: Bearer {token}" \
  --header "Mailbox: {mailboxUuid}" \
  --form "file=@dictionary.csv"
```

The endpoint returns `201 Created`:

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

Response fields:

| Field  | Type | Description            |
| ------ | ---- | ---------------------- |
| `uuid` | UUID | Upload task identifier |

Use `uuid` as `uploadUuid` in the confirmation and status requests.

Status codes:

| Status code   | Description                    |
| ------------- | ------------------------------ |
| `201 Created` | CSV file uploaded successfully |

### Step 2 Confirm the import

```http
PUT /api/v1/upload/{uploadUuid}/confirm
Authorization: Bearer {token}
Content-Type: application/json
```

Path parameters:

| Parameter    | Type | Required | Description            |
| ------------ | ---- | -------- | ---------------------- |
| `uploadUuid` | UUID | Yes      | Upload task identifier |

Request body:

```json
{
  "headerFirstRow": true,
  "delimiter": ",",
  "quote": "\"",
  "escape": "\\",
  "replace": false
}
```

<table><thead><tr><th width="151">Field</th><th width="102">Type</th><th width="106">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>headerFirstRow</code></td><td>boolean</td><td>Yes</td><td>Indicates whether the first row contains column names</td></tr><tr><td><code>delimiter</code></td><td>string</td><td>Yes</td><td>CSV column delimiter</td></tr><tr><td><code>quote</code></td><td>string</td><td>Yes</td><td>CSV quote character</td></tr><tr><td><code>escape</code></td><td>string</td><td>Yes</td><td>CSV escape character</td></tr><tr><td><code>replace</code></td><td>boolean</td><td>Yes</td><td>Removes existing dictionary records before import</td></tr></tbody></table>

Set `headerFirstRow` to `true` when the first CSV row contains column names. Set `replace` to `true` to remove existing records before the import.

### Step 3 Check the import status

```http
GET /api/v1/upload/{uploadUuid}
Authorization: Bearer {token}
```

Path parameters:

| Parameter    | Type | Required | Description            |
| ------------ | ---- | -------- | ---------------------- |
| `uploadUuid` | UUID | Yes      | Upload task identifier |

Response example:

```json
{
  "status": "PROCESSING",
  "createdAt": "2026-08-27T13:11:11.912Z",
  "errorMessage": null
}
```

Response fields:

| Field          | Type           | Description                |
| -------------- | -------------- | -------------------------- |
| `status`       | string         | Current import task status |
| `createdAt`    | datetime       | Task creation time         |
| `errorMessage` | string or null | Import error message       |

Check the task until `status` becomes `COMPLETED`. If it becomes `FAILED`, review `errorMessage`.

### Related topics

* [Dictionaries](/api-reference/dictionaries)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)


# Simple File Send widget

This document explains how to use and embed the Simple File Send Widget.

### Send a file

Use this [widget](https://app.docstudio.com/widgets/simple-send.html) to let anyone send a file for signing without authorization.

<figure><img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2FUGKJXav4XAoo3YMB1Hv0%2Fwidget.gif?alt=media&amp;token=0c6e5799-bbcc-4e2c-976e-c1f34cf26fc5" alt=""><figcaption></figcaption></figure>

1. Drag and drop a file into the upload zone, or click the zone to select a file manually.
2. Enter the **Recipient's email address**.
3. Click the <img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2FpCIUKmQlKrH2pgPM94G1%2Fimage.png?alt=media&amp;token=be8c6c79-973b-4b06-a54b-9a06ea6404f3" alt="" data-size="line"> button.
4. Enter **Your email address**. Use an email address not registered on the platform.
5. Click the <img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2FpCIUKmQlKrH2pgPM94G1%2Fimage.png?alt=media&amp;token=be8c6c79-973b-4b06-a54b-9a06ea6404f3" alt="" data-size="line"> button.
6. Check your mailbox for the **Email Address Confirmation** letter, copy the code, and paste it into the **Enter Email Code** field.
7. Click the <img src="https://2619072834-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcOltVL8GwCu4tL8RwTDW%2Fuploads%2FpCIUKmQlKrH2pgPM94G1%2Fimage.png?alt=media&amp;token=be8c6c79-973b-4b06-a54b-9a06ea6404f3" alt="" data-size="line"> button.

After confirmation, the platform creates the envelope and sends it to the **recipient**. Receive an email notification after the envelope is completed.

{% hint style="warning" %}
Send no more than 3 files per 5 minutes from one IP address. This limit helps prevent spam.
{% endhint %}

### Embed the widget

Add the `<wd-widget>` element where the widget must appear, then load the widget bundle before the closing `</body>` tag.

{% hint style="info" %}
The `base-api` attribute and the script URL must use the same DocStudio platform URL.
{% endhint %}

Use the following implementation:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple File Send</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            background: #f0f2f5;
        }

        .widget-container {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }

        wd-widget {
            display: block;
            min-width: 350px;
            min-height: 504px;
        }
    </style>
</head>
<body>
    <div class="widget-container">
        <wd-widget base-api="https://app.docstudio.com/"></wd-widget>
    </div>

    <script src="https://app.docstudio.com/widgets/simple-send.bundle.js"></script>
</body>
</html>
```

Replace `https://app.docstudio.com/` in both locations when the widget must use another DocStudio environment. Do not use different platform URLs for `base-api` and `simple-send.bundle.js`.

{% hint style="warning" %}
Set the widget dimensions to at least `min-height: 504px` and `min-width: 350px`.
{% endhint %}


# Send Envelope from Template

This document explains how to create, send, track, and download an envelope from a DocStudio template.

### Scenario

Send a sales agreement from a saved DocStudio template. The template already contains the document structure, recipient roles, and fields, so the API request only needs to reference the selected template version, assign real recipient mailboxes to template roles, and pass field values.

Use this example when the envelope structure is already prepared in DocStudio and the external system only starts the workflow. For example, a CRM can create an envelope from a contract template, assign the customer and manager mailboxes, prefill agreement data, and save the returned envelope UUID for tracking.

### Step 1 Prepare template values

| Method | Endpoint                |
| ------ | ----------------------- |
| `POST` | `/api/v1/envelope/send` |

Prepare all identifiers before building the request. Do not create template UUIDs, template versions, role IDs, document IDs, or field names manually; these values must come from the selected template version.

You need:

{% columns %}
{% column %}

* API token
* sender mailbox UUID
* template UUID
* template version UUID
  {% endcolumn %}

{% column %}

* role IDs from the template flow
* recipient mailbox UUIDs
* document IDs from the template
* field names from the template
  {% endcolumn %}
  {% endcolumns %}

| Template value         | Used in envelope XML                 |
| ---------------------- | ------------------------------------ |
| `template/@uuid`       | `envelope/@templateUuid`             |
| `template/@version`    | `envelope/@templateVersion`          |
| `role/@id`             | `flow > roles > role/@id`            |
| recipient mailbox UUID | `flow > roles > role/@mailboxUuid`   |
| `document/@id`         | `documents > document/@id`           |
| `field/@name`          | `documents > document > field/@name` |

#### Template fragment

This simplified template fragment shows the values that must be reused in the send request. The example has two roles and one document field; the envelope XML must use the same template UUID, template version, role IDs, document ID, and field name.

```xml
<template uuid="56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5" version="ab0d11cb-ebdd-42bd-a581-ddca1bb9b585">
  <flow>
    <roles>
      <role id="23f20eec-adad-4325-b553-1bde4be29198" />
      <role id="b811f2b6-1656-42aa-9420-a9b8addb0246" />
    </roles>
  </flow>
  <documents>
    <document id="4a61f258-fd9d-406c-b47e-81c90d4e5c47">
      <field name="date field" type="date" />
    </document>
  </documents>
</template>
```

### Step 2 Build envelope XML

Build the envelope XML by referencing the template and assigning recipient mailboxes to the template roles. Field values must be placed under the correct document ID and field name from the same template version.

```xml
<envelope templateUuid="56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5" templateVersion="ab0d11cb-ebdd-42bd-a581-ddca1bb9b585">
  <info>
    <subject>Sales agreement</subject>
    <message>Please review and complete the agreement.</message>
  </info>
  <flow>
    <roles>
      <role id="23f20eec-adad-4325-b553-1bde4be29198" mailboxUuid="9baec31c-e940-4894-b6d1-52033e1af66e" />
      <role id="b811f2b6-1656-42aa-9420-a9b8addb0246" mailboxUuid="42c95245-30c1-46ef-bd5b-a9a111deec10" />
    </roles>
  </flow>
  <documents>
    <document id="4a61f258-fd9d-406c-b47e-81c90d4e5c47">
      <field name="date field">2026-07-21</field>
    </document>
  </documents>
</envelope>
```

### Step 3 Send the request

#### Headers

| Header          | Required | Description                                     |
| --------------- | -------- | ----------------------------------------------- |
| `Authorization` | Yes      | Bearer authorization token                      |
| `Content-Type`  | Yes      | Use `application/json`                          |
| `Mailbox`       | Yes      | Sender mailbox UUID used as the mailbox context |

#### Request body

Send envelope XML as a string in `data`. Add [metadata](/guides/envelope-metadata) when the envelope needs external identifiers or other integration references.

```
{  "data": "<envelope templateUuid=\"56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5\" templateVersion=\"ab0d11cb-ebdd-42bd-a581-ddca1bb9b585\"><info><subject>Sales agreement</subject><message>Please review and complete the agreement.</message></info><flow><roles><role id=\"23f20eec-adad-4325-b553-1bde4be29198\" mailboxUuid=\"9baec31c-e940-4894-b6d1-52033e1af66e\"/><role id=\"b811f2b6-1656-42aa-9420-a9b8addb0246\" mailboxUuid=\"42c95245-30c1-46ef-bd5b-a9a111deec10\"/></roles></flow><documents><document id=\"4a61f258-fd9d-406c-b47e-81c90d4e5c47\"><field name=\"date field\">2026-07-21</field></document></documents></envelope>"}
```

| Field      | Type   | Required | Description                                                      |
| ---------- | ------ | -------- | ---------------------------------------------------------------- |
| `uuid`     | UUID   | No       | Envelope UUID, when the flow already has an envelope identifier. |
| `data`     | string | Yes      | Envelope XML string.                                             |
| `metadata` | object | No       | Custom key-value metadata added to the envelope.                 |

### Request example

```http
POST /api/v1/envelope/send
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {senderMailboxUuid}
```

```json
{
  "data": "{envelopeXml}"
}
```

### Step 4 Save the envelope UUID

The endpoint returns `201 Created` with the created envelope UUID. Save this UUID in the external system, because it is required for follow-up operations such as retrieving the envelope, checking its status, downloading documents, or matching callback events.

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

| Field  | Type | Description            |
| ------ | ---- | ---------------------- |
| `uuid` | UUID | Created envelope UUID. |

### Step 5 Continue processing

After the request is processed, DocStudio creates the envelope from the selected template and sends it according to the template flow. The recipient mailboxes assigned in the XML become participants in the envelope, and the provided field values are saved to the matching fields.

Use the returned UUID to check envelope status and download the envelope archive.

### Common mistakes

{% hint style="warning" %}
Use identifiers from the same template version. Set the sender mailbox in `Mailbox`, assign each template role to the correct recipient mailbox, and pass valid XML as a JSON string in `data`.
{% endhint %}


# Send Envelope with Prefilled Fields

This document explains how to send a template envelope with prefilled fields.

### Scenario

Send an envelope from a template and prefill several fields before recipients open it. Use this example when an external system already has business data, such as customer name, contract number, amount, start date, or selected payment method, and this data must be inserted into the envelope automatically.

The template must already contain the fields that you want to prefill. The API request does not create new fields or change field configuration; it only sends values for fields that already exist in the selected template version.

### Step 1 Prepare template values

| Method | Endpoint                |
| ------ | ----------------------- |
| `POST` | `/api/v1/envelope/send` |

Prepare all identifiers before building the request. Use values from the selected template version.

You need:

{% columns %}
{% column %}

* API token
* sender mailbox UUID
* template UUID
* template version UUID
* role IDs from the template flow
  {% endcolumn %}

{% column %}

* recipient mailbox UUIDs
* document IDs from the template
* exact field names from the selected document
* values that match field validation rules
  {% endcolumn %}
  {% endcolumns %}

#### Prefilled fields

<table><thead><tr><th width="164">Field name</th><th width="200">Example value</th><th>Value requirements</th></tr></thead><tbody><tr><td><code>customer_name</code></td><td><code>ACME Ltd</code></td><td>text value</td></tr><tr><td><code>contract_number</code></td><td><code>SA-2026-001</code></td><td>value defined by the template configuration</td></tr><tr><td><code>quantity</code></td><td><code>10</code></td><td>numeric value</td></tr><tr><td><code>total_amount</code></td><td><code>1250.50</code></td><td>numeric or currency value</td></tr><tr><td><code>start_date</code></td><td><code>2026-07-15T10:00:00Z</code></td><td>date or date-time format accepted by the field</td></tr><tr><td><code>payment_method</code></td><td><code>Bank transfer</code></td><td>value matching the configured option</td></tr></tbody></table>

### Step 2 Build envelope XML

Add field values inside the `documents` block. Each value must be placed inside a `field` element with the same `name` used in the template field configuration.

```xml
<envelope templateUuid="56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5" templateVersion="ab0d11cb-ebdd-42bd-a581-ddca1bb9b585">
  <info>
    <subject>Sales agreement for ACME Ltd</subject>
    <message>Please review and complete the agreement.</message>
  </info>
  <flow>
    <roles>
      <role id="23f20eec-adad-4325-b553-1bde4be29198" mailboxUuid="9baec31c-e940-4894-b6d1-52033e1af66e" />
      <role id="b811f2b6-1656-42aa-9420-a9b8addb0246" mailboxUuid="42c95245-30c1-46ef-bd5b-a9a111deec10" />
    </roles>
  </flow>
  <documents>
    <document id="4a61f258-fd9d-406c-b47e-81c90d4e5c47">
      <field name="customer_name">ACME Ltd</field>
      <field name="contract_number">SA-2026-001</field>
      <field name="quantity">10</field>
      <field name="total_amount">1250.50</field>
      <field name="start_date">2026-07-15T10:00:00Z</field>
      <field name="payment_method">Bank transfer</field>
    </document>
  </documents>
</envelope>
```

Use the document ID and field names from the selected template version. Place each value under the document where that field is configured.

### Step 3 Send the request

#### Headers

<table><thead><tr><th width="142">Header</th><th width="172">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td>Use <code>application/json</code></td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>Sender mailbox UUID used as the mailbox context</td></tr></tbody></table>

#### Request body

Send the envelope XML as a string in the JSON `data` field. Escape XML quotes and line breaks so the value remains valid JSON.

```json
{
  "data": "<envelope templateUuid=\"56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5\" templateVersion=\"ab0d11cb-ebdd-42bd-a581-ddca1bb9b585\"><info><subject>Sales agreement for ACME Ltd</subject><message>Please review and complete the agreement.</message></info><flow><roles><role id=\"23f20eec-adad-4325-b553-1bde4be29198\" mailboxUuid=\"9baec31c-e940-4894-b6d1-52033e1af66e\"/><role id=\"b811f2b6-1656-42aa-9420-a9b8addb0246\" mailboxUuid=\"42c95245-30c1-46ef-bd5b-a9a111deec10\"/></roles></flow><documents><document id=\"4a61f258-fd9d-406c-b47e-81c90d4e5c47\"><field name=\"customer_name\">ACME Ltd</field><field name=\"contract_number\">SA-2026-001</field><field name=\"quantity\">10</field><field name=\"total_amount\">1250.50</field><field name=\"start_date\">2026-07-15T10:00:00Z</field><field name=\"payment_method\">Bank transfer</field></document></documents></envelope>"
}
```

<table><thead><tr><th width="99">Field</th><th width="80">Type</th><th width="123">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>uuid</code></td><td>UUID</td><td>No</td><td>Envelope UUID when the flow already has an identifier</td></tr><tr><td><code>data</code></td><td>string</td><td>Yes</td><td>Envelope XML string with prefilled field values</td></tr><tr><td><code>metadata</code></td><td>object</td><td>No</td><td>Custom key-value metadata added to the envelope</td></tr></tbody></table>

### Request example

```http
POST /api/v1/envelope/send
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {senderMailboxUuid}

{
  "data": "<envelope templateUuid=\"56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5\" templateVersion=\"ab0d11cb-ebdd-42bd-a581-ddca1bb9b585\"><info><subject>Sales agreement for ACME Ltd</subject><message>Please review and complete the agreement.</message></info><flow><roles><role id=\"23f20eec-adad-4325-b553-1bde4be29198\" mailboxUuid=\"9baec31c-e940-4894-b6d1-52033e1af66e\"/><role id=\"b811f2b6-1656-42aa-9420-a9b8addb0246\" mailboxUuid=\"42c95245-30c1-46ef-bd5b-a9a111deec10\"/></roles></flow><documents><document id=\"4a61f258-fd9d-406c-b47e-81c90d4e5c47\"><field name=\"customer_name\">ACME Ltd</field><field name=\"contract_number\">SA-2026-001</field><field name=\"quantity\">10</field><field name=\"total_amount\">1250.50</field><field name=\"start_date\">2026-07-15T10:00:00Z</field><field name=\"payment_method\">Bank transfer</field></document></documents></envelope>"
}
```

### Step 4 Save the envelope UUID

The endpoint returns `201 Created` with the created envelope UUID. Save this UUID for follow-up operations.

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

| Field  | Type | Description           |
| ------ | ---- | --------------------- |
| `uuid` | UUID | Created envelope UUID |

### Step 5 Continue processing

Use the returned UUID to check envelope status and download the envelope archive.

### Common mistakes

{% hint style="warning" %}
Use identifiers from the same template version. Set the sender mailbox in `Mailbox`, assign each template role to the correct recipient mailbox, and pass valid field values in the XML `data` string.
{% endhint %}


# Send Envelope with Metadata

This document explains how to store and use envelope metadata through the API.

### Scenario

Send an envelope from a template and attach metadata for an external process.

### Step 1 Prepare template and metadata values

| Method | Endpoint                |
| ------ | ----------------------- |
| `POST` | `/api/v1/envelope/send` |

Prepare the template values and metadata before building the request.

You need:

{% columns %}
{% column %}

* API token
* sender mailbox UUID
* template UUID
* template version UUID
* role IDs from the template flow
  {% endcolumn %}

{% column %}

* recipient mailbox UUIDs
* document IDs from the template
* field names from the template
* metadata keys and values
  {% endcolumn %}
  {% endcolumns %}

#### Metadata rules

| Rule                  | Value                       |
| --------------------- | --------------------------- |
| Key length            | 1–32 characters             |
| Value length          | 0–128 characters            |
| Supported value types | `string`, `boolean`, `null` |

```json
{
  "customerId": "C-1024",
  "crmRecordId": "CRM-77551",
  "source": "crm",
  "priority": true,
  "externalReference": null
}
```

### Step 2 Build envelope XML

Build the envelope XML with template, role, document, and field values.

```xml
<envelope
  templateUuid="56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5"
  templateVersion="ab0d11cb-ebdd-42bd-a581-ddca1bb9b585"
>
  <info>
    <subject>Sales agreement for ACME Ltd</subject>
    <message>Please review and complete the agreement.</message>
  </info>
  <flow>
    <roles>
      <role
        id="23f20eec-adad-4325-b553-1bde4be29198"
        mailboxUuid="9baec31c-e940-4894-b6d1-52033e1af66e"
      />
    </roles>
  </flow>
  <documents>
    <document id="4a61f258-fd9d-406c-b47e-81c90d4e5c47">
      <field name="customer_name">ACME Ltd</field>
      <field name="contract_amount">1250.50</field>
    </document>
  </documents>
</envelope>
```

Pass metadata in the `metadata` JSON object. Do not add it to the XML.

### Step 3 Send the request

Use these headers:

| Header          | Required | Description                |
| --------------- | -------- | -------------------------- |
| `Authorization` | Yes      | Bearer authorization token |
| `Content-Type`  | Yes      | Use `application/json`     |
| `Mailbox`       | Yes      | Sender mailbox UUID        |

Send the envelope XML in `data` and metadata in `metadata`.

```json
{
  "data": "<envelope templateUuid=\"56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5\" templateVersion=\"ab0d11cb-ebdd-42bd-a581-ddca1bb9b585\">\n  <info>\n    <subject>Sales agreement for ACME Ltd</subject>\n    <message>Please review and complete the agreement.</message>\n  </info>\n  <flow>\n    <roles>\n      <role id=\"23f20eec-adad-4325-b553-1bde4be29198\" mailboxUuid=\"9baec31c-e940-4894-b6d1-52033e1af66e\" />\n    </roles>\n  </flow>\n  <documents>\n    <document id=\"4a61f258-fd9d-406c-b47e-81c90d4e5c47\">\n      <field name=\"customer_name\">ACME Ltd</field>\n      <field name=\"contract_amount\">1250.50</field>\n    </document>\n  </documents>\n</envelope>",
  "metadata": {
    "customerId": "C-1024",
    "crmRecordId": "CRM-77551",
    "source": "crm",
    "priority": true
  }
}
```

<table><thead><tr><th width="98">Field</th><th width="82">Type</th><th width="110">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>uuid</code></td><td>UUID</td><td>No</td><td>Envelope UUID when the flow already has an envelope identifier</td></tr><tr><td><code>data</code></td><td>string</td><td>Yes</td><td>Envelope XML string</td></tr><tr><td><code>metadata</code></td><td>object</td><td>No</td><td>Custom key-value metadata</td></tr></tbody></table>

### Request example

```http
POST /api/v1/envelope/send
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {senderMailboxUuid}

{
  "data": "<envelope templateUuid=\"56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5\" templateVersion=\"ab0d11cb-ebdd-42bd-a581-ddca1bb9b585\">\n  <info>\n    <subject>Sales agreement for ACME Ltd</subject>\n    <message>Please review and complete the agreement.</message>\n  </info>\n  <flow>\n    <roles>\n      <role id=\"23f20eec-adad-4325-b553-1bde4be29198\" mailboxUuid=\"9baec31c-e940-4894-b6d1-52033e1af66e\" />\n    </roles>\n  </flow>\n  <documents>\n    <document id=\"4a61f258-fd9d-406c-b47e-81c90d4e5c47\">\n      <field name=\"customer_name\">ACME Ltd</field>\n      <field name=\"contract_amount\">1250.50</field>\n    </document>\n  </documents>\n</envelope>",
  "metadata": {
    "customerId": "C-1024",
    "crmRecordId": "CRM-77551",
    "source": "crm",
    "priority": true
  }
}
```

### Step 4 Save the envelope UUID

The endpoint returns `201 Created`. Save the envelope UUID.

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

| Field  | Type | Description           |
| ------ | ---- | --------------------- |
| `uuid` | UUID | Created envelope UUID |

### Step 5 Manage metadata

#### Update metadata

Use this endpoint to add or change metadata.

| Method | Endpoint                         |
| ------ | -------------------------------- |
| `PUT`  | `/api/v1/envelope/{id}/metadata` |

Use these headers:

| Header          | Required | Description                |
| --------------- | -------- | -------------------------- |
| `Authorization` | Yes      | Bearer authorization token |
| `Content-Type`  | Yes      | Use `application/json`     |
| `Mailbox`       | Yes      | Current mailbox UUID       |

Path parameters:

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id`      | UUID | Yes      | Envelope ID |

```json
{
  "crmRecordId": "CRM-77551",
  "processingStatus": "synced",
  "priority": true
}
```

The request adds new keys and overwrites existing values. The endpoint returns `200 OK`.

#### Read metadata

Read `envelope.metadata`.

```json
{
  "envelope": {
    "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "WAITING",
    "metadata": {
      "customerId": "C-1024",
      "crmRecordId": "CRM-77551",
      "source": "crm",
      "priority": true
    }
  }
}
```

#### Display metadata

Add this element to the template info section:

```xml
<metadata show="true" />
```

{% hint style="info" %}
Display metadata only when the template includes this element and metadata has a value.
{% endhint %}

### Continue processing

Use the envelope UUID to check the envelope status, process callbacks, or download the completed archive.

{% hint style="warning" %}
Keep document values in fields and external references in metadata.

* Include the `Authorization` header
* Use the sender mailbox UUID in `Mailbox`
* Confirm token access to the sender mailbox
* Send valid envelope XML in `data`
* Send a valid JSON object in `metadata`
* Use keys that are 1–32 characters long
* Use values that are 0–128 characters long
* Use supported metadata value types
* Do not include secrets or large data blocks
* Add `<metadata show="true" />` to display metadata
  {% endhint %}


# Authorization

This document contains details for the /api/login endpoint, including the request body, response token, and status codes.

### Endpoint

| Property | Value        |
| -------- | ------------ |
| Method   | `POST`       |
| URL      | `/api/login` |

### Headers

<table><thead><tr><th width="164.333251953125">Header</th><th width="106.3333740234375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Content-Type</code></td><td>Yes</td><td><code>application/json</code></td></tr><tr><td><code>Client-Device-Id</code></td><td>No</td><td>Client device identifier. When provided, the response includes <code>deviceId</code>.</td></tr></tbody></table>

```http
Content-Type: application/json
```

### Request body

| Field      | Type   | Required | Description         |
| ---------- | ------ | -------- | ------------------- |
| `login`    | string | Yes      | User login or email |
| `password` | string | Yes      | User password       |

### Request example

```http
POST /api/login
Content-Type: application/json
```

```json
{
  "login": "user@example.com",
  "password": "password"
}
```

### Response

{% hint style="info" %}
The response always contains a temporary authorization token. The `deviceId` field is returned only when the request includes the client device ID header; otherwise, this field is omitted.
{% endhint %}

<table><thead><tr><th width="104">Field</th><th width="95">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>token</code></td><td>string</td><td>Temporary authorization token. Expires after 3 hours</td></tr><tr><td><code>deviceId</code></td><td>string</td><td>Device ID returned only when the request includes the client device identifier header</td></tr></tbody></table>

#### Response examples

When the request does not include the `Client-Device-Id` header, the response contains only the temporary authorization token. When the header is provided, the response also contains the generated `deviceId`.

**Response without `Client-Device-Id`**

```json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

**Response with `Client-Device-Id`**

```json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "deviceId": "{deviceId}"
```

### Status codes

<table><thead><tr><th width="85.4444580078125">Code</th><th>Description</th></tr></thead><tbody><tr><td><code>200</code></td><td>Success. The response contains a temporary authorization token and, when requested, a device ID</td></tr><tr><td><code>401</code></td><td>Invalid login or password</td></tr><tr><td><code>403</code></td><td>Authenticated user lacks required access</td></tr></tbody></table>

### Related topics

* [Authentication and application tokens](/introduction/authentication-and-application-tokens)
* [API token security](/introduction/api-token-security)
* [Error Codes](/error-codes/error-handling-and-api-error-codes)


# Send Envelope

This document contains details for the /api/v1/envelope/send endpoint, including headers, request parameters, response fields, and status codes.

### Endpoint

| Method | Endpoint                |
| ------ | ----------------------- |
| `POST` | `/api/v1/envelope/send` |

### Headers

| Header          | Required | Description                |
| --------------- | -------- | -------------------------- |
| `Authorization` | Yes      | Bearer authorization token |
| `Content-Type`  | Yes      | `application/json`         |
| `Mailbox`       | Yes      | UUID of the sender mailbox |

Use a token with access to the sender mailbox.

### Request

| Field      | Type   | Required | Description                              |
| ---------- | ------ | -------- | ---------------------------------------- |
| `uuid`     | UUID   | No       | Predefined envelope UUID                 |
| `data`     | string | Yes      | Envelope XML serialized as a JSON string |
| `metadata` | object | No       | Custom envelope metadata                 |

### Envelope XML

Use identifiers from the same template version.

| Envelope value              | Source                                              |
| --------------------------- | --------------------------------------------------- |
| `envelope/@templateUuid`    | Template UUID                                       |
| `envelope/@templateVersion` | Template version UUID                               |
| `role/@id`                  | Role ID from the template flow                      |
| `role/@mailboxUuid`         | Recipient mailbox UUID                              |
| `document/@id`              | Document ID from the selected template version      |
| `field/@name`               | Exact field name from the selected template version |

Example envelope XML:

```xml
<envelope
  templateUuid="{templateUuid}"
  templateVersion="{templateVersion}"
>
  <info>
    <subject>Sales agreement</subject>
    <message>Please review and complete the agreement.</message>
  </info>

  <flow>
    <roles>
      <role
        id="{roleId}"
        mailboxUuid="{recipientMailboxUuid}"
      />
    </roles>
  </flow>

  <documents>
    <document id="{documentId}">
      <field name="Customer name">ACME Ltd</field>
      <field name="Contract amount">1250.50</field>
    </document>
  </documents>
</envelope>
```

### Request example

```http
POST /api/v1/envelope/send
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {senderMailboxUuid}
```

```json
{
  "data": "{envelopeXml}"
}
```

### Optional request fields

#### `uuid`

Set `uuid` when the integration assigns the envelope UUID.

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "data": "{envelopeXml}"
}
```

#### `metadata`

Set `metadata` to store custom envelope data.

```json
{
  "data": "{envelopeXml}",
  "metadata": {
    "customerId": "C-1024",
    "crmRecordId": "CRM-77551",
    "priority": true
  }
}
```

### Response

The endpoint returns `201 Created` with the created envelope UUID.

```json
{
  "uuid": "89499ba2-287d-404c-87b0-342dc5b01b6a"
}
```

| Field  | Type | Description                  |
| ------ | ---- | ---------------------------- |
| `uuid` | UUID | UUID of the created envelope |

### Status codes

| Code  | Description                                                               |
| ----- | ------------------------------------------------------------------------- |
| `201` | Envelope created and sent successfully                                    |
| `400` | Invalid request headers, JSON body, envelope XML, or reusable identifiers |
| `401` | Missing, invalid, or expired authorization token                          |
| `403` | No permission to send envelopes from the specified mailbox                |

### Related topics

{% columns %}
{% column %}

* [Send your first envelope](/introduction/send-your-first-envelope)
* [XML payloads](/guides/xml-payloads)
* [Templates and reusable IDs](/guides/templates-and-reusable-ids)
* [Envelope fields](/guides/envelope-fields)
* [Envelope metadata](/guides/envelope-metadata)
  {% endcolumn %}

{% column %}

* [Upload Attachments](/api-reference/upload-attachments)
* [Fill Envelope](/api-reference/fill-envelope)
* [Check Envelope Status](/api-reference/check-envelope-status)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)
  {% endcolumn %}
  {% endcolumns %}


# Check Envelope Status

This document contains details for the /api/v1/envelope/{envelopeUuid} endpoint, including headers, parameters, response fields, and status codes.

Use this endpoint when you already know the envelope UUID and need to retrieve its latest status and details. If you need to find envelopes or filter a list by status and other criteria, use `POST /api/v1/envelope/search` instead. The current status of the retrieved envelope is returned in `envelope.status`.

### Endpoint

| Method | Endpoint                          |
| ------ | --------------------------------- |
| `GET`  | `/api/v1/envelope/{envelopeUuid}` |

### Headers

| Header          | Required | Description                                             |
| --------------- | -------- | ------------------------------------------------------- |
| `Authorization` | Yes      | Bearer authorization token                              |
| `Mailbox`       | Yes      | UUID of the mailbox used as the current mailbox context |

### Path parameters

| Parameter      | Type | Required | Description                      |
| -------------- | ---- | -------- | -------------------------------- |
| `envelopeUuid` | UUID | Yes      | UUID of the envelope to retrieve |

### Request example

```http
GET /api/v1/envelope/89499ba2-287d-404c-87b0-342dc5b01b6a
Authorization: Bearer {token}
Mailbox: 9baec31c-e940-4894-b6d1-52033e1af66e
```

### Response

The endpoint returns `200 OK` with envelope, template, and scenario details.

```json
{
  "envelope": {
    "uuid": "89499ba2-287d-404c-87b0-342dc5b01b6a",
    "createdAt": "2026-08-27T13:02:46.796Z",
    "receivedAt": "2026-08-27T13:02:46.796Z",
    "sentAt": "2026-08-27T13:02:46.796Z",
    "status": "COMPLETED",
    "sender": {
      "mailboxUuid": "fdfde267-6558-40a9-93fd-e59529baef36",
      "mailboxName": "Sender mailbox",
      "accountUuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "accountName": "Sender account"
    },
    "deleted": false,
    "archived": false,
    "metadata": {
      "customerId": "ACME-1001"
    }
  },
  "template": {
    "uuid": "56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5",
    "name": "Sales agreement",
    "version": "143a2a4b-325e-4c05-a4c1-52f44e21b745"
  },
  "scenario": null
}
```

#### Response fields

| Field      | Type             | Description                     |
| ---------- | ---------------- | ------------------------------- |
| `envelope` | object           | Envelope details                |
| `template` | object           | Template details                |
| `scenario` | object or `null` | Scenario details when available |

#### Envelope fields

| Field        | Type     | Description                        |
| ------------ | -------- | ---------------------------------- |
| `uuid`       | UUID     | Envelope UUID                      |
| `createdAt`  | datetime | Envelope creation time             |
| `receivedAt` | datetime | Envelope receipt time              |
| `sentAt`     | datetime | Envelope send time                 |
| `status`     | string   | Current envelope status            |
| `sender`     | object   | Sender mailbox and account details |
| `deleted`    | boolean  | Whether the envelope is deleted    |
| `archived`   | boolean  | Whether the envelope is archived   |
| `metadata`   | object   | Custom envelope metadata           |

#### Sender fields

| Field         | Type   | Description         |
| ------------- | ------ | ------------------- |
| `mailboxUuid` | UUID   | Sender mailbox UUID |
| `mailboxName` | string | Sender mailbox name |
| `accountUuid` | UUID   | Sender account UUID |
| `accountName` | string | Sender account name |

#### Template fields

| Field     | Type   | Description           |
| --------- | ------ | --------------------- |
| `uuid`    | UUID   | Template UUID         |
| `name`    | string | Template name         |
| `version` | UUID   | Template version UUID |

### Status codes

| Code  | Description                                      |
| ----- | ------------------------------------------------ |
| `200` | Envelope retrieved successfully                  |
| `401` | Missing, invalid, or expired authorization token |
| `403` | No access to the specified mailbox               |
| `404` | Envelope or mailbox not found                    |

### Related topics

* [Authorization](/api-reference/authorization)
* [Send Envelope](/api-reference/send-envelope)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)


# Download Envelope Archive

This document explains how to download a completed envelope archive through DocStudio API.

#### Endpoint

| Method | Endpoint                    |
| ------ | --------------------------- |
| `GET`  | `/api/v1/envelope/{id}/zip` |

#### Headers

<table><thead><tr><th width="155">Header</th><th width="129">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>UUID of the mailbox used as the current mailbox context</td></tr></tbody></table>

#### Path parameters

<table><thead><tr><th width="136">Parameter</th><th width="96">Type</th><th width="106">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>UUID</td><td>Yes</td><td>UUID of the envelope to download</td></tr></tbody></table>

#### Query parameters

<table><thead><tr><th width="166">Parameter</th><th width="88">Type</th><th width="106">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>documentId</code></td><td>string</td><td>No</td><td>ID of one document to include in the archive</td></tr><tr><td><code>excludeFiles</code></td><td>string</td><td>No</td><td>Mask defining which generated files must be excluded</td></tr><tr><td><code>zipStructureName</code></td><td>string</td><td>No</td><td>Name of a ZIP structure previously saved in the envelope template</td></tr><tr><td><code>wait</code></td><td>boolean</td><td>No</td><td>Wait for the archive to become available instead of returning <code>425</code></td></tr></tbody></table>

#### Download the complete envelope archive

```http
GET /api/v1/envelope/89499ba2-287d-404c-87b0-342dc5b01b6a/zip?wait=true
Authorization: Bearer {token}
Mailbox: 9baec31c-e940-4894-b6d1-52033e1af66e
```

#### Download one document

Pass the document ID through the `documentId` query parameter when only one envelope document is required. The document ID must come from the envelope or template structure.

```http
GET /api/v1/envelope/89499ba2-287d-404c-87b0-342dc5b01b6a/zip?documentId={documentId}&wait=true
Authorization: Bearer {token}
Mailbox: 9baec31c-e940-4894-b6d1-52033e1af66e
```

#### Exclude generated files

Use `excludeFiles` to remove generated files that are not required in the downloaded archive. Combine several values in one mask when multiple file types must be excluded.

| Value | Excluded files                       |
| ----- | ------------------------------------ |
| `c`   | Signature or processing certificates |
| `p`   | Printable versions                   |
| `a`   | Audit trail                          |

For example, `excludeFiles=cp` excludes certificates and printable versions:

```http
GET /api/v1/envelope/89499ba2-287d-404c-87b0-342dc5b01b6a/zip?excludeFiles=cp&wait=true
Authorization: Bearer {token}
Mailbox: 9baec31c-e940-4894-b6d1-52033e1af66e
```

#### Response

A successful request returns `200 OK` with the archive as binary content using the `application/octet-stream` media type. Save the response body as a `.zip` file instead of attempting to process it as JSON.

If `wait` is set to `true`, the request waits for the archive to become available. Without this option, the API can return `425` when the requested archive has not been generated yet.

#### Status codes

<table><thead><tr><th width="293">Code</th><th>Description</th></tr></thead><tbody><tr><td><code>200</code></td><td>Archive returned successfully</td></tr><tr><td><code>425</code></td><td>Archive is not ready and the request did not wait for it</td></tr></tbody></table>

#### Related topics

* [Check Envelope Status](/api-reference/check-envelope-status)
* [Send Envelope](/api-reference/send-envelope)
* [Upload Attachments](/api-reference/upload-attachments)


# Upload Attachments

This document contains details for the /api/v1/envelope/attachment endpoint, including headers, request body, response fields, and status codes.

### Endpoint

| Method | Endpoint                      |
| ------ | ----------------------------- |
| `POST` | `/api/v1/envelope/attachment` |

### Headers

<table><thead><tr><th width="192">Header</th><th width="211">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td><code>multipart/form-data</code></td></tr><tr><td><code>Mailbox</code></td><td>No</td><td>UUID of the current mailbox context</td></tr></tbody></table>

### Query parameters

<table><thead><tr><th width="115">Parameter</th><th width="86">Type</th><th width="106">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>type</code></td><td>string</td><td>No</td><td>File category: <code>all</code>, <code>document</code>, <code>file</code>, <code>image</code>, or <code>archive</code></td></tr></tbody></table>

### Request

Send the file as `multipart/form-data` in the required `file` field.

<table><thead><tr><th width="91">Field</th><th width="101">Type</th><th width="220">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>file</code></td><td>binary</td><td>Yes</td><td>File to upload</td></tr></tbody></table>

### Request example

```bash
curl --request POST \
  "https://{baseUrl}/api/v1/envelope/attachment?type=document" \
  --header "Authorization: Bearer {token}" \
  --header "Mailbox: {mailboxUuid}" \
  --form "file=@contract.pdf"
```

Let the HTTP client generate the multipart boundary automatically.

### Response

The endpoint returns `201 Created` with the uploaded attachment details.

```json
{
  "filename": "contract.pdf",
  "attachmentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "filesize": 204800,
  "contentType": "application/pdf",
  "updatedPdf": "string"
}
```

<table><thead><tr><th width="153">Field</th><th width="187">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>filename</code></td><td>string</td><td>Name of the uploaded file</td></tr><tr><td><code>attachmentId</code></td><td>UUID</td><td>Identifier of the uploaded attachment</td></tr><tr><td><code>filesize</code></td><td>integer</td><td>Uploaded file size in bytes</td></tr><tr><td><code>contentType</code></td><td>string</td><td>MIME type of the uploaded file</td></tr><tr><td><code>updatedPdf</code></td><td>byte string</td><td>Updated PDF data when included in the response</td></tr></tbody></table>

### Attachment references

Set `attachmentUuid` to the returned `attachmentId`.

#### External document

Use the attachment as an external envelope document:

```xml
<document
  id="{documentId}"
  attachmentUuid="{attachmentId}"
/>
```

#### File field

Use the attachment as a file field value:

```xml
<document id="{documentId}">
  <field
    name="File"
    attachmentUuid="{attachmentId}"
  >contract.pdf</field>
</document>
```

### Status codes

<table><thead><tr><th width="324">Code</th><th>Description</th></tr></thead><tbody><tr><td><code>201</code></td><td>Attachment uploaded successfully</td></tr><tr><td><code>400</code></td><td>Invalid request body, query parameter, or headers</td></tr><tr><td><code>401</code></td><td>Missing, invalid, or expired authorization token</td></tr><tr><td><code>403</code></td><td>No access to the specified mailbox</td></tr><tr><td><code>413</code></td><td>Uploaded file exceeds the allowed size</td></tr></tbody></table>

### Related topics

* [XML payloads](/guides/xml-payloads)
* [Templates and reusable IDs](/guides/templates-and-reusable-ids)
* [Envelope fields](/guides/envelope-fields)
* [Send your first envelope](/introduction/send-your-first-envelope)
* [Send Envelope](/api-reference/send-envelope)
* [Fill Envelope](/api-reference/fill-envelope)


# Fill Envelope

This document contains details for the /api/v1/envelope/fill endpoint, including headers, request body, response, and status codes.

### Endpoint

| Method | Endpoint                |
| ------ | ----------------------- |
| `PUT`  | `/api/v1/envelope/fill` |

### Headers

<table><thead><tr><th width="165">Header</th><th width="253">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>Yes</td><td>Bearer authorization token</td></tr><tr><td><code>Content-Type</code></td><td>Yes</td><td><code>application/json</code></td></tr><tr><td><code>Mailbox</code></td><td>Yes</td><td>UUID of the mailbox filling the envelope</td></tr></tbody></table>

### Request body

<table><thead><tr><th width="81">Field</th><th width="82">Type</th><th width="198">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>uuid</code></td><td>UUID</td><td>Yes</td><td>UUID of the envelope to fill</td></tr><tr><td><code>data</code></td><td>string</td><td>Yes</td><td>Envelope XML containing the field values</td></tr></tbody></table>

### Request example

```http
PUT /api/v1/envelope/fill
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: 42c95245-30c1-46ef-bd5b-a9a111deec10
```

```json
{
  "uuid": "89499ba2-287d-404c-87b0-342dc5b01b6a",
  "data": "{envelopeXml}"
}
```

Envelope XML:

```xml
<envelope
  templateUuid="500afafd-711e-471a-a18f-24a89cd4ede3"
  templateVersion="143a2a4b-325e-4c05-a4c1-52f44e21b745"
>
  <documents>
    <document id="ef247568-559a-4ec1-9ecc-6b44c9fb8215">
      <field name="Customer name">ACME Ltd</field>
      <field name="Contract amount">1000.00</field>
    </document>
  </documents>
</envelope>
```

{% hint style="warning" %}
Use document IDs and field names from the envelope template version.
{% endhint %}

### Response

The endpoint returns `200 OK` after updating the field values.

### Status codes

| Code  | Description                 |
| ----- | --------------------------- |
| `200` | Fields updated successfully |

### Related topics

* [Working with XML payloads](/guides/xml-payloads)
* [Envelope fields](/guides/envelope-fields)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)


# Create Template

This document contains details for the /api/v1/template endpoint, including headers, request body, response fields, and status codes.

### Endpoint

| Property | Value              |
| -------- | ------------------ |
| Method   | `POST`             |
| URL      | `/api/v1/template` |

### Headers

| Header          | Required | Description                |
| --------------- | -------- | -------------------------- |
| `Authorization` | Yes      | Bearer authorization token |
| `Content-Type`  | Yes      | `application/json`         |
| `mailboxUuid`   | Yes      | Target mailbox UUID        |

```http
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {mailboxUuid}
```

### Request body

<table><thead><tr><th width="126.6666259765625">Field</th><th width="117.5555419921875">Type</th><th width="110.3333740234375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>access</code></td><td>string</td><td>Yes</td><td>Template access level, such as <code>mailbox</code></td></tr><tr><td><code>categories</code></td><td>array</td><td>Yes</td><td>Category IDs, or an empty array</td></tr><tr><td><code>data</code></td><td>string</td><td>Yes</td><td>Template XML serialized as a JSON string</td></tr></tbody></table>

### Request example

```http
POST /api/v1/template
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: 9baec31c-e940-4894-b6d1-52033e1af66e
```

```json
{
  "access": "mailbox",
  "categories": [],
  "data": "<template><info><name>Sales agreement</name><description>Template for sales agreement envelopes</description><subject>Sales agreement</subject><message>Please review and complete the agreement.</message></info><flow><roles><role id=\"23f20eec-adad-4325-b553-1bde4be29198\" title=\"Sender\" type=\"sender\" order=\"0\"/><role id=\"b811f2b6-1656-42aa-9420-a9b8addb0246\" title=\"Assignee\" type=\"assignee\" order=\"1\"/></roles></flow><documents><document id=\"4a61f258-fd9d-406c-b47e-81c90d4e5c47\"><info><title>Agreement</title></info><body><field type=\"text\" name=\"customer_name\" placeholder=\"Enter customer name\" roleId=\"b811f2b6-1656-42aa-9420-a9b8addb0246\" optional=\"false\"/></body></document></documents></template>"
}
```

### Response

| Field     | Type | Description                   |
| --------- | ---- | ----------------------------- |
| `uuid`    | UUID | Created template UUID         |
| `version` | UUID | Created template version UUID |

### Response example

```json
{
  "uuid": "56cacd6a-ffe7-4b77-9c0c-f928d9a18cb5",
  "version": "ab0d11cb-ebdd-42bd-a581-ddca1bb9b585"
}
```

### Status codes

<table><thead><tr><th width="180.6666259765625">Code</th><th>Description</th></tr></thead><tbody><tr><td><code>200</code></td><td>Success. The response contains the template UUID and version</td></tr><tr><td><code>401</code></td><td>Missing, invalid, or expired authorization token</td></tr><tr><td><code>403</code></td><td>Authenticated user cannot create templates in the target mailbox</td></tr></tbody></table>

### Related topics

* [Send Envelope](/api-reference/send-envelope)
* [Fill Envelope](/api-reference/fill-envelope)


# Search Mailboxes and Contacts

This document contains details for the /api/v1/mailbox/search endpoint, including headers, query parameters, response fields, and status codes.

### Endpoint

| Property | Value                    |
| -------- | ------------------------ |
| Method   | `GET`                    |
| URL      | `/api/v1/mailbox/search` |

### Headers

| Header          | Required | Description                                   |
| --------------- | -------- | --------------------------------------------- |
| `Authorization` | Yes      | Bearer authorization token                    |
| `Mailbox`       | Yes      | Current mailbox UUID and contact-list context |

### Query parameters

| Parameter | Type   | Required | Description                                               |
| --------- | ------ | -------- | --------------------------------------------------------- |
| `q`       | string | Yes      | Alias, contact, user email, mailbox name, or mailbox UUID |
| `type`    | string | No       | Restricts the search to `ALIAS` or `UUID`                 |

#### Type values

| Value   | Description             |
| ------- | ----------------------- |
| `ALIAS` | Search by mailbox alias |
| `UUID`  | Search by mailbox UUID  |

### Request example

```http
GET /api/v1/mailbox/search?q=john.doe@example.com
Authorization: Bearer {token}
Mailbox: 837bc65e-4818-48f5-a933-2d00b24b6e12
```

### Response

```json
[
  {
    "mailboxName": "John Doe",
    "mailboxUuid": "9baec31c-e940-4894-b6d1-52033e1af66e",
    "alias": "john-doe",
    "accountUuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "inContacts": true
  }
]
```

| Field         | Type    | Description                                                    |
| ------------- | ------- | -------------------------------------------------------------- |
| `mailboxName` | string  | Mailbox name                                                   |
| `mailboxUuid` | UUID    | Mailbox UUID                                                   |
| `alias`       | string  | Mailbox alias                                                  |
| `accountUuid` | UUID    | Account UUID                                                   |
| `inContacts`  | boolean | Whether the mailbox is saved in the current mailbox’s contacts |

{% hint style="info" %}
Use `mailboxUuid` when assigning a mailbox to an envelope role.
{% endhint %}

### Status codes

| Code     | Description                |
| -------- | -------------------------- |
| `200 OK` | Returns matching mailboxes |

### Related topics

* [Authorization](/api-reference/authorization)
* [Send Envelope](/api-reference/send-envelope)
* [Error handling](/error-codes/error-handling-and-api-error-codes)


# Account Domains

This document contains account domain endpoints, including parameters, requests, responses, and status codes.

## Account Domains

An account domain is a verified company email domain connected to a DocStudio account. It establishes the corporate environment in which an organization can create and manage corporate users, assign account and mailbox permissions, configure automatic mailbox creation, and apply corporate authentication rules.

The endpoints on this page manage the domain and its SAML2 or OAuth2 identity providers. They do not create users, mailboxes, roles, or permissions directly. For complete request and response schemas, parameter requirements, and status codes, use the [Swagger UI](https://api.docstudio.com/swagger-ui/index.html).

### Business goals

Account Domain endpoints support the following business goals:

* **Establish a corporate environment.** Register and verify that an organization controls a company email domain before using it for corporate user management.
* **Manage the domain lifecycle.** Retrieve, update, verify, activate, deactivate, check, or delete a domain configuration.
* **Configure corporate authentication.** Connect a SAML2 or OAuth2 identity provider to the domain and optionally require users from that domain to authenticate through SSO.
* **Automate administration.** Manage corporate domain and identity-provider configuration from an internal administration system instead of configuring it manually.

### Endpoint summary

#### Account domains

<table><thead><tr><th width="98">Method</th><th width="332">Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/v1/account/{accountUuid}/domain</code></td><td>Retrieve account domains or find them by name or status</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/account/{accountUuid}/domain</code></td><td>Register a corporate email domain and optionally connect an identity provider</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/account/{accountUuid}/domain/{domainUuid}</code></td><td>Retrieve one domain's current configuration and status</td></tr><tr><td><code>PUT</code></td><td><code>/api/v1/account/{accountUuid}/domain/{domainUuid}</code></td><td>Change the connected identity provider or the SSO-only login setting</td></tr><tr><td><code>PATCH</code></td><td><code>/api/v1/account/{accountUuid}/domain/{domainUuid}/{action}</code></td><td>Verify, confirm, activate, deactivate, or check the domain</td></tr><tr><td><code>DELETE</code></td><td><code>/api/v1/account/{accountUuid}/domain/{domainUuid}</code></td><td>Remove a domain that the organization no longer manages through the account</td></tr></tbody></table>

#### SAML2 identity providers

<table><thead><tr><th width="98">Method</th><th width="310">Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/v1/account/{accountId}/saml-provider</code></td><td>Retrieve the SAML2 providers configured for the account</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/account/{accountId}/saml-provider</code></td><td>Add a SAML2 provider before connecting it to a corporate domain</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/account/{accountId}/saml-provider/{id}</code></td><td>Retrieve one SAML2 provider's complete configuration</td></tr><tr><td><code>PUT</code></td><td><code>/api/v1/account/{accountId}/saml-provider/{id}</code></td><td>Update SAML metadata, attribute mappings, certificates, or signing credentials</td></tr><tr><td><code>DELETE</code></td><td><code>/api/v1/account/{accountId}/saml-provider/{id}</code></td><td>Remove a SAML2 provider that is no longer used</td></tr></tbody></table>

#### OAuth2 identity providers

<table><thead><tr><th width="99">Method</th><th>Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/v1/account/{accountId}/oauth-provider</code></td><td>Retrieve the OAuth2 providers configured for the account</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/account/{accountId}/oauth-provider</code></td><td>Add an OAuth2 provider before connecting it to a corporate domain</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/account/{accountId}/oauth-provider/{id}</code></td><td>Retrieve one OAuth2 provider's complete configuration</td></tr><tr><td><code>PUT</code></td><td><code>/api/v1/account/{accountId}/oauth-provider/{id}</code></td><td>Update client credentials, provider endpoints, issuer information, JWK settings, or scopes</td></tr><tr><td><code>DELETE</code></td><td><code>/api/v1/account/{accountId}/oauth-provider/{id}</code></td><td>Remove an OAuth2 provider that is no longer used</td></tr></tbody></table>

### Account domain lifecycle

A domain is first registered through `POST /api/v1/account/{accountUuid}/domain`. The request can include an identity-provider UUID and the `onlySsoLogin` setting, but the identity provider must already exist in the account.

```json
{
  "ssoIdProviderUuid": "{providerUuid}",
  "onlySsoLogin": true,
  "domain": "acme.com"
}
```

Use `GET /api/v1/account/{accountUuid}/domain/{domainUuid}` to retrieve the domain before changing its configuration. The response shows its current status, verification information, connected identity provider, and `onlySsoLogin` value.

Use `PUT /api/v1/account/{accountUuid}/domain/{domainUuid}` to replace the connected identity provider or change the SSO-only login setting without recreating the domain.

```json
{
  "ssoIdProviderUuid": "{providerUuid}",
  "onlySsoLogin": true
}
```

Use one endpoint for domain verification and status changes:

```http
PATCH /api/v1/account/{accountUuid}/domain/{domainUuid}/{action}
Authorization: Bearer {token}
Content-Type: application/json

{
  "method": "DNS_TXT_RECORD"
}
```

Supported `{action}` values:

<table><thead><tr><th width="235">Action</th><th>Purpose</th></tr></thead><tbody><tr><td><code>verify</code></td><td>Start or update DNS-based domain verification</td></tr><tr><td><code>confirm</code></td><td>Confirm verification after configuring the required DNS record</td></tr><tr><td><code>activate</code></td><td>Activate the verified domain</td></tr><tr><td><code>deactivate</code></td><td>Disable the domain without deleting its configuration</td></tr><tr><td><code>check</code></td><td>Check the current verification state</td></tr></tbody></table>

Use `DNS_TXT_RECORD` or `DNS_CNAME_RECORD` as the request body `method`.

### Identity-provider configuration

SAML2 provider endpoints are intended for organizations that authenticate users through a SAML-compatible identity provider. The configuration includes SAML metadata, user attribute mappings, a signing certificate, and a signing private key.

OAuth2 provider endpoints are intended for organizations that use OAuth2 or OpenID Connect authentication. The configuration includes the client ID and secret, authorization and token endpoints, issuer URI, JWK set URI, and requested scopes.

After creating a provider, use its UUID as `ssoIdProviderUuid` when creating or updating an account domain. Set `onlySsoLogin` to `true` when users from the domain must authenticate through the connected corporate provider.

{% hint style="warning" %}
Provider configurations may contain signing private keys or OAuth2 client secrets. Store these values securely. Do not include real credentials in source code, application logs, or public documentation.
{% endhint %}

### Practical example: Configure a corporate domain with SAML2 SSO

A company uses `acme.com` email addresses and wants its corporate users to authenticate through its SAML2 identity provider. The integration must create the provider, register and verify the domain, connect the provider, and activate the domain.

#### Create the SAML2 provider

```http
POST /api/v1/account/{accountId}/saml-provider
Authorization: Bearer {token}
Content-Type: application/json

{
  "id": "68b95bf4-71a8-4fa4-b086-7fc32c187d71",
  "name": "Acme SAML",
  "firstNameMapping": "givenName",
  "lastNameMapping": "surname",
  "phoneMapping": "telephoneNumber",
  "metadataUrl": "https://idp.acme.com/saml/metadata",
  "metadataXml": "{metadataXml}",
  "signingCertificate": "{signingCertificate}",
  "signingPrivateKey": "{signingPrivateKey}"
}
```

#### Register the domain

Use the provider UUID as `ssoIdProviderUuid`. Enabling `onlySsoLogin` requires users from the domain to use the connected provider.

```http
POST /api/v1/account/{accountUuid}/domain
Authorization: Bearer {token}
Content-Type: application/json

{
  "ssoIdProviderUuid": "68b95bf4-71a8-4fa4-b086-7fc32c187d71",
  "onlySsoLogin": true,
  "domain": "acme.com"
}
```

#### Verify and activate the domain

Use the `domainUuid` returned when the domain was created. Run `verify`, `confirm`, and `activate` in that order. Configure the returned DNS record before running `confirm`.

```http
PATCH /api/v1/account/{accountUuid}/domain/{domainUuid}/{action}
Authorization: Bearer {token}
Content-Type: application/json

{
  "method": "DNS_TXT_RECORD"
}
```

Retrieve the domain to check its current configuration and status:

```http
GET /api/v1/account/{accountUuid}/domain/{domainUuid}
Authorization: Bearer {token}
```

### Practical example: Move a domain from SAML2 to OAuth2

A company already has a corporate domain but is replacing its SAML2 provider with an OAuth2 provider. The domain does not need to be recreated because its connected provider can be changed through the update endpoint.

#### Create the OAuth2 provider

```http
POST /api/v1/account/{accountId}/oauth-provider
Authorization: Bearer {token}
Content-Type: application/json

{
  "id": "c42a5f61-cecf-4ef0-b3ad-4956d3555049",
  "name": "Acme OAuth2",
  "clientId": "docstudio-client",
  "clientSecret": "{clientSecret}",
  "authorizationUri": "https://login.acme.com/oauth2/authorize",
  "tokenUri": "https://login.acme.com/oauth2/token",
  "issuerUri": "https://login.acme.com",
  "jwkSetUri": "https://login.acme.com/.well-known/jwks.json",
  "scopes": "openid profile email"
}
```

#### Connect the new provider to the domain

```http
PUT /api/v1/account/{accountUuid}/domain/{domainUuid}
Authorization: Bearer {token}
Content-Type: application/json

{
  "ssoIdProviderUuid": "c42a5f61-cecf-4ef0-b3ad-4956d3555049",
  "onlySsoLogin": true
}
```

Retrieve the domain and confirm that it references the new provider. Remove the previous SAML2 provider only after no domain uses it:

```http
GET /api/v1/account/{accountUuid}/domain/{domainUuid}
Authorization: Bearer {token}
```

```http
DELETE /api/v1/account/{accountId}/saml-provider/{id}
Authorization: Bearer {token}
```

### Related topics

* [Authorization](/api-reference/authorization)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)


# Dictionaries

This document contains dictionary endpoints, including parameters, request bodies, responses, and status codes.

## Dictionaries

Dictionaries store structured, reusable data that can be shared across DocStudio templates and envelopes. They are useful for centrally managed datasets such as employees, vendors, products, cost centers, office locations, contract types, or other values that should remain consistent across multiple document workflows.

A dictionary contains columns that define its structure and records that contain its data. Dictionary fields can display selectable values from a dictionary, while related values from the selected record can be used by lookup logic. For complete request and response schemas, parameter requirements, and status codes, use the [Swagger UI](https://api.docstudio.com/swagger-ui/index.html).

### Business goals

Dictionary endpoints support the following business goals:

* **Centralize reusable business data.** Store reference data once and reuse it across templates, envelopes, and document workflows.
* **Synchronize DocStudio with external systems.** Create, update, search, or delete dictionary records when data changes in an ERP, CRM, HR, or another internal system.
* **Provide controlled values for document fields.** Retrieve valid options for Dictionary fields and use related record values when filling documents.
* **Manage dictionary structure.** Create and update the columns that define the data stored in each record.
* **Export dictionary data.** Generate a CSV export for reporting, backup, migration, or external processing.

### Endpoint summary

#### Dictionary lifecycle

<table><thead><tr><th width="98">Method</th><th>Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/v1/dictionary</code></td><td>Retrieve available dictionaries or find one by name, UUID, or access level</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/dictionary</code></td><td>Create an empty dictionary and receive its UUID</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}</code></td><td>Retrieve a dictionary and optionally include its columns and record count</td></tr><tr><td><code>PATCH</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}</code></td><td>Set or update the dictionary name, description, access level, or filtered-access setting</td></tr><tr><td><code>PATCH</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/archive</code></td><td>Archive a dictionary that is no longer used for new data</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/check</code></td><td>Check whether the dictionary exists and is accessible in the current context</td></tr></tbody></table>

#### Dictionary columns

<table><thead><tr><th width="98">Method</th><th>Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>POST</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/column</code></td><td>Add a column that defines part of the dictionary record structure</td></tr><tr><td><code>PUT</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/column/{columnUuid}</code></td><td>Change a column name, order, width, or long-text setting</td></tr><tr><td><code>DELETE</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/column/{columnUuid}</code></td><td>Remove a column that is no longer required</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/column/{columnUuid}/check</code></td><td>Check whether a column exists and is accessible</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/column/{columnUuid}</code></td><td>Retrieve selectable values from a column for a Dictionary field</td></tr></tbody></table>

#### Dictionary records

<table><thead><tr><th width="98">Method</th><th>Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>POST</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/records</code></td><td>Retrieve records and filter them by column values</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/record</code></td><td>Create one or multiple dictionary records</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/record/{recordUuid}</code></td><td>Retrieve all values stored in one record</td></tr><tr><td><code>PATCH</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/record/{recordUuid}</code></td><td>Update selected column values in an existing record</td></tr><tr><td><code>DELETE</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/record</code></td><td>Delete one or multiple records</td></tr><tr><td><code>POST</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/record-uuids</code></td><td>Find record UUIDs by values stored in a specific column</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/record/{recordUuid}/column/{columnUuid}</code></td><td>Retrieve one column value from a specific record</td></tr></tbody></table>

#### Dictionary export

<table><thead><tr><th width="98">Method</th><th>Endpoint</th><th>Purpose</th></tr></thead><tbody><tr><td><code>POST</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/download</code></td><td>Start an asynchronous dictionary export in CSV format</td></tr><tr><td><code>GET</code></td><td><code>/api/v1/dictionary/{dictionaryUuid}/download/status/{taskUuid}</code></td><td>Check the export task and retrieve the generated file URL when it is ready</td></tr></tbody></table>

### Dictionary structure and headers

Most dictionary operations require the current mailbox UUID in the `Mailbox` header. The mailbox context determines which dictionaries and records are available to the request.

```http
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {mailboxUuid}
```

Create a dictionary as an empty object. Save its `dictionaryUuid`. Then update its properties, add columns, and create records.

Save each `columnUuid`. Use it in record requests to identify the column for each value.

```json
{
  "uuid": "{columnUuid}",
  "value": "Acme Corporation"
}
```

To create multiple records, send an array of records. Each record is represented by an array of column-value objects.

```json
[
  [
    {
      "uuid": "{vendorCodeColumnUuid}",
      "value": "V-1001"
    },
    {
      "uuid": "{vendorNameColumnUuid}",
      "value": "Acme Corporation"
    }
  ],
  [
    {
      "uuid": "{vendorCodeColumnUuid}",
      "value": "V-1002"
    },
    {
      "uuid": "{vendorNameColumnUuid}",
      "value": "Northwind Logistics"
    }
  ]
]
```

Start an export with `POST /api/v1/dictionary/{dictionaryUuid}/download`. Save the returned `taskUuid`. Use `GET /api/v1/dictionary/{dictionaryUuid}/download/status/{taskUuid}` to check the task and retrieve the generated file URL.

### Practical example: Synchronize a vendor directory

A company stores its approved vendors in an ERP system and wants the same data to be available in DocStudio document workflows. The integration creates a Vendor Directory dictionary, defines its columns, adds vendor records, and searches those records when business data is updated.

#### Create an empty dictionary

```http
POST /api/v1/dictionary
Authorization: Bearer {token}
Mailbox: {mailboxUuid}
```

The response contains the new `dictionaryUuid`.

```json
{
  "uuid": "{dictionaryUuid}"
}
```

#### Configure the dictionary

```http
PATCH /api/v1/dictionary/{dictionaryUuid}
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {mailboxUuid}

{
  "name": "Vendor Directory",
  "description": "Approved vendors synchronized from the ERP system",
  "access": "mailbox",
  "filteredAccessOnly": false
}
```

#### Create the columns

Create each column with the following values. Save every returned column UUID. Record requests use UUIDs instead of column names.

<table data-header-hidden><thead><tr><th width="140"></th><th width="184"></th><th width="195"></th><th></th></tr></thead><tbody><tr><td>Column</td><td><code>name</code></td><td><code>order</code></td><td><code>width</code></td></tr><tr><td>vendor code</td><td><code>Vendor Code</code></td><td><code>0</code></td><td><code>150</code></td></tr><tr><td>vendor name</td><td><code>Vendor Name</code></td><td><code>1</code></td><td><code>300</code></td></tr><tr><td>country</td><td><code>Country</code></td><td><code>2</code></td><td><code>150</code></td></tr></tbody></table>

```http
POST /api/v1/dictionary/{dictionaryUuid}/column
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {mailboxUuid}

{
  "name": "Vendor Code",
  "order": 0,
  "width": 150,
  "longText": false
}
```

#### Create vendor records

```http
POST /api/v1/dictionary/{dictionaryUuid}/record
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {mailboxUuid}

[
  [
    {
      "uuid": "{vendorCodeColumnUuid}",
      "value": "V-1001"
    },
    {
      "uuid": "{vendorNameColumnUuid}",
      "value": "Acme Corporation"
    },
    {
      "uuid": "{countryColumnUuid}",
      "value": "United States"
    }
  ],
  [
    {
      "uuid": "{vendorCodeColumnUuid}",
      "value": "V-1002"
    },
    {
      "uuid": "{vendorNameColumnUuid}",
      "value": "Northwind Logistics"
    },
    {
      "uuid": "{countryColumnUuid}",
      "value": "Canada"
    }
  ]
]
```

#### Find a vendor by code

```http
POST /api/v1/dictionary/{dictionaryUuid}/records?offset=0&limit=25
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {mailboxUuid}

{
  "filters": [
    {
      "uuid": "{vendorCodeColumnUuid}",
      "op": "=",
      "value": "V-1001"
    }
  ]
}
```

The response contains the matching record UUID and all stored values. Save the UUID for later read, update, or delete operations.

### Practical example: Retrieve values for a Dictionary field

A purchase-order template contains a Dictionary field that allows a user to select an approved vendor. The integration retrieves matching values from the Vendor Name column and then reads the selected record to obtain related vendor information.

#### Retrieve matching vendor names

```http
POST /api/v1/dictionary/{dictionaryUuid}/column/{vendorNameColumnUuid}?offset=0&limit=25
Authorization: Bearer {token}
Content-Type: application/json
Mailbox: {mailboxUuid}

{
  "envelopeUuid": "{envelopeUuid}",
  "templateUuid": "{templateUuid}",
  "versionUuid": "{versionUuid}",
  "documentId": "purchase-order",
  "fieldName": "vendor",
  "rowIndex": 0,
  "keyword": "Acme",
  "filter": {}
}
```

The response contains matching display values and their record UUIDs.

```json
{
  "totalElements": 1,
  "sizeRequested": 25,
  "numberOfElements": 1,
  "data": [
    {
      "recordUuid": "{recordUuid}",
      "data": "Acme Corporation"
    }
  ]
}
```

#### Retrieve the selected record

Use the returned `recordUuid` to retrieve the complete vendor record or one related column value.

```http
GET /api/v1/dictionary/{dictionaryUuid}/record/{recordUuid}
Authorization: Bearer {token}
Mailbox: {mailboxUuid}
```

Retrieve one related value directly by its column UUID:

```http
GET /api/v1/dictionary/{dictionaryUuid}/record/{recordUuid}/column/{countryColumnUuid}
Authorization: Bearer {token}
Mailbox: {mailboxUuid}
```

Use the selected vendor record while filling or validating other document fields.

### Related topics

* [Authentication and application tokens](/introduction/authentication-and-application-tokens)
* [Envelope fields](/guides/envelope-fields)
* [Import Dictionary CSV](/guides/import-dictionary-csv)
* [Error handling and API error codes](/error-codes/error-handling-and-api-error-codes)


# Application token object

This document contains the application token object returned by token endpoints.

### Used in

| Endpoint / Area                                                                              | How it is used                                       |
| -------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| [Authentication and application tokens](/introduction/authentication-and-application-tokens) | Returned when listing or creating application tokens |

### Object example

```json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "token": "string",
  "createdAt": "2026-07-21T13:41:33.695Z",
  "expireAt": "2026-07-21T13:41:33.695Z",
  "lastUsedAt": "2026-07-21T13:41:33.695Z"
}
```

### Fields

<table><thead><tr><th width="127">Field</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>UUID</td><td>Not specified</td><td>Application token ID</td></tr><tr><td><code>name</code></td><td>string</td><td>Not specified</td><td>Application token name</td></tr><tr><td><code>token</code></td><td>string</td><td>Not specified</td><td>Token value for the <code>Authorization</code> header</td></tr><tr><td><code>createdAt</code></td><td>date-time</td><td>Not specified</td><td>Token creation date and time</td></tr><tr><td><code>expireAt</code></td><td>date-time</td><td>Not specified</td><td>Token expiration date and time</td></tr><tr><td><code>lastUsedAt</code></td><td>date-time</td><td>Not specified</td><td>Date and time when the token was last used</td></tr></tbody></table>

{% hint style="info" %}
Store the `token` value securely when it is created.
{% endhint %}


# List response object

This document contains the pagination object used in list responses.

### Used in

<table><thead><tr><th width="321.77783203125">Endpoint / Area</th><th>How it is used</th></tr></thead><tbody><tr><td><a href="/api-reference/dictionaries">Dictionaries</a></td><td>Returns dictionary, record, or column value lists</td></tr><tr><td><a href="/api-reference/account-domains">Account Domain Endpoints</a></td><td>Returns matching account domains</td></tr><tr><td><a href="/api-reference/check-envelope-status">Check Envelope Status</a></td><td>Returns matching envelopes</td></tr></tbody></table>

### Object example

```json
{
  "totalElements": 0,
  "sizeRequested": 25,
  "numberOfElements": 0,
  "data": []
}
```

### Fields

<table><thead><tr><th width="169.22216796875">Field</th><th width="126.444580078125">Type</th><th width="174.111083984375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>totalElements</code></td><td>integer</td><td>Yes</td><td>Total matching records</td></tr><tr><td><code>sizeRequested</code></td><td>integer</td><td>Yes</td><td>Requested page size</td></tr><tr><td><code>numberOfElements</code></td><td>integer</td><td>Yes</td><td>Records in the current response</td></tr><tr><td><code>data</code></td><td>array</td><td>Yes</td><td>Returned objects</td></tr></tbody></table>

{% hint style="info" %}
The element type in `data` depends on the response schema.
{% endhint %}


# UUID list object

This document contains the UUID list response object.

### Used in

| Endpoint / Area                             | How it is used                   |
| ------------------------------------------- | -------------------------------- |
| [Dictionaries](/api-reference/dictionaries) | Returns UUIDs of created records |

### Object example

```json
{
  "data": [
    "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  ],
  "totalElements": 1
}
```

### Fields

| Field           | Type    | Required | Description          |
| --------------- | ------- | -------- | -------------------- |
| `data`          | array   | Yes      | Returned UUID values |
| `totalElements` | integer | Yes      | Returned UUID count  |

{% hint style="info" %}
Each `data` item is a UUID string.
{% endhint %}


# UUID response object

This document contains the UUID response object returned by API operations.

### Used in

<table><thead><tr><th width="352.888916015625">Endpoint / Area</th><th>How it is used</th></tr></thead><tbody><tr><td><a href="/api-reference/create-template">Create Template</a></td><td>Returns the created template UUID</td></tr><tr><td><a href="/api-reference/dictionaries">Dictionaries</a></td><td>Returns the created dictionary or column UUID</td></tr></tbody></table>

### Object example

```json
{
  "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

### Fields

<table><thead><tr><th width="112.66668701171875">Field</th><th width="210.111083984375">Type</th><th width="128.111083984375">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>uuid</code></td><td>UUID</td><td>Yes</td><td>Resource UUID returned by the API</td></tr></tbody></table>

{% hint style="info" %}
The `uuid` value identifies the returned resource.
{% endhint %}


# Error handling and API error codes

This document explains how to interpret API errors and resolve common request failures.

### HTTP status codes

<table><thead><tr><th width="83">Code</th><th width="186">Meaning</th><th>What to check first</th></tr></thead><tbody><tr><td><code>400</code></td><td>Bad request</td><td>Request format, required values, JSON, XML, and query parameters</td></tr><tr><td><code>401</code></td><td>Unauthorized</td><td>Token and <code>Authorization</code> header</td></tr><tr><td><code>402</code></td><td>Payment Required</td><td>Billing limits, plan restrictions, and enabled functionality</td></tr><tr><td><code>403</code></td><td>Forbidden</td><td>Permissions and access to the mailbox, account, or object</td></tr><tr><td><code>404</code></td><td>Not found</td><td>UUID, environment, and object availability</td></tr><tr><td><code>409</code></td><td>Conflict</td><td>Current entity state and duplicate operations</td></tr><tr><td><code>410</code></td><td>Entity gone</td><td>Whether the entity was deleted, archived, or became unavailable</td></tr><tr><td><code>422</code></td><td>Unprocessable entity</td><td>Template values, XML, fields, and validation rules</td></tr><tr><td><code>425</code></td><td>Too early</td><td>Whether the previous operation is complete</td></tr><tr><td><code>429</code></td><td>Too many requests</td><td>Endpoint rate limits and request frequency</td></tr></tbody></table>

### Authentication and access errors

Use `401` when the request is not authenticated. Check the token and header format.

```http
Authorization: Bearer {token}
```

Use `403` when the request is authenticated but lacks access. Check the token owner, mailbox context, and permissions.

{% columns %}
{% column %}

* token belongs to the expected user or integration
* correct environment
* access to the target mailbox
* correct `mailboxUuid` header
  {% endcolumn %}

{% column %}

* access to the template or envelope
* access to the account or dictionary
* permission for the requested action
  {% endcolumn %}
  {% endcolumns %}

### Request format and validation errors

Use `400` when the request format is invalid. Use `422` when the request format is valid but values cannot be processed.

For `400`, check:

{% columns %}
{% column %}

* endpoint URL and HTTP method
* required headers
* `Content-Type`
* path and query parameters
  {% endcolumn %}

{% column %}

* URL-encoded query values
* valid JSON body
* valid XML in `data`
* endpoint request format
  {% endcolumn %}
  {% endcolumns %}

For `422`, check:

{% columns %}
{% column %}

* matching `templateUuid` and `templateVersion`
* role and document IDs from the template version
* field names in the selected document
* required field values
  {% endcolumn %}

{% column %}

* field formats and validation rules
* dynamic table group names and indexes
* attachment UUIDs
* active mailbox role and envelope state
  {% endcolumn %}
  {% endcolumns %}

### Mailbox and file errors

Use mailbox UUIDs only in their intended context. Do not interchange sender, recipient, and current mailbox values.

```http
GET /api/v1/mailbox/{mailboxUuid}?UUID={envelopeUuid}
Authorization: Bearer {token}
Content-Type: application/json
mailboxUuid: {mailboxUuid}
```

Upload a file before referencing it in an envelope. Use the returned `attachmentId` as `attachmentUuid`.

```xml
<field name="supporting_file" attachmentUuid="{attachmentId}">
  {filename}
</field>
```

### Retry behavior

Retry only when the endpoint contract and request state allow it.

| Response                                        | Action                                           |
| ----------------------------------------------- | ------------------------------------------------ |
| `425`                                           | Wait before retrying                             |
| `429`                                           | Reduce request frequency and retry after a delay |
| `409`                                           | Check the current entity state before retrying   |
| `400`, `401`, `402`, `403`, `404`, `410`, `422` | Correct the underlying issue before retrying     |

{% hint style="warning" %}
Do not retry data-creating requests until you confirm their current state.
{% endhint %}

### Safe error logging

Log only data needed to diagnose the issue. Mask secrets before storing or sharing logs.

{% columns %}
{% column %}
**Safe to log**

* endpoint name
* HTTP method
* status code
* environment
* sanitized error message
  {% endcolumn %}

{% column %}
**Do not log**

* API tokens
* passwords
* private keys
* full `Authorization` headers
* document and file contents
  {% endcolumn %}
  {% endcolumns %}

```http
Authorization: Bearer ***
```

### Application error codes

Error codes identify the affected product area. Use the error detail and response context to locate the failed value or operation.

#### Common

<table><thead><tr><th width="85">Code</th><th>Error detail</th><th>Resolution</th></tr></thead><tbody><tr><td><code>1000</code></td><td>Undefined exception</td><td>Record the sanitized error details and contact support</td></tr><tr><td><code>1001</code></td><td>Record not found</td><td>Check the request parameter and object UUID</td></tr><tr><td><code>1004</code></td><td>Empty value for required field</td><td>Provide a value for the required field</td></tr><tr><td><code>1005</code></td><td>Too many requests</td><td>Wait before retrying the request</td></tr><tr><td><code>1006</code></td><td>Validation failed</td><td>Use the response details to identify the failed field and rule</td></tr><tr><td><code>1008</code></td><td>Invalid XML</td><td>Correct the XML structure</td></tr><tr><td><code>1019</code></td><td>File is not ready for download</td><td>Wait and retry the download</td></tr><tr><td><code>1022</code></td><td>Request header required</td><td>Add the required header</td></tr><tr><td><code>1023</code></td><td>Request query parameter required</td><td>Add the required query parameter</td></tr><tr><td><code>1024</code></td><td>Request body parameter required</td><td>Add the required request body parameter</td></tr><tr><td><code>1025</code></td><td>Request path parameter required</td><td>Add the required path parameter</td></tr><tr><td><code>1027</code></td><td>Authentication token has expired or was revoked</td><td>Authorize again</td></tr><tr><td><code>1032</code></td><td>Attachment not found</td><td>Check the attachment UUID</td></tr><tr><td><code>1039</code></td><td>Attachment belongs to another mailbox</td><td>Use an attachment available in the current mailbox context</td></tr><tr><td><code>1055</code></td><td>Payload is too large</td><td>Reduce the request or file size</td></tr></tbody></table>

#### Template and envelope

<table><thead><tr><th width="84">Code</th><th>Error detail</th><th>Resolution</th></tr></thead><tbody><tr><td><code>40001</code></td><td>Document not found</td><td>Check the document ID</td></tr><tr><td><code>40002</code></td><td>Template is archived</td><td>Use an active template</td></tr><tr><td><code>40003</code></td><td>Template not found</td><td>Check the template UUID</td></tr><tr><td><code>40051</code></td><td>Template UUID and version mismatch</td><td>Use values from the same template structure</td></tr><tr><td><code>40052</code></td><td>Template role not found</td><td>Check the role ID</td></tr><tr><td><code>50001</code></td><td>Envelope field is empty</td><td>Provide a value for the required field</td></tr><tr><td><code>50007</code></td><td>Role mailbox UUID is invalid</td><td>Assign a valid mailbox UUID to each required role</td></tr><tr><td><code>50008</code></td><td>Role ID is invalid</td><td>Use role IDs from the selected template version</td></tr><tr><td><code>50011</code></td><td>Envelope not found</td><td>Check the envelope UUID and mailbox context</td></tr><tr><td><code>50012</code></td><td>Template UUID or version is required</td><td>Provide both template identifiers</td></tr><tr><td><code>50017</code></td><td>Envelope document not found in XML</td><td>Use the document ID from the template structure</td></tr><tr><td><code>50033</code></td><td>No XML data for envelope</td><td>Provide the envelope XML in the request</td></tr><tr><td><code>50049</code></td><td>No active role for mailbox</td><td>Wait for the active role or use the correct mailbox</td></tr><tr><td><code>50050</code></td><td>Wrong envelope status</td><td>Check the envelope state before sending the request</td></tr><tr><td><code>50067</code></td><td>Attachment UUID is required</td><td>Use the uploaded attachment ID as `attachmentUuid`</td></tr><tr><td><code>50079</code></td><td>Roles do not match template roles</td><td>Update the envelope XML flow</td></tr></tbody></table>

#### Access and object errors

<table><thead><tr><th width="130">Area</th><th width="86">Code</th><th>Error detail</th><th>Resolution</th></tr></thead><tbody><tr><td>User</td><td><code>10001</code></td><td>User not found</td><td>Check the user UUID</td></tr><tr><td>Account</td><td><code>20001</code></td><td>Account not found</td><td>Check the account UUID</td></tr><tr><td>Mailbox</td><td><code>30001</code></td><td>Mailbox not found</td><td>Check the mailbox UUID</td></tr><tr><td>Dictionary</td><td><code>60001</code></td><td>Dictionary not found</td><td>Check the dictionary UUID</td></tr><tr><td>Integration</td><td><code>80002</code></td><td>Integration rule not found</td><td>Check the integration rule UUID</td></tr><tr><td>Permissions</td><td><code>90002</code></td><td>Insufficient account privileges</td><td>Request the required account permission</td></tr><tr><td>Permissions</td><td><code>90003</code></td><td>Insufficient mailbox privileges</td><td>Request the required mailbox permission</td></tr><tr><td>Permissions</td><td><code>90009</code></td><td>No access to template</td><td>Request access to the template</td></tr><tr><td>Permissions</td><td><code>90013</code></td><td>No access to mailbox</td><td>Request access to the mailbox</td></tr><tr><td>Permissions</td><td><code>90015</code></td><td>No access to envelope</td><td>Use a mailbox included in the envelope flow</td></tr><tr><td>Billing</td><td><code>120003</code></td><td>Plan limit reached</td><td>Adjust usage or change the billing plan</td></tr></tbody></table>

### Related topics

{% columns %}
{% column %}

* [Authentication and application tokens](/introduction/authentication-and-application-tokens)
* [API token security](/introduction/api-token-security)
* [Working with XML payloads](/guides/xml-payloads)
  {% endcolumn %}

{% column %}

* [Working with templates and reusable IDs](/guides/templates-and-reusable-ids)
* [Working with envelope fields](/guides/envelope-fields)
* [Uploading files and external documents](/guides/files-and-external-documents)
  {% endcolumn %}
  {% endcolumns %}


# Java & PHP Software Development Kits

This document contains links to the Java and PHP SDKs, including quick start resources and the published Composer package for PHP.

For further convenience, we have built SDKs for Java and PHP.

### Java SDK

Java SDK, minimal requirements, and a quick start guide can be found at <https://github.com/jecksolovyev/com.docstudio.api.client>

### PHP SDK

PHP SDK, minimal requirements, and a quick start guide can be found at <https://github.com/jecksolovyev/com.docstudio.api.php-client>

{% hint style="info" %}
In addition, we have published the PHP SDK as a *Composer package* at <https://packagist.org/packages/yuramozol/com.docstudio.api.php-client>
{% endhint %}


