---
title: "Documents — Endpoints API v3 de AllSign"
type: reference
canonical_url: "https://allsign.io/developers/docs/endpoints/documents"
api_version: "2026-07-11"
---

# Documents

Un documento representa un archivo listo para firma electrónica con biometría, anti-deepfake y NOM-151. En la API v3 un **solo endpoint** (`POST /v3/documents`) crea el documento a partir de una **plantilla** o de un **PDF subido en base64** — tú eliges la fuente con el campo `source`.

Todas las respuestas usan **camelCase** en el wire, ids opacos con prefijo (`doc_`, `tmpl_`, `fld_`, `sgr_`, `evt_`) y `livemode` para distinguir entorno `live` de `test`. Los errores siguen **problem+json** (RFC 9457) con un campo `code` en `UPPER_SNAKE`. Las listas paginan por cursor (`startingAfter` / `endingBefore` + `hasMore`) y las respuestas traen headers `RateLimit-*`.

Si el documento nace de una plantilla PDF con formulario, sus campos viven en `GET …/fields`: quién los llena (`role`, `signerId`), qué valor tienen, si el emisor los prellenó y bloqueó (`values`/`readOnly` al crear, `filledBy: "owner"`) y quién puso cada valor (`filledBy`, `filledAt`). Guía: [Formularios PDF](https://allsign.io/developers/docs/guides/pdf-forms).

Los ejemplos usan `$ALLSIGN_API_KEY`. Defínela una vez con tu key de sandbox: `export ALLSIGN_API_KEY="allsign_test_sk_…"` (en PowerShell: `$env:ALLSIGN_API_KEY="allsign_test_sk_…"`).

[Descargar OpenAPI](https://allsign.io/developers/docs/openapi.public.json)[Colección de Postman](https://allsign.io/developers/docs/allsign-api-v3.postman_collection.json)

Endpoints

-   [GET`/documents`](#list-documents)
-   [GET`/documents/stats`](#get-aggregate-statistics)
-   [POST`/documents`](#create-document)
-   [GET`/documents/{document_id}`](#retrieve-document)
-   [PATCH`/documents/{document_id}`](#update-document)
-   [POST`/documents/{document_id}/send`](#send-document)
-   [POST`/documents/{document_id}/void`](#void-document)
-   [GET`/documents/{document_id}/signers`](#list-signers)
-   [PATCH`/documents/{document_id}/signers/{signer_id}`](#change-a-signer-s-stage)
-   [GET`/documents/{document_id}/fields`](#list-document-fields)
-   [POST`/documents/{document_id}/fields`](#create-document-field)
-   [PATCH`/documents/{document_id}/fields/{field_id}`](#update-document-field)
-   [DELETE`/documents/{document_id}/fields/{field_id}`](#delete-document-field)
-   [POST`/documents/{document_id}/fields:assign-role`](#assign-fields-to-a-role)
-   [GET`/documents/{document_id}/roles`](#list-document-roles)
-   [DELETE`/documents/{document_id}/roles/{role_id}`](#delete-a-document-role)
-   [POST`/documents/{document_id}/fields:from-document`](#import-signing-fields-from-a-document)
-   [GET`/documents/{document_id}/file`](#download-document-file)
-   [GET`/documents/{document_id}/values`](#get-document-values)
-   [PATCH`/documents/{document_id}/values`](#update-document-values)
-   [POST`/documents/{document_id}/save-to-template`](#save-the-document-as-a-template-version)
-   [GET`/documents/{document_id}/events`](#list-events)
-   [GET`/documents/{document_id}/evidence`](#get-evidence-bundle)
-   [POST`/documents/{document_id}/annexes`](#attach-an-annex)
-   [GET`/documents/{document_id}/family`](#get-a-document-s-family)
-   [POST`/documents/{document_id}/signers/{signer_id}/remind`](#remind-signer)
-   [POST`/documents/{document_id}/signers/remind-all`](#remind-all-pending-signers)
-   [POST`/documents/{document_id}/signers/{signer_id}/reassign`](#reassign-signer)
-   [POST`/sandbox/signers/{signer_id}/sign`](#sign-as-a-signer-sandbox-only)
-   [GET`/documents/{document_id}/observers`](#list-document-observers)
-   [POST`/documents/{document_id}/observers`](#add-document-observer)
-   [DELETE`/documents/{document_id}/observers/{observer_id}`](#remove-document-observer)
-   [POST`/documents/{document_id}/transfer-owner`](#transfer-document-owner)
-   [POST`/documents/transfer-owner`](#transfer-documents-owner)
-   [DELETE`/documents/bulk`](#bulk-delete-documents)
-   [POST`/documents/bulk-sends`](#create-bulk-send)
-   [GET`/documents/bulk-sends/{batch_id}`](#get-bulk-send)

## El objeto Document

#### Atributos

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `id` string requerido
    
    ID del documento (`doc_…`).
    
-   `object` string, siempre "document"
    
    Siempre `"document"`.
    
-   `name` string requerido
    
    Nombre visible del documento.
    
-   `status` enum requerido
    
    Estado del ciclo de vida: `draft`, `collecting_data`, `awaiting_signatures`, `correcting`, `processing`, `completed`, `expired`, `voided`, `error`.
    
    Valores: `draft` `collecting_data` `awaiting_signatures` `correcting` `processing` `completed` `expired` `voided` `error`
    
-   `documentType` string requerido
    
    Token opaco del tipo de documento.
    
-   `signerCount` integer requerido
    
    Número total de firmantes.
    
-   `signedCount` integer requerido
    
    Cuántos firmantes ya firmaron.
    
-   `ownerId` string requerido
    
    Dueño del documento (`usr_…`).
    
-   `orgId` string puede ser null
    
    Organización del documento (`org_…`).
    
-   `folderId` string puede ser null
    
    Carpeta que contiene el documento (`fld_…`). Es `null` si el documento no está en ninguna carpeta que esta credencial pueda abrir con `GET /v3/folders/{id}`.
    
-   `expiresAt` string (fecha-hora ISO 8601) puede ser null
    
    Fecha límite de firma (ISO 8601).
    
-   `signingOrder` enum
    
    `parallel` o `sequential` (firmantes por etapas con `routingOrder`). Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
    
    Valores: `parallel` `sequential`
    
-   `currentStage` integer puede ser null
    
    Etapa activa en un documento `sequential` mientras espera firmas; `null` en paralelo o al terminar. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
    
-   `expirationReminders` array de integer puede ser null
    
    Horas antes del vencimiento en las que se envían recordatorios.
    
-   `templateId` string puede ser null
    
    Plantilla de la que nació el documento (`tmpl_…`), o `null`.
    
-   `templateVersionId` string puede ser null
    
    Versión de esa plantilla cuyo layout se aplicó (`tv_…`), o `null`.
    
-   `parentDocumentId` string puede ser null
    
    Documento del que este es un anexo (`doc_…`). `null` si es un documento raíz. Ver `POST /documents/{id}/annexes` y `GET /documents/{id}/family`.
    
-   `createdAt` string (fecha-hora ISO 8601) requerido
    
    Fecha de creación (ISO 8601).
    
-   `updatedAt` string (fecha-hora ISO 8601) requerido
    
    Última actualización (ISO 8601).
    

**El objeto Document**

```
{
  "livemode": false,
  "id": "doc_fdde14eeff0b4444acec4d6b10736068",
  "object": "document",
  "name": "Mi primer contrato (sandbox)",
  "status": "completed",
  "documentType": "EDITABLE",
  "signerCount": 1,
  "signedCount": 1,
  "ownerId": "usr_08f394a003014001b429ca03db05b7f7",
  "orgId": "f4d8bad5-5bb0-451c-a917-2ae6b489d38f",
  "folderId": null,
  "expiresAt": null,
  "signingOrder": "parallel",
  "currentStage": null,
  "expirationReminders": null,
  "templateId": null,
  "templateVersionId": null,
  "parentDocumentId": null,
  "createdAt": "2026-07-11T18:01:02.144000Z",
  "updatedAt": "2026-07-11T18:01:05.421000Z"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:19 (hora CDMX) · test `docs-checks-v3/tests/recetas/primer-documento-a-firma.receta.spec.ts`

## List documents

GET `/documents`

Lista tus documentos con paginación por cursor y filtros. Para la página siguiente manda el `nextCursor` de la respuesta como `startingAfter`; para la anterior, el `previousCursor` como `endingBefore`. Los cursores son opacos: el `id` de un documento no sirve como cursor (`400 INVALID_CURSOR`).

#### Parámetros

-   `limit` integer query
    
    Resultados por página (1–100, default `20`).
    
    default 20 · entre 1 y 100
    
-   `startingAfter` string query
    
    Cursor opaco: el `nextCursor` de la página anterior. Devuelve la página que sigue.
    
-   `endingBefore` string query
    
    Cursor opaco: el `previousCursor` de la página actual. Devuelve la página anterior.
    
-   `status` enum query
    
    Filtra por estado: `draft`, `collecting_data`, `awaiting_signatures`, `correcting`, `processing`, `completed`, `expired`, `voided`.
    
    Valores: `draft` `collecting_data` `awaiting_signatures` `correcting` `processing` `completed` `expired` `voided` `error`
    
-   `status[not]` array de enum query
    
    Statuses to hide. Repeat the parameter to hide several, e.g. `?status[not]=voided&status[not]=expired`. Omit to return every status. Documents with no signature state are never hidden. Mutually exclusive with `status`.
    
-   `sort` enum query
    
    Orden. Solo `createdAt` / `updatedAt`, ascendente o descendente con el prefijo `-`. Valores: `createdAt`, `-createdAt`, `updatedAt`, `-updatedAt` (default `-createdAt`). Otro valor es un `422 VALIDATION_ERROR`.
    
    Valores: `createdAt` `-createdAt` `updatedAt` `-updatedAt`
    
-   `scope` enum query
    
    Alcance: `owner` (default), `org`, `tenant`, `accessible`.
    
    Valores: `owner` `org` `tenant` `accessible`
    
-   `folderId` string query
    
    Filtra por carpeta (`fld_…`).
    
-   `templateId` string query
    
    Keep only documents created from this template (`tmpl_…`).
    
-   `search` string query
    
    Búsqueda por texto libre en el nombre (1–255 caracteres).
    
    de 1 a 255 caracteres
    
-   `createdAt[gte]` string (fecha-hora ISO 8601) query
    
    Solo documentos creados en o después de esta fecha (ISO 8601).
    
-   `createdAt[lte]` string (fecha-hora ISO 8601) query
    
    Solo documentos creados en o antes de esta fecha (ISO 8601).
    
-   `includeTotal` boolean query
    
    Si es `true`, la respuesta incluye `totalCount`. Default `false` (más rápido).
    
    default false
    
-   `includeFiledDocuments` boolean query
    
    When false, hides documents the caller has filed into one of their own folders. The auto-created inbox folder does not count as filing. Ignored when `folderId` selects a folder.
    
    default true
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Sobre de paginación por cursor (`object: "list"`) con objetos Document.

Ver los 7 atributos de la respuesta

-   `object` string, siempre "list"
    
    Siempre `"list"`.
    
-   `data` array de objetos requerido
    
    Arreglo de objetos Document.
    
    Ver 20 atributos hijos
    
    -   `data[].livemode` boolean requerido
        
        `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
        
    -   `data[].id` string requerido
        
        ID del documento (`doc_…`).
        
    -   `data[].object` string, siempre "document"
        
        Siempre `"document"`.
        
    -   `data[].name` string requerido
        
        Nombre visible del documento.
        
    -   `data[].status` enum requerido
        
        Estado del ciclo de vida: `draft`, `collecting_data`, `awaiting_signatures`, `correcting`, `processing`, `completed`, `expired`, `voided`, `error`.
        
        Valores: `draft` `collecting_data` `awaiting_signatures` `correcting` `processing` `completed` `expired` `voided` `error`
        
    -   `data[].documentType` string requerido
        
        Token opaco del tipo de documento.
        
    -   `data[].signerCount` integer requerido
        
        Número total de firmantes.
        
    -   `data[].signedCount` integer requerido
        
        Cuántos firmantes ya firmaron.
        
    -   `data[].ownerId` string requerido
        
        Dueño del documento (`usr_…`).
        
    -   `data[].orgId` string puede ser null
        
        Organización del documento (`org_…`).
        
    -   `data[].folderId` string puede ser null
        
        Carpeta que contiene el documento (`fld_…`). Es `null` si el documento no está en ninguna carpeta que esta credencial pueda abrir con `GET /v3/folders/{id}`.
        
    -   `data[].expiresAt` string (fecha-hora ISO 8601) puede ser null
        
        Fecha límite de firma (ISO 8601).
        
    -   `data[].signingOrder` enum
        
        `parallel` o `sequential` (firmantes por etapas con `routingOrder`). Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
        
        Valores: `parallel` `sequential`
        
    -   `data[].currentStage` integer puede ser null
        
        Etapa activa en un documento `sequential` mientras espera firmas; `null` en paralelo o al terminar. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
        
    -   `data[].expirationReminders` array de integer puede ser null
        
        Horas antes del vencimiento en las que se envían recordatorios.
        
    -   `data[].templateId` string puede ser null
        
        Plantilla de la que nació el documento (`tmpl_…`), o `null`.
        
    -   `data[].templateVersionId` string puede ser null
        
        Versión de esa plantilla cuyo layout se aplicó (`tv_…`), o `null`.
        
    -   `data[].parentDocumentId` string puede ser null
        
        Documento del que este es un anexo (`doc_…`). `null` si es un documento raíz. Ver `POST /documents/{id}/annexes` y `GET /documents/{id}/family`.
        
    -   `data[].createdAt` string (fecha-hora ISO 8601) requerido
        
        Fecha de creación (ISO 8601).
        
    -   `data[].updatedAt` string (fecha-hora ISO 8601) requerido
        
        Última actualización (ISO 8601).
        
    
-   `hasMore` boolean requerido
    
    `true` si hay más resultados después de esta página.
    
-   `nextCursor` string puede ser null
    
    Cursor para la siguiente página (pásalo como `startingAfter`).
    
-   `previousCursor` string puede ser null
    
    Cursor para la página anterior (pásalo como `endingBefore`).
    
-   `limit` integer requerido
    
    El límite aplicado a esta página.
    
-   `totalCount` integer puede ser null
    
    Total de coincidencias. Solo se llena cuando pides `includeTotal=true`.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents?limit=2' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents?limit=2', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents?limit=2",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "object": "list",
  "data": [
    {
      "livemode": false,
      "id": "doc_82fa050abbc44b9587b71c8f84e8f923",
      "object": "document",
      "name": "v3audit-ejemplos renombrado",
      "status": "draft",
      "documentType": "EDITABLE",
      "signerCount": 0,
      "signedCount": 0,
      "ownerId": "usr_0f24c8f44ca14ab387cf439de4bab66f",
      "orgId": "d5894966-ea17-4641-85c6-43eab7203145",
      "folderId": null,
      "expiresAt": null,
      "signingOrder": "parallel",
      "currentStage": null,
      "expirationReminders": null,
      "templateId": null,
      "templateVersionId": null,
      "parentDocumentId": null,
      "createdAt": "2026-07-11T18:00:00.000000Z",
      "updatedAt": "2026-07-11T18:00:01.278000Z"
    },
    {
      "livemode": false,
      "id": "doc_8a984914f25548b880c312a7bc855763",
      "object": "document",
      "name": "v3audit-ejemplos anexo",
      "status": "draft",
      "documentType": "EDITABLE",
      "signerCount": 1,
      "signedCount": 0,
      "ownerId": "usr_0f24c8f44ca14ab387cf439de4bab66f",
      "orgId": "d5894966-ea17-4641-85c6-43eab7203145",
      "folderId": null,
      "expiresAt": null,
      "signingOrder": "parallel",
      "currentStage": null,
      "expirationReminders": null,
      "templateId": null,
      "templateVersionId": null,
      "parentDocumentId": "doc_9feee6be06a5489c92590d3bf830768c",
      "createdAt": "2026-07-11T17:59:59.387000Z",
      "updatedAt": "2026-07-11T17:59:59.387000Z"
    }
  ],
  "hasMore": true,
  "nextCursor": "<cursor>",
  "previousCursor": null,
  "limit": 2,
  "totalCount": null
}
```

**Respuesta · 401 · AUTHENTICATION_REQUIRED**

```
{
  "type": "https://allsign.io/developers/docs/errors#AUTHENTICATION_REQUIRED",
  "title": "Authentication required",
  "status": 401,
  "detail": "Provide an API key via Authorization: Bearer $ALLSIGN_API_KEY…",
  "instance": "/v3/documents",
  "code": "AUTHENTICATION_REQUIRED",
  "requestId": "req_b18d2960e68d4135ad139055bdf24f98"
}
```

**Respuesta · 400 · UNSUPPORTED_API_VERSION**

```
{
  "type": "https://allsign.io/developers/docs/errors#UNSUPPORTED_API_VERSION",
  "title": "Unsupported API version",
  "status": 400,
  "detail": "Unknown AllSign-Version '2020-01-01'. Supported: 2026-07-11.",
  "instance": "/v3/documents",
  "code": "UNSUPPORTED_API_VERSION",
  "requestId": "req_bef341c69ac84957ad49e9fc8f4f5a4d"
}
```

**Respuesta · 400 · INVALID_CURSOR**

```
{
  "type": "https://allsign.io/developers/docs/errors#INVALID_CURSOR",
  "title": "Bad Request",
  "status": 400,
  "detail": "The pagination cursor is malformed.",
  "instance": "/v3/documents",
  "code": "INVALID_CURSOR",
  "requestId": "req_631464956abd4a51be5d9580e50e14b8"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Get aggregate statistics

GET `/documents/stats`

Conteos agregados en el mismo `scope` que `GET /documents`. Sin rango de fechas, usa los últimos 365 días por default; `recentCount` siempre son los últimos 7 días **dentro** de esa ventana, no de todo el histórico. No es un objeto recurso (sin `livemode`) — es un resumen, como `List documents` pero contado en vez de listado.

#### Parámetros

-   `scope` enum query
    
    Alcance: `owner` (default), `org`, `tenant`, `accessible`.
    
    Valores: `owner` `org` `tenant` `accessible`
    
-   `createdAt[gte]` string (fecha-hora ISO 8601) query
    
    Solo cuenta documentos creados en o después de esta fecha (ISO 8601).
    
-   `createdAt[lte]` string (fecha-hora ISO 8601) query
    
    Solo cuenta documentos creados en o antes de esta fecha (ISO 8601).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Los 5 conteos agregados.

Ver los 6 atributos de la respuesta

-   `totalDocuments` integer requerido
    
    Total de documentos en el scope pedido.
    
-   `totalCompleted` integer requerido
    
    Documentos con flujo de firma completado.
    
-   `totalPending` integer requerido
    
    Documentos en `awaiting_signatures` o `collecting_data`. No cuenta borradores, anulados ni expirados.
    
-   `totalConfiguring` integer requerido
    
    Documentos en configuración, antes de enviarse.
    
-   `totalError` integer requerido
    
    Documentos cuyo estado de firma es `error` — algo falló procesándolos después de enviarse. No están incluidos en `totalPending`.
    
-   `recentCount` integer requerido
    
    Documentos creados en los últimos 7 días.
    

Errores posibles (problem+json): [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/stats' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/stats', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/stats",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "totalDocuments": 119,
  "totalCompleted": 112,
  "totalPending": 2,
  "totalConfiguring": 2,
  "totalError": 0,
  "recentCount": 119
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Create document

POST `/documents`

Crea un documento a partir de **una plantilla** (`source: "template"`) **o** de un **archivo subido en base64** (`source: "file"`) — nunca ambos. El campo `source` es un discriminador explícito; si lo omites, se infiere de cuál de `templateId` / `file` mandaste, pero cuando lo incluyes **debe coincidir** con el campo presente. Efectos en entorno `live`: consume 1 o más créditos, arranca un workflow de Temporal y sube el archivo a S3. Con una key `test` el documento es `livemode: false` y no factura. Cada firmante toma un **rol** de la plantilla con `roleName` y hereda sus campos; `values` prellena campos del formulario PDF por nombre y `readOnly` lista los que el firmante no puede cambiar (guía [Formularios PDF](https://allsign.io/developers/docs/guides/pdf-forms)). `signingOrder: "sequential"` + `routingOrder` por firmante invita por etapas.

#### Parámetros

-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `source` enum puede ser null
    
    Discriminador: `template`, `file` o `compound`. Opcional (se infiere), pero si lo mandas debe concordar con el campo presente.
    
    Valores: `template` `file` `compound`
    
-   `templateId` string puede ser null
    
    ID de una plantilla existente (`tmpl_…`). Requerido cuando `source` es `template`.
    
-   `templateValues` objeto (llave → valor) puede ser null
    
    Mapa de valores para las variables de la plantilla, con llaves naturales del negocio (ej. `nombre_completo`). Nunca se camelizan.
    
-   `values` objeto (llave → valor) puede ser null
    
    Prellenado de campos del formulario PDF por nombre de campo, para cualquier rol. Los `values` de cada firmante tienen prioridad sobre estos.
    
-   `readOnly` array de string puede ser null
    
    Nombres de campos prellenados que ningún firmante puede cambiar.
    
-   `file` objeto puede ser null
    
    Archivo inline cuando `source` es `file`. Mutuamente exclusivo con `templateId`/`documents`.
    
    Ver 3 atributos hijos
    
    -   `file.content` string requerido
        
        Contenido del archivo codificado en Base64. Máximo 10 MB decodificados.
        
    -   `file.fileType` string
        
        Tipo de archivo. Default `pdf`.
        
        default "pdf"
        
    -   `file.name` string puede ser null
        
        Nombre del archivo (ej. `contrato.pdf`). Se valida contra path traversal.
        
    
-   `documents` array de objetos puede ser null
    
    Expediente compound: 1..N piezas (archivo o plantilla). Mutuamente exclusivo con el `file`/`templateId` de un solo origen. Mismo cerebro que `POST /v2/documents/` con `documents[]`.
    
    Ver 7 atributos hijos
    
    -   `documents[].file` objeto puede ser null
        
        Archivo inline (PDF/DOCX en base64). Mutuamente exclusivo con `templateId`.
        
        Ver 3 atributos hijos
        
        -   `documents[].file.content` string requerido
            
            Contenido del archivo codificado en Base64. Máximo 10 MB decodificados.
            
        -   `documents[].file.fileType` string
            
            Tipo de archivo. Default `pdf`.
            
            default "pdf"
            
        -   `documents[].file.name` string puede ser null
            
            Nombre del archivo (ej. `contrato.pdf`). Se valida contra path traversal.
            
        
    -   `documents[].templateId` string puede ser null
        
        ID de plantilla (`tmpl_…`). Mutuamente exclusivo con `file`.
        
    -   `documents[].templateValues` objeto (llave → valor) puede ser null
        
        Valores owner-fixed para variables de este item (llaves naturales, no camelCase).
        
    -   `documents[].name` string puede ser null
        
        Nombre visible de esta pieza dentro del expediente.
        
        máx. 255 caracteres
        
    -   `documents[].kind` enum
        
        Rol de la pieza: `main`, `attachment` o `cover`.
        
        Valores: `main` `attachment` `cover`
        
        default "main"
        
    -   `documents[].position` integer puede ser null
        
        Orden 1-based de concatenación. Si se omite, se asigna 1..N por índice.
        
        mín. 1
        
    -   `documents[].dedupeScope` enum
        
        `document` comparte variables entre piezas; `pdf` las aísla a este item.
        
        Valores: `document` `pdf`
        
        default "document"
        
    
-   `fields` array de objetos puede ser null
    
    Campos de firma a colocar al crear (`anchorString` o `position`). Cada `email`/`phone` debe coincidir con un `signers[]`. En compound usa `documentPdfPosition` para anclar a una pieza.
    
    Ver 10 atributos hijos
    
    -   `fields[].email` string puede ser null
        
        Correo del firmante (debe coincidir con un `signers[].email`).
        
    -   `fields[].phone` string puede ser null
        
        WhatsApp del firmante (debe coincidir con un `signers[].phone`).
        
    -   `fields[].pageNumber` integer puede ser null
        
        Página 1-based. En anclas, acota la búsqueda a esa página.
        
    -   `fields[].documentPdfPosition` integer puede ser null
        
        Compound: posición 1-based del PDF de `documents[]` al que pertenece este campo.
        
    -   `fields[].anchorString` string puede ser null
        
        Texto ancla en el PDF. Mutuamente exclusivo con `position`.
        
    -   `fields[].anchorHorizontalAlignment` enum
        
        Alineación horizontal sobre el ancla. Ignorado en modo coordenadas.
        
        Valores: `left` `center` `right`
        
        default "left"
        
    -   `fields[].anchorVerticalAlignment` enum
        
        Alineación vertical sobre el ancla. Ignorado en modo coordenadas.
        
        Valores: `top` `center` `bottom`
        
        default "center"
        
    -   `fields[].position` objeto puede ser null
        
        Coordenadas {x,y} en puntos PDF. Mutuamente exclusivo con `anchorString`.
        
        Ver 2 atributos hijos
        
        -   `fields[].position.x` number requerido
            
        -   `fields[].position.y` number requerido
            
        
    -   `fields[].height` number
        
        Alto del campo en puntos. El ancho es 2×.
        
        default 100 · mayor que 0
        
    -   `fields[].includeInAllPages` boolean
        
        Solo modo coordenadas: repetir el campo en todas las páginas.
        
        default false
        
    
-   `sendInvitations` boolean
    
    Si es true, dispara invitaciones al crear (equivale a v2 `config.sendInvitations`). Fuerza `startAtStep=3`.
    
    default false
    
-   `startAtStep` integer
    
    Paso inicial: 1=borrador, 2=campos, 3=esperando firmas (cobra al crear).
    
    default 1 · entre 1 y 3
    
-   `folderId` string puede ser null
    
    Carpeta destino (`fld_…`).
    
-   `ownerEmail` string puede ser null
    
    Dueño del documento (email de un user del tenant). Equivale a v2 `permissions.ownerEmail`.
    
-   `name` string puede ser null
    
    Nombre visible del documento. Si se omite, se deriva de la plantilla o del archivo.
    
-   `signers` array de objetos puede ser null
    
    Firmantes a adjuntar al crear el documento.
    
    Ver 10 atributos hijos
    
    -   `signers[].email` string puede ser null
        
        Correo del firmante. Manda `email` o `phone`, no los dos: cada firmante recibe su invitación por un solo canal (422 `VALIDATION_ERROR` si llegan ambos).
        
    -   `signers[].phone` string puede ser null
        
        Teléfono del firmante (para invitación por WhatsApp). Excluye a `email`: un firmante lleva un solo canal.
        
        máx. 32 caracteres
        
    -   `signers[].name` string puede ser null
        
        Nombre del firmante.
        
        máx. 255 caracteres
        
    -   `signers[].roleName` string puede ser null
        
        Rol semántico del firmante (ej. `proveedor`), usado para auto-asignar variables de plantilla marcadas con ese rol. Opcional — si se omite, las variables deben asignarse manualmente.
        
        máx. 255 caracteres
        
    -   `signers[].values` objeto (llave → valor) puede ser null
        
        Prellenado de campos del formulario PDF por nombre de campo (texto o casilla). Sólo aplica a plantillas PDF con campos; las llaves nunca se camelizan.
        
    -   `signers[].readOnly` array de string puede ser null
        
        Nombres de campos prellenados que el firmante no puede cambiar.
        
    -   `signers[].routingOrder` integer puede ser null
        
        Etapa de firma (1 = primera). Firmantes con el mismo número firman en paralelo. Solo aplica con `signingOrder: "sequential"`. Con `signingOrder: "sequential"` es **obligatorio en todos** los firmantes: si le falta a alguno, la creación se rechaza con 422 `VALIDATION_ERROR` diciendo en cuál falta, en vez de repartir etapas por su cuenta. Dentro del producto un firmante sin número cuenta como etapa 1, pero la API v3 no asume ese default: un `sequential` a medio numerar sería un documento que firma todo el mundo a la vez sin decirlo. Después de crear, la etapa se cambia con `PATCH /v3/documents/{documentId}/signers/{signerId}`. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
        
        mín. 1
        
    -   `signers[].kind` enum
        
        `signer` (default) firma. `carbon_copy` es un observador: nunca firma ni recibe campos, solo los avisos de `events` y, con `capability: notify_and_view`, un enlace de solo lectura. Un observador necesita `email` y no lleva `roleName`, `routingOrder`, `values` ni `readOnly`. Después de crear se administran con `/v3/documents/{documentId}/observers`.
        
        Valores: `signer` `carbon_copy`
        
        default "signer"
        
    -   `signers[].capability` enum puede ser null
        
        Solo observadores: `notify` (default) o `notify_and_view`.
        
        Valores: `notify` `notify_and_view`
        
    -   `signers[].events` array de string puede ser null
        
        Solo observadores: avisos que recibe. `document.completed` (default), `document.expired`, `document.voided`.
        
        máx. 10 elementos
        
    
-   `signatureValidation` objeto puede ser null
    
    Nivel de validez legal (autógrafa/NOM-151/FEA/biometría/videofirma). Por default: solo autógrafa.
    
    Ver 6 atributos hijos
    
    -   `signatureValidation.autografa` boolean
        
        Firma autógrafa (trazo en pantalla).
        
        default true
        
    -   `signatureValidation.nom151` boolean
        
        Constancia de conservación NOM-151.
        
        default false
        
    -   `signatureValidation.fea` boolean
        
        Firma Electrónica Avanzada (FEA/e.firma SAT).
        
        default false
        
    -   `signatureValidation.biometricSignature` boolean
        
        Verificación biométrica (selfie vs. identificación, anti-deepfake).
        
        default false
        
    -   `signatureValidation.idScan` boolean
        
        Escaneo de identificación oficial (INE, pasaporte).
        
        default false
        
    -   `signatureValidation.videofirma` boolean
        
        Graba video del firmante durante el proceso de firma.
        
        default false
        
    
-   `expiresAt` string (fecha-hora ISO 8601) puede ser null
    
    Fecha límite de firma (ISO 8601).
    
-   `mode` enum puede ser null
    
    Pasa `draft` para crear el documento sin cobrar ni enviar invitaciones (fuerza `startAtStep=1`). Si se omite, se conserva el comportamiento actual.
    
    Valores: `draft`
    
-   `signingOrder` enum puede ser null
    
    `parallel` (default): todos los firmantes reciben su invitación a la vez. `sequential`: cada firmante trae `routingOrder` y solo la etapa activa puede firmar; la siguiente se invita cuando la anterior termina. `sequential` exige `routingOrder` en **cada** firmante (422 `VALIDATION_ERROR` si falta alguno) y `parallel` no lo admite en ninguno. El modo no se puede cambiar después; las etapas sí, con `PATCH /v3/documents/{documentId}/signers/{signerId}`. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
    
    Valores: `parallel` `sequential`
    

#### Devuelve

**201** Documento creado (mismo shape que Retrieve document). — [el objeto Document](#objeto-document)

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [402](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [413](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Contrato de servicios (sandbox)",
  "file": {
    "content": "'"$(base64 < contrato.pdf | tr -d '\n')"'",
    "fileType": "pdf",
    "name": "contrato.pdf"
  },
  "signers": [
    {
      "email": "signer-success@sandbox.allsign.io",
      "name": "Ana Torres"
    }
  ]
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';
import { readFileSync } from 'node:fs';

const respuesta = await fetch('https://api.allsign.io/v3/documents', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: 'Contrato de servicios (sandbox)',
        file: {
            content: readFileSync('contrato.pdf').toString('base64'),
            fileType: 'pdf',
            name: 'contrato.pdf',
        },
        signers: [
            {
                email: 'signer-success@sandbox.allsign.io',
                name: 'Ana Torres',
            },
        ],
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import base64
import os
import uuid
from pathlib import Path

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "name": "Contrato de servicios (sandbox)",
        "file": {
            "content": base64.b64encode(Path("contrato.pdf").read_bytes()).decode(),
            "fileType": "pdf",
            "name": "contrato.pdf",
        },
        "signers": [
            {
                "email": "signer-success@sandbox.allsign.io",
                "name": "Ana Torres",
            },
        ],
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 201**

```
{
  "livemode": false,
  "id": "doc_c18e3aaf505d4e8aa839591f6d38f7b9",
  "object": "document",
  "name": "Contrato de servicios (sandbox)",
  "status": "draft",
  "documentType": "EDITABLE",
  "signerCount": 1,
  "signedCount": 0,
  "ownerId": "usr_d6f2ef7bc72d4754940f12e71ad1964f",
  "orgId": "cc2dd4db-c027-496a-924f-bcdbb9b51387",
  "folderId": null,
  "expiresAt": null,
  "signingOrder": "parallel",
  "currentStage": null,
  "expirationReminders": null,
  "templateId": null,
  "templateVersionId": null,
  "parentDocumentId": null,
  "createdAt": "2026-07-11T18:00:00.000000Z",
  "updatedAt": "2026-07-11T18:00:00.000000Z"
}
```

**Respuesta · 422 · VALIDATION_ERROR**

```
{
  "type": "https://allsign.io/developers/docs/errors#VALIDATION_ERROR",
  "title": "Validation failed",
  "status": 422,
  "detail": "The values are not valid. Fix the fields listed in `errors`. You can test a set of values for free with POST /v3/templates/{id}/validate-values.",
  "instance": "/v3/documents",
  "code": "VALIDATION_ERROR",
  "requestId": "req_71750d833b65413ea2c9794e81405461",
  "errors": [
    {
      "field": "templateValues.ciudad_celebracion",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.fecha_celebracion",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.folio_acuerdo",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.jurisdiccion",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.monto_pena",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.monto_pena_letra",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.objeto_relacion",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_a__domicilio",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_a__email",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_a__representante",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_a__rfc",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_a__telefono",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_b__domicilio",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_b__email",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_b__nombre",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_b__representante",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_b__rfc",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.parte_b__telefono",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.tipo_informacion_confidencial",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.vigencia",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    },
    {
      "field": "templateValues.vigencia_post_terminacion",
      "code": "MISSING_REQUIRED_VARIABLE",
      "detail": "This required variable is missing. Send it with a non-empty value."
    }
  ]
}
```

**Respuesta · 404 · TEMPLATE_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#TEMPLATE_NOT_FOUND",
  "title": "Template not found",
  "status": 404,
  "detail": "Template not found or has been deleted.",
  "instance": "/v3/documents",
  "code": "TEMPLATE_NOT_FOUND",
  "requestId": "req_252364b6627a443285dda69be2eb4213"
}
```

**Respuesta · 409 · IDEMPOTENCY_KEY_REUSED**

```
{
  "type": "https://allsign.io/developers/docs/errors#IDEMPOTENCY_KEY_REUSED",
  "title": "Idempotency key reused",
  "status": 409,
  "detail": "This Idempotency-Key was already used with a different request.",
  "instance": "/v3/documents",
  "code": "IDEMPOTENCY_KEY_REUSED",
  "requestId": "req_7a71eb8164e14a01a6760499df342f6f"
}
```

**Respuesta · 413 · DOCUMENT_TOO_LARGE**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_TOO_LARGE",
  "title": "Request Entity Too Large",
  "status": 413,
  "detail": "The file (10.0 MB decoded) exceeds the 10 MB limit for source=file.",
  "instance": "/v3/documents",
  "code": "DOCUMENT_TOO_LARGE",
  "requestId": "req_96b273bd7e82482aa0d45651aeb4631c"
}
```

**Respuesta · 422 · TEMPLATE_ENDPOINT_REQUIRED**

```
{
  "type": "https://allsign.io/developers/docs/errors#TEMPLATE_ENDPOINT_REQUIRED",
  "title": "Template endpoint required",
  "status": 422,
  "detail": "Esta plantilla firma en orden y esta ruta no aplica su orden de firma: el documento nacería con todos los firmantes a la vez. Créalo con POST /v3/templates/tmpl_30cc50acf8d447c285146e8992ba3dc4/documents. No se creó ningún documento.",
  "instance": "/v3/documents",
  "code": "TEMPLATE_ENDPOINT_REQUIRED",
  "requestId": "req_9e0b14b183204b34b6c451acc11c8f23",
  "templateId": "tmpl_30cc50acf8d447c285146e8992ba3dc4"
}
```

**Respuesta · 409 · IDEMPOTENCY_KEY_IN_PROGRESS**

```
{
  "type": "https://allsign.io/developers/docs/errors#IDEMPOTENCY_KEY_IN_PROGRESS",
  "title": "Conflict",
  "status": 409,
  "detail": "A request with this Idempotency-Key is still in progress.",
  "instance": "/v3/documents",
  "code": "IDEMPOTENCY_KEY_IN_PROGRESS",
  "requestId": "req_2e344a0ea69a46418d8a96c1de58ba64",
  "retryAfter": 2
}
```

**Respuesta · 400 · IDEMPOTENCY_KEY_REQUIRED**

```
{
  "type": "https://allsign.io/developers/docs/errors#IDEMPOTENCY_KEY_REQUIRED",
  "title": "Bad Request",
  "status": 400,
  "detail": "POST requests that create or charge require a unique Idempotency-Key (UUID v4).",
  "instance": "/v3/documents",
  "code": "IDEMPOTENCY_KEY_REQUIRED",
  "requestId": "req_48ab6b50c363414c8d0e41850d05d5f5"
}
```

**Respuesta · 400 · IDEMPOTENCY_KEY_INVALID**

```
{
  "type": "https://allsign.io/developers/docs/errors#IDEMPOTENCY_KEY_INVALID",
  "title": "Bad Request",
  "status": 400,
  "detail": "Idempotency-Key must be a UUID v4.",
  "instance": "/v3/documents",
  "code": "IDEMPOTENCY_KEY_INVALID",
  "requestId": "req_e289ae908d284f7bbbdfc6abc2178d32"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:14 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/errores.ejemplos.spec.ts`

## Retrieve document

GET `/documents/{document_id}`

Consulta un documento por su `id`. `folderId` es la carpeta (`fld_…`) donde está el documento, y es `null` si no está en una carpeta que tu key pueda abrir con `GET /v3/folders/{id}`.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `expand` string query
    
    Lista separada por comas de sub-recursos a expandir en línea. Si se omite, la respuesta trae solo los campos del propio documento.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** El objeto Document. — [el objeto Document](#objeto-document)

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_fdde14eeff0b4444acec4d6b10736068' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_fdde14eeff0b4444acec4d6b10736068', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_fdde14eeff0b4444acec4d6b10736068",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "id": "doc_fdde14eeff0b4444acec4d6b10736068",
  "object": "document",
  "name": "Mi primer contrato (sandbox)",
  "status": "completed",
  "documentType": "EDITABLE",
  "signerCount": 1,
  "signedCount": 1,
  "ownerId": "usr_08f394a003014001b429ca03db05b7f7",
  "orgId": "f4d8bad5-5bb0-451c-a917-2ae6b489d38f",
  "folderId": null,
  "expiresAt": null,
  "signingOrder": "parallel",
  "currentStage": null,
  "expirationReminders": null,
  "templateId": null,
  "templateVersionId": null,
  "parentDocumentId": null,
  "createdAt": "2026-07-11T18:01:02.144000Z",
  "updatedAt": "2026-07-11T18:01:05.421000Z"
}
```

**Respuesta · 400 · INVALID_ID**

```
{
  "type": "https://allsign.io/developers/docs/errors#INVALID_ID",
  "title": "Malformed identifier",
  "status": 400,
  "detail": "Invalid document id.",
  "instance": "/v3/documents/doc_contrato-de-renta",
  "code": "INVALID_ID",
  "requestId": "req_4b48db5236a44765a71ce07ab8cf59ac"
}
```

**Respuesta · 400 · INVALID_EXPAND**

```
{
  "type": "https://allsign.io/developers/docs/errors#INVALID_EXPAND",
  "title": "Bad Request",
  "status": 400,
  "detail": "Unknown expand path(s): firmantes.",
  "instance": "/v3/documents/doc_8434c2beca964c7b959f96e5bbc4d1b3",
  "code": "INVALID_EXPAND",
  "requestId": "req_2042308d311a44c693926d1a9b56dea3"
}
```

**Respuesta · 400 · EXPAND_DEPTH_EXCEEDED**

```
{
  "type": "https://allsign.io/developers/docs/errors#EXPAND_DEPTH_EXCEEDED",
  "title": "Bad Request",
  "status": 400,
  "detail": "At most 3 expand paths are allowed.",
  "instance": "/v3/documents/doc_8434c2beca964c7b959f96e5bbc4d1b3",
  "code": "EXPAND_DEPTH_EXCEEDED",
  "requestId": "req_df05e47a00434d8db363f5efdbd30f97"
}
```

**Respuesta · 404 · DOCUMENT_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_NOT_FOUND",
  "title": "Document not found",
  "status": 404,
  "detail": "No document was found with that id.",
  "instance": "/v3/documents/doc_dd56d81575b84eb790373c6dff92cb95",
  "code": "DOCUMENT_NOT_FOUND",
  "requestId": "req_c72bfc8e0f1f4fc69bcc8111e77dc52d"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:14 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/errores.ejemplos.spec.ts`

## Update document

PATCH `/documents/{document_id}`

Merge-patch parcial: solo se modifican los campos que envías. Los únicos campos mutables son `name` y `folderId`. `folderId: "fld_…"` mueve el documento a esa carpeta; `folderId: null` lo saca de su carpeta. Enviar cualquier otro campo (`status`, `ownerId`, `id`, `createdAt`, …) se rechaza al parsear con **422 `VALIDATION_ERROR`** nombrando el campo ofensor — así se protege un campo inmutable.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `name` string puede ser null
    
    Nuevo nombre visible del documento.
    
-   `folderId` string puede ser null
    
    Mover a otra carpeta (`fld_…`), o `null` para sacarlo de la carpeta.
    

#### Devuelve

**200** El objeto Document actualizado. — [el objeto Document](#objeto-document)

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X PATCH 'https://api.allsign.io/v3/documents/doc_ec50be6599c04f82a3d8bba51b5cbb24' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Content-Type: application/json" \
  -d '{
  "folderId": "fld_c1c3fb2ea6634f929addda83f073a00c"
}'
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_ec50be6599c04f82a3d8bba51b5cbb24', {
    method: 'PATCH',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        folderId: 'fld_c1c3fb2ea6634f929addda83f073a00c',
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.patch(
    "https://api.allsign.io/v3/documents/doc_ec50be6599c04f82a3d8bba51b5cbb24",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
    json={
        "folderId": "fld_c1c3fb2ea6634f929addda83f073a00c",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "id": "doc_ec50be6599c04f82a3d8bba51b5cbb24",
  "object": "document",
  "name": "v3audit-ejemplos documento en carpeta",
  "status": "draft",
  "documentType": "EDITABLE",
  "signerCount": 0,
  "signedCount": 0,
  "ownerId": "usr_beadaffd52b943749b179fded8733b31",
  "orgId": "6332dfb0-7654-42fb-8d21-16dcecdee536",
  "folderId": "fld_c1c3fb2ea6634f929addda83f073a00c",
  "expiresAt": null,
  "signingOrder": "parallel",
  "currentStage": null,
  "expirationReminders": null,
  "templateId": null,
  "templateVersionId": null,
  "parentDocumentId": null,
  "createdAt": "2026-07-11T17:59:58.914000Z",
  "updatedAt": "2026-07-11T18:00:01.675000Z"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/carpetas.ejemplos.spec.ts`

## Send document

POST `/documents/{document_id}/send`

Cobra los créditos, avanza el estado del documento y despacha las invitaciones de firma (email o WhatsApp vía Temporal) a los firmantes que adjuntaste al crearlo. `recipients` es opcional y solo sirve para invitar a **algunos** de esos firmantes, nombrándolos por su `email` o su `phone`: no agrega personas. Si alguno no es firmante del documento, la respuesta es `422 RECIPIENT_NOT_SIGNER` y no se cobra ni se invita a nadie. `Idempotency-Key` es obligatoria: repetir con la misma llave devuelve la respuesta original sin cobrar ni invitar otra vez. Un `send` nuevo sobre un documento que ya está en firma no vuelve a cobrar y solo invita a quien no tiene una invitación vigente (y, en orden secuencial, a quien ya le toca); para insistirle a quien ya la tiene usa Remind signer (uno cada 4 horas). Un documento anulado o expirado responde `409 DOCUMENT_NOT_SENDABLE`.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `recipients` array de objetos puede ser null
    
    Firmantes del documento a quienes invitar, por su correo o su teléfono. Cada uno tiene que ser un firmante ya adjunto: si alguno no lo es, la respuesta es 422 `RECIPIENT_NOT_SIGNER` y no se cobra ni se invita a nadie. Si se omite, se usan los firmantes ya adjuntos que siguen pendientes de firma. En un documento en `collecting_data` o `awaiting_signatures`, repetir `send` solo invita a quien no tiene una liga vigente (sin revocar ni vencida); para recordarle a quien ya la tiene usa `remindSigner`. En `correcting`, `send` vuelve a invitar a todos los pendientes.
    
    Ver 3 atributos hijos
    
    -   `recipients[].email` string puede ser null
        
        Correo del destinatario.
        
    -   `recipients[].phone` string puede ser null
        
        Teléfono del destinatario (invitación por WhatsApp).
        
    -   `recipients[].name` string puede ser null
        
        Nombre del destinatario.
        
    

#### Devuelve

**200** El Document; su `status` avanza (típicamente a `awaiting_signatures`). — [el objeto Document](#objeto-document)

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [402](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors) [503](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/send' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/send', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({}),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/send",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={},
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "id": "doc_c18e3aaf505d4e8aa839591f6d38f7b9",
  "object": "document",
  "name": "Contrato de servicios (sandbox)",
  "status": "completed",
  "documentType": "EDITABLE",
  "signerCount": 1,
  "signedCount": 1,
  "ownerId": "usr_d6f2ef7bc72d4754940f12e71ad1964f",
  "orgId": "cc2dd4db-c027-496a-924f-bcdbb9b51387",
  "folderId": null,
  "expiresAt": null,
  "signingOrder": "parallel",
  "currentStage": null,
  "expirationReminders": null,
  "templateId": null,
  "templateVersionId": null,
  "parentDocumentId": null,
  "createdAt": "2026-07-11T18:00:00.000000Z",
  "updatedAt": "2026-07-11T18:00:01.978000Z"
}
```

**Respuesta · 409 · DOCUMENT_NOT_SENDABLE**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_NOT_SENDABLE",
  "title": "Conflict",
  "status": 409,
  "detail": "The document requires handwritten signatures (signatureValidation.autografa=true) but has no signature fields placed, so it cannot be sent for signing. Place at least one signature field before sending.",
  "instance": "/v3/documents/doc_82fa050abbc44b9587b71c8f84e8f923/send",
  "code": "DOCUMENT_NOT_SENDABLE",
  "requestId": "req_fdb94dfd9e8e41809ba7db813e2097e4",
  "reason": "The document requires handwritten signatures (signatureValidation.autografa=true) but has no signature fields placed, so it cannot be sent for signing. Place at least one signature field before sending."
}
```

**Respuesta · 422 · SIGNING_ORDER_INCOMPLETE**

```
{
  "type": "https://allsign.io/developers/docs/errors#SIGNING_ORDER_INCOMPLETE",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "Every signer is in the same stage, so signing in order would behave exactly like signing all at once. Use signingOrder 'parallel' or spread the signers across different stages.",
  "instance": "/v3/documents/doc_2d02df9682eb4daa89e1dcf73635d684/send",
  "code": "SIGNING_ORDER_INCOMPLETE",
  "requestId": "req_977bab702af14b0790961d843440acd6",
  "problems": [
    "Every signer is in the same stage, so signing in order would behave exactly like signing all at once. Use signingOrder 'parallel' or spread the signers across different stages."
  ],
  "reason": "single_stage"
}
```

**Respuesta · 422 · RECIPIENT_NOT_SIGNER**

```
{
  "type": "https://allsign.io/developers/docs/errors#RECIPIENT_NOT_SIGNER",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "These recipients are not signers of this document: maria@ejemplo.com. Attach signers with `signers[]` when you create the document.",
  "instance": "/v3/documents/doc_966231febee54daeb77ff684f988b07b/send",
  "code": "RECIPIENT_NOT_SIGNER",
  "requestId": "req_381f6083e0434eebb1fba906d993129d",
  "errors": [
    {
      "field": "recipients[0].email",
      "code": "NOT_A_SIGNER",
      "detail": "maria@ejemplo.com is not a signer of this document."
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Void document

POST `/documents/{document_id}/void`

Anula (invalida) un documento. **No es un DELETE**: la retención NOM-151 conserva el registro, por eso anular es una operación explícita que deja el documento en `voided`. Puedes incluir una `reason` opcional. Una anulación legítima puede cancelar cero firmas — el resultado se decide por el `status`, no por cuántas firmas se cancelaron.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `reason` string puede ser null
    
    Motivo de la anulación (queda en la bitácora del documento).
    

#### Devuelve

**200** El Document; su `status` queda en `voided`. — [el objeto Document](#objeto-document)

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/void' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Se firmará otra versión con el monto corregido"
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/void', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        reason: 'Se firmará otra versión con el monto corregido',
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/void",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "reason": "Se firmará otra versión con el monto corregido",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "id": "doc_d0a1551c68d6457294e702fb25d07e4e",
  "object": "document",
  "name": "Contrato de arrendamiento — Ana Torres",
  "status": "voided",
  "documentType": "EDITABLE",
  "signerCount": 1,
  "signedCount": 0,
  "ownerId": "usr_024a2896938b4a6d81723e882bd556a9",
  "orgId": "f2cfe411-e1ac-4881-bf0c-a252d08e423a",
  "folderId": null,
  "expiresAt": null,
  "signingOrder": "parallel",
  "currentStage": null,
  "expirationReminders": null,
  "templateId": null,
  "templateVersionId": null,
  "parentDocumentId": null,
  "createdAt": "2026-07-11T17:59:57.129000Z",
  "updatedAt": "2026-07-11T18:00:17.507000Z"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:16 (hora CDMX) · test `docs-checks-v3/tests/recetas/anula-recuerda-reasigna.receta.spec.ts`

## List signers

GET `/documents/{document_id}/signers`

Lista los firmantes de un documento. Es una colección acotada (no paginada por cursor).

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Colección acotada (`object: "list"`, `hasMore` siempre `false`) con los firmantes.

Ver los 6 atributos de la respuesta

-   `object` string, siempre "list"
    
    Siempre `"list"`.
    
-   `data` array de objetos requerido
    
    Arreglo de firmantes del documento.
    
    Ver 11 atributos hijos
    
    -   `data[].livemode` boolean requerido
        
        `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
        
    -   `data[].id` string requerido
        
        ID del firmante (`sgr_…`).
        
    -   `data[].object` string, siempre "signer"
        
        Siempre `"signer"`.
        
    -   `data[].documentId` string requerido
        
        Documento al que pertenece (`doc_…`).
        
    -   `data[].email` string puede ser null
        
        Correo del firmante.
        
    -   `data[].phone` string puede ser null
        
        Teléfono del firmante.
        
    -   `data[].name` string puede ser null
        
        Nombre del firmante.
        
    -   `data[].status` enum requerido
        
        Estado por firmante: `pending`, `sent`, `signed`, `cancelled`, `waiting_turn`.
        
        Valores: `pending` `sent` `signed` `cancelled` `waiting_turn`
        
    -   `data[].signedAt` string (fecha-hora ISO 8601) puede ser null
        
        Momento de la firma (ISO 8601), o `null` si aún no firma.
        
    -   `data[].routingOrder` integer puede ser null
        
        Etapa de firma en un documento `sequential`; `null` en paralelo. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
        
    -   `data[].delivery` objeto puede ser null
        
        Entrega de la última invitación vigente (no revocada). `null` si no hay nada rastreado: invitaciones por correo sin rebote, anteriores al seguimiento, o un firmante recién reasignado.
        
        Ver 5 atributos hijos
        
        -   `data[].delivery.channel` enum requerido
            
            Canal de la última invitación: `whatsapp` o `email`.
            
            Valores: `whatsapp` `email`
            
        -   `data[].delivery.status` enum requerido
            
            Estado de entrega según el proveedor: `sent`, `delivered`, `read` o `failed`. En correo solo se informa `failed` (rebote).
            
            Valores: `sent` `delivered` `read` `failed`
            
        -   `data[].delivery.reason` enum puede ser null
            
            Por qué falló, en un catálogo estable de AllSign: `provider_payment_issue`, `undeliverable`, `bounced` u `other`. `null` si no falló.
            
            Valores: `provider_payment_issue` `undeliverable` `bounced` `other`
            
        -   `data[].delivery.providerCode` integer puede ser null
            
            Código de error original del proveedor (p. ej. de WhatsApp), o `null`.
            
        -   `data[].delivery.updatedAt` string (fecha-hora ISO 8601) requerido
            
            Momento del último cambio de estado (ISO 8601).
            
        
    
-   `hasMore` boolean
    
    Siempre `false` en esta colección acotada.
    
    default false
    
-   `nextCursor` null
    
    Siempre `null` — esta colección no pagina.
    
-   `previousCursor` null
    
    Siempre `null` — esta colección no pagina.
    
-   `limit` null
    
    Siempre `null` — sin parámetro `limit` en este endpoint.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "object": "list",
  "data": [
    {
      "livemode": false,
      "id": "sgr_80189c3a228a438cbb36757ed5f4738c",
      "object": "signer",
      "documentId": "doc_d0a1551c68d6457294e702fb25d07e4e",
      "email": "signer-pending@sandbox.allsign.io",
      "phone": null,
      "name": "Ana Torres",
      "status": "sent",
      "signedAt": null,
      "routingOrder": null,
      "delivery": null
    }
  ],
  "hasMore": false,
  "nextCursor": null,
  "previousCursor": null,
  "limit": null
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:16 (hora CDMX) · test `docs-checks-v3/tests/recetas/anula-recuerda-reasigna.receta.spec.ts`

## Change a signer's stage

PATCH `/documents/{document_id}/signers/{signer_id}`

Mueve a un firmante de etapa en un documento `sequential`, sin tocar su identidad ni sus campos: mismo `sgr_…`, mismo contacto, mismos campos colocados — sólo cambia cuándo le toca firmar. La etapa activa es la más baja que todavía tiene firmantes pendientes, y se recalcula en el momento: adelantar a alguien a la etapa activa lo invita de inmediato, y sacar de la etapa activa al último pendiente cierra esa etapa e invita a la siguiente. Por eso la respuesta trae el `status` ya recalculado (`waiting_turn` si quedó detrás de la etapa activa). Se rechaza con **409** en tres casos, cada uno con su `reason`: el firmante ya firmó y su etapa es historia (`already_signed`); el documento firma en paralelo (`document_not_sequential` — `signingOrder` no se puede cambiar después de crear); o ese firmante no tiene un rol propio al que colgarle la etapa y cuenta siempre como etapa 1 (`signer_without_role`, que se resuelve volviendo a crear el documento con todos los firmantes numerados). Disponible sólo si el orden de firma está habilitado en el entorno; si no, sobre un documento en paralelo responde 403 `SEQUENTIAL_NOT_AVAILABLE` en vez del 409 `document_not_sequential`. Para cambiar a la persona detrás del lugar, usa `POST /v3/documents/{documentId}/signers/{signerId}/reassign`.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `signer_id` string ruta requerido
    
    ID del firmante (`sgr_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `routingOrder` integer requerido
    
    Nueva etapa de firma del firmante (1 = primera). Los firmantes que comparten número firman a la vez; la siguiente etapa se invita sola cuando la anterior termina de firmar, así que mover a alguien puede abrir o cerrar una etapa al instante. Sólo aplica a documentos creados con `signingOrder: "sequential"` (en uno `parallel` la petición se rechaza con **409**, o con 403 `SEQUENTIAL_NOT_AVAILABLE` si el orden de firma no está habilitado en el entorno), y sólo mientras ese firmante no haya firmado (**409** si ya firmó). El número es obligatorio: la v3 no acepta "quitarle" la etapa a un firmante. Dentro del producto un firmante sin número cuenta como etapa 1, pero en esta API el orden siempre va escrito.
    
    mín. 1
    

#### Devuelve

**200** El firmante con su etapa nueva y su `status` ya recalculado (`waiting_turn` si quedó detrás de la etapa activa).

Ver los 11 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `id` string requerido
    
    ID del firmante (`sgr_…`).
    
-   `object` string, siempre "signer"
    
    Siempre `"signer"`.
    
-   `documentId` string requerido
    
    Documento al que pertenece (`doc_…`).
    
-   `email` string puede ser null
    
    Correo del firmante.
    
-   `phone` string puede ser null
    
    Teléfono del firmante.
    
-   `name` string puede ser null
    
    Nombre del firmante.
    
-   `status` enum requerido
    
    Estado por firmante: `pending`, `sent`, `signed`, `cancelled`, `waiting_turn`.
    
    Valores: `pending` `sent` `signed` `cancelled` `waiting_turn`
    
-   `signedAt` string (fecha-hora ISO 8601) puede ser null
    
    Momento de la firma (ISO 8601), o `null` si aún no firma.
    
-   `routingOrder` integer puede ser null
    
    Etapa de firma en un documento `sequential`; `null` en paralelo. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
    
-   `delivery` objeto puede ser null
    
    Entrega de la última invitación vigente (no revocada). `null` si no hay nada rastreado: invitaciones por correo sin rebote, anteriores al seguimiento, o un firmante recién reasignado.
    
    Ver 5 atributos hijos
    
    -   `delivery.channel` enum requerido
        
        Canal de la última invitación: `whatsapp` o `email`.
        
        Valores: `whatsapp` `email`
        
    -   `delivery.status` enum requerido
        
        Estado de entrega según el proveedor: `sent`, `delivered`, `read` o `failed`. En correo solo se informa `failed` (rebote).
        
        Valores: `sent` `delivered` `read` `failed`
        
    -   `delivery.reason` enum puede ser null
        
        Por qué falló, en un catálogo estable de AllSign: `provider_payment_issue`, `undeliverable`, `bounced` u `other`. `null` si no falló.
        
        Valores: `provider_payment_issue` `undeliverable` `bounced` `other`
        
    -   `delivery.providerCode` integer puede ser null
        
        Código de error original del proveedor (p. ej. de WhatsApp), o `null`.
        
    -   `delivery.updatedAt` string (fecha-hora ISO 8601) requerido
        
        Momento del último cambio de estado (ISO 8601).
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X PATCH 'https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/signers/sgr_0dcad5b836254b2791fab1bb6e6995f2' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Content-Type: application/json" \
  -d '{
  "routingOrder": 3
}'
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/signers/sgr_0dcad5b836254b2791fab1bb6e6995f2', {
    method: 'PATCH',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        routingOrder: 3,
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.patch(
    "https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/signers/sgr_0dcad5b836254b2791fab1bb6e6995f2",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
    json={
        "routingOrder": 3,
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "id": "sgr_0dcad5b836254b2791fab1bb6e6995f2",
  "object": "signer",
  "documentId": "doc_cb8538f977be47d597896fd6a71f8f17",
  "email": "ana@ejemplo.com",
  "phone": null,
  "name": "Ana Torres",
  "status": "waiting_turn",
  "signedAt": null,
  "routingOrder": 3,
  "delivery": null
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## List document fields

GET `/documents/{document_id}/fields`

El estado de cada campo del formulario de un documento: `role` y `signerId` (quién debe llenarlo), `value` (texto o casilla), `readOnly` (prellenado que el firmante no puede cambiar), `status` (`pending` hasta que su firmante firma), y la procedencia del valor: `filledBy` (`owner` si lo puso el emisor por API o desde el panel, `signer` si lo puso el firmante dueño) y `filledAt`. Es la llamada para volcar lo capturado a tu sistema cuando el documento se completa.

#### Parámetros

-   `document_id` string ruta requerido
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Colección acotada con todos los campos del documento y `unassignedCount`.

Ver los 6 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "list"
    
    Siempre `"list"`.
    
-   `documentId` string requerido
    
    El documento dueño de los campos (`doc_…`).
    
-   `data` array de objetos requerido
    
    Campos del documento.
    
    Ver 22 atributos hijos
    
    -   `data[].id` string requerido
        
        ID del campo (`fie_…`).
        
    -   `data[].object` string, siempre "document\_field"
        
        Siempre `"document_field"`.
        
    -   `data[].name` string requerido
        
        Nombre del campo (igual al widget del PDF).
        
    -   `data[].type` enum requerido
        
        Tipo de campo.
        
        Valores: `text` `date` `checkbox` `radio` `select` `signature` `initials` `stamp`
        
    -   `data[].role` string puede ser null
        
        Rol dueño, o `null` si nadie lo ha reclamado.
        
    -   `data[].signerId` string puede ser null
        
        Firmante (`sgr_…`) que lo llena, si el rol ya tiene firmante.
        
    -   `data[].required` boolean
        
        Si debe llenarse antes de firmar.
        
        default true
        
    -   `data[].label` string puede ser null
        
        Etiqueta que ve el firmante.
        
    -   `data[].options` array de string puede ser null
        
        Opciones de `select` / `radio`.
        
    -   `data[].group` string puede ser null
        
        Grupo de exclusión mutua.
        
    -   `data[].source` enum puede ser null
        
        De dónde nació el campo.
        
        Valores: `acroform` `drawn` `template`
        
    -   `data[].readOnly` boolean
        
        Prellenado por el emisor y bloqueado para el firmante.
        
        default false
        
    -   `data[].fixedWidth` boolean
        
        Ancho fijo: si el texto no cabe, el campo no se alarga y se encoge la letra (mínimo 6 pt).
        
        default false
        
    -   `data[].placeholder` string puede ser null
        
        Texto de ejemplo que ve el firmante en el campo vacío, o `null` si no tiene.
        
    -   `data[].maxLength` integer puede ser null
        
        Cuántos caracteres admite el campo, o `null` si no tiene límite.
        
    -   `data[].page` integer requerido
        
        Página 1-based.
        
        mín. 1
        
    -   `data[].rect` objeto requerido
        
        Rectángulo en % del papel.
        
        Ver 4 atributos hijos
        
        -   `data[].rect.x` number requerido
            
            X izquierdo, porcentaje del ancho de la página.
            
            entre 0 y 100
            
        -   `data[].rect.y` number requerido
            
            Y superior, porcentaje del alto de la página.
            
            entre 0 y 100
            
        -   `data[].rect.width` number requerido
            
            Ancho en porcentaje de la página.
            
            entre 0 y 100
            
        -   `data[].rect.height` number requerido
            
            Alto en porcentaje de la página.
            
            entre 0 y 100
            
        
    -   `data[].position` integer
        
        Posición del PDF dentro del documento (compuestos).
        
        default 1 · mín. 1
        
    -   `data[].status` enum requerido
        
        `pending` hasta que su firmante firma.
        
        Valores: `pending` `signed`
        
    -   `data[].value` objeto requerido
        
        Valor actual del campo.
        
        Ver 2 atributos hijos
        
        -   `data[].value.text` string puede ser null
            
            Valor de texto / fecha (`YYYY-MM-DD`) / opción elegida.
            
        -   `data[].value.checked` boolean puede ser null
            
            Estado de una casilla.
            
        
    -   `data[].filledBy` enum puede ser null
        
        Quién puso el valor: `owner` (el emisor, por API o dashboard) o `signer` (el firmante dueño, ver `signerId`). `null` si nadie lo ha llenado.
        
        Valores: `owner` `signer`
        
    -   `data[].filledAt` string (fecha-hora ISO 8601) puede ser null
        
        Cuándo se puso el valor (ISO 8601); `null` si nadie lo ha llenado.
        
    
-   `unassignedCount` integer requerido
    
    Cuántos campos no tienen rol todavía.
    
    mín. 0
    
-   `hasMore` boolean
    
    Siempre `false` en esta colección acotada.
    
    default false
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "list",
  "documentId": "doc_6c14cce88de246d4b322520d14f4b07f",
  "data": [
    {
      "id": "fie_c0d65ee73b7344c1a476f6a5ddbcf075",
      "object": "document_field",
      "name": "nombre",
      "type": "text",
      "role": "Cliente",
      "signerId": "sgr_0bc65682c186474ca97666dfdba23652",
      "required": true,
      "label": "Nombre",
      "options": null,
      "group": null,
      "source": "template",
      "readOnly": false,
      "fixedWidth": false,
      "placeholder": null,
      "maxLength": null,
      "page": 1,
      "rect": {
        "x": 8.1699,
        "y": 10.101,
        "width": 40.8497,
        "height": 3.0303
      },
      "position": 1,
      "status": "pending",
      "value": {
        "text": null,
        "checked": null
      },
      "filledBy": null,
      "filledAt": null
    },
    {
      "id": "fie_3ed740f6c7c04e19b014c89aea51fb9d",
      "object": "document_field",
      "name": "rfc",
      "type": "text",
      "role": "Cliente",
      "signerId": "sgr_0bc65682c186474ca97666dfdba23652",
      "required": true,
      "label": "Rfc",
      "options": null,
      "group": null,
      "source": "template",
      "readOnly": true,
      "fixedWidth": false,
      "placeholder": null,
      "maxLength": null,
      "page": 1,
      "rect": {
        "x": 8.1699,
        "y": 15.1515,
        "width": 40.8497,
        "height": 3.0303
      },
      "position": 1,
      "status": "pending",
      "value": {
        "text": "XAXX010101000",
        "checked": null
      },
      "filledBy": "owner",
      "filledAt": "2026-07-11T18:00:00.000000Z"
    },
    {
      "id": "fie_c23f9b44ff2e46ee8201519babdc80ba",
      "object": "document_field",
      "name": "fecha",
      "type": "date",
      "role": "Cliente",
      "signerId": "sgr_0bc65682c186474ca97666dfdba23652",
      "required": true,
      "label": "Fecha",
      "options": null,
      "group": null,
      "source": "template",
      "readOnly": false,
      "fixedWidth": false,
      "placeholder": null,
      "maxLength": null,
      "page": 1,
      "rect": {
        "x": 8.1699,
        "y": 20.202,
        "width": 40.8497,
        "height": 3.0303
      },
      "position": 1,
      "status": "pending",
      "value": {
        "text": null,
        "checked": null
      },
      "filledBy": null,
      "filledAt": null
    },
    {
      "id": "fie_911a1cdb1f7e422da4cd55c8ae1e200a",
      "object": "document_field",
      "name": "acepta",
      "type": "checkbox",
      "role": "Cliente",
      "signerId": "sgr_0bc65682c186474ca97666dfdba23652",
      "required": false,
      "label": "Acepta",
      "options": null,
      "group": null,
      "source": "template",
      "readOnly": false,
      "fixedWidth": false,
      "placeholder": null,
      "maxLength": null,
      "page": 1,
      "rect": {
        "x": 8.1699,
        "y": 25.2525,
        "width": 3.5948,
        "height": 2.7778
      },
      "position": 1,
      "status": "pending",
      "value": {
        "text": null,
        "checked": null
      },
      "filledBy": null,
      "filledAt": null
    },
    {
      "id": "fie_10706806e45d4618804a9e5979cc904d",
      "object": "document_field",
      "name": "firma_cliente",
      "type": "signature",
      "role": "Cliente",
      "signerId": "sgr_0bc65682c186474ca97666dfdba23652",
      "required": true,
      "label": null,
      "options": null,
      "group": null,
      "source": "template",
      "readOnly": false,
      "fixedWidth": false,
      "placeholder": null,
      "maxLength": null,
      "page": 1,
      "rect": {
        "x": 8.1699,
        "y": 39.1414,
        "width": 40.8497,
        "height": 7.5758
      },
      "position": 1,
      "status": "pending",
      "value": {
        "text": null,
        "checked": null
      },
      "filledBy": null,
      "filledAt": null
    }
  ],
  "unassignedCount": 0,
  "hasMore": false
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/campos.ejemplos.spec.ts`

## Create document field

POST `/documents/{document_id}/fields`

Agrega un campo a un documento que todavía no se envía. Igual que en plantillas: `type`, `page`, `rect` (en % del papel), `role` (se crea si no existe), `required`, `label`, `options`, `group`. Puedes mandar tu propio `id` (`fie_…`) para crearlo de forma idempotente, o `aliasOf` para que comparta valor con otro campo del mismo nombre.

#### Parámetros

-   `document_id` string ruta requerido
    
-   `Idempotency-Key` string header
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `id` string puede ser null
    
    ID (`fie_…`) elegido por el cliente para crear de forma idempotente; si falta, lo asigna AllSign.
    
-   `type` enum requerido
    
    Tipo de campo.
    
    Valores: `text` `date` `checkbox` `radio` `select` `signature` `initials` `stamp`
    
-   `page` integer requerido
    
    Página 1-based dentro del PDF elegido.
    
    mín. 1
    
-   `rect` objeto requerido
    
    Rectángulo en % del papel.
    
    Ver 4 atributos hijos
    
    -   `rect.x` number requerido
        
        X izquierdo, porcentaje del ancho de la página.
        
        entre 0 y 100
        
    -   `rect.y` number requerido
        
        Y superior, porcentaje del alto de la página.
        
        entre 0 y 100
        
    -   `rect.width` number requerido
        
        Ancho en porcentaje de la página.
        
        entre 0 y 100
        
    -   `rect.height` number requerido
        
        Alto en porcentaje de la página.
        
        entre 0 y 100
        
    
-   `documentPdfId` string puede ser null
    
    El PDF del documento que recibe el campo (compuestos). Forma preferida: es estable aunque el documento se reordene. Requerido si el documento tiene más de un PDF y no mandas `position`.
    
-   `position` integer puede ser null
    
    Alias heredado de `documentPdfId`: posición 1-based del PDF dentro del documento. Frágil — cambia si el documento se reordena. Usa `documentPdfId` cuando puedas.
    
    mín. 1
    
-   `name` string puede ser null
    
    Nombre del campo; se genera si falta.
    
    máx. 120 caracteres
    
-   `aliasOf` string puede ser null
    
    Nombre de un campo existente: este hueco comparte su valor.
    
    máx. 120 caracteres
    
-   `role` string puede ser null
    
    Rol dueño (se crea si no existe).
    
    máx. 120 caracteres
    
-   `signer` string puede ser null
    
    Firmante dueño (`sgr_…`). El campo hereda el rol de ese firmante; no lo combines con `role`.
    
-   `required` boolean
    
    Si es obligatorio.
    
    default true
    
-   `label` string puede ser null
    
    Etiqueta para el firmante.
    
    máx. 200 caracteres
    
-   `options` array de string puede ser null
    
    Opciones de `select` / `radio`.
    
-   `group` string puede ser null
    
    Grupo de exclusión mutua.
    
    máx. 120 caracteres
    
-   `fixedWidth` boolean puede ser null
    
    Ancho fijo: si el texto no cabe, el campo no se alarga y se encoge la letra (mínimo 6 pt).
    
-   `placeholder` string puede ser null
    
    Texto de ejemplo que ve el firmante en el campo vacío. Solo campos de texto; en fecha, casilla y firma se ignora.
    
    máx. 200 caracteres
    
-   `maxLength` integer puede ser null
    
    Cuántos caracteres admite el campo (1 a 500). Solo campos de texto; en fecha, casilla y firma se ignora.
    
    entre 1 y 500
    

#### Devuelve

**201** El campo creado.

Ver los 22 atributos de la respuesta

-   `id` string requerido
    
    ID del campo (`fie_…`).
    
-   `object` string, siempre "document\_field"
    
    Siempre `"document_field"`.
    
-   `name` string requerido
    
    Nombre del campo (igual al widget del PDF).
    
-   `type` enum requerido
    
    Tipo de campo.
    
    Valores: `text` `date` `checkbox` `radio` `select` `signature` `initials` `stamp`
    
-   `role` string puede ser null
    
    Rol dueño, o `null` si nadie lo ha reclamado.
    
-   `signerId` string puede ser null
    
    Firmante (`sgr_…`) que lo llena, si el rol ya tiene firmante.
    
-   `required` boolean
    
    Si debe llenarse antes de firmar.
    
    default true
    
-   `label` string puede ser null
    
    Etiqueta que ve el firmante.
    
-   `options` array de string puede ser null
    
    Opciones de `select` / `radio`.
    
-   `group` string puede ser null
    
    Grupo de exclusión mutua.
    
-   `source` enum puede ser null
    
    De dónde nació el campo.
    
    Valores: `acroform` `drawn` `template`
    
-   `readOnly` boolean
    
    Prellenado por el emisor y bloqueado para el firmante.
    
    default false
    
-   `fixedWidth` boolean
    
    Ancho fijo: si el texto no cabe, el campo no se alarga y se encoge la letra (mínimo 6 pt).
    
    default false
    
-   `placeholder` string puede ser null
    
    Texto de ejemplo que ve el firmante en el campo vacío, o `null` si no tiene.
    
-   `maxLength` integer puede ser null
    
    Cuántos caracteres admite el campo, o `null` si no tiene límite.
    
-   `page` integer requerido
    
    Página 1-based.
    
    mín. 1
    
-   `rect` objeto requerido
    
    Rectángulo en % del papel.
    
    Ver 4 atributos hijos
    
    -   `rect.x` number requerido
        
        X izquierdo, porcentaje del ancho de la página.
        
        entre 0 y 100
        
    -   `rect.y` number requerido
        
        Y superior, porcentaje del alto de la página.
        
        entre 0 y 100
        
    -   `rect.width` number requerido
        
        Ancho en porcentaje de la página.
        
        entre 0 y 100
        
    -   `rect.height` number requerido
        
        Alto en porcentaje de la página.
        
        entre 0 y 100
        
    
-   `position` integer
    
    Posición del PDF dentro del documento (compuestos).
    
    default 1 · mín. 1
    
-   `status` enum requerido
    
    `pending` hasta que su firmante firma.
    
    Valores: `pending` `signed`
    
-   `value` objeto requerido
    
    Valor actual del campo.
    
    Ver 2 atributos hijos
    
    -   `value.text` string puede ser null
        
        Valor de texto / fecha (`YYYY-MM-DD`) / opción elegida.
        
    -   `value.checked` boolean puede ser null
        
        Estado de una casilla.
        
    
-   `filledBy` enum puede ser null
    
    Quién puso el valor: `owner` (el emisor, por API o dashboard) o `signer` (el firmante dueño, ver `signerId`). `null` si nadie lo ha llenado.
    
    Valores: `owner` `signer`
    
-   `filledAt` string (fecha-hora ISO 8601) puede ser null
    
    Cuándo se puso el valor (ISO 8601); `null` si nadie lo ha llenado.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "telefono",
  "type": "text",
  "page": 1,
  "rect": {
    "x": 10,
    "y": 80,
    "width": 30,
    "height": 4
  },
  "role": "Cliente",
  "required": false
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: 'telefono',
        type: 'text',
        page: 1,
        rect: {
            x: 10,
            y: 80,
            width: 30,
            height: 4,
        },
        role: 'Cliente',
        required: false,
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "name": "telefono",
        "type": "text",
        "page": 1,
        "rect": {
            "x": 10,
            "y": 80,
            "width": 30,
            "height": 4,
        },
        "role": "Cliente",
        "required": False,
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 201**

```
{
  "id": "fie_5670d7b1d4b343209afb35164c4de9ce",
  "object": "document_field",
  "name": "telefono",
  "type": "text",
  "role": "Cliente",
  "signerId": "sgr_0bc65682c186474ca97666dfdba23652",
  "required": false,
  "label": null,
  "options": null,
  "group": null,
  "source": "drawn",
  "readOnly": false,
  "fixedWidth": false,
  "placeholder": null,
  "maxLength": null,
  "page": 1,
  "rect": {
    "x": 10,
    "y": 80,
    "width": 30,
    "height": 4
  },
  "position": 1,
  "status": "pending",
  "value": {
    "text": null,
    "checked": null
  },
  "filledBy": null,
  "filledAt": null
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/campos.ejemplos.spec.ts`

## Update document field

PATCH `/documents/{document_id}/fields/{field_id}`

Mueve, renombra, reasigna o configura un campo — y **prellena**: `value` (texto, fecha `YYYY-MM-DD` o `true`/`false` para casillas) deja el valor puesto por el emisor (`filledBy: "owner"`); `readOnly: true` lo bloquea para que el firmante lo vea pero no lo cambie. Un campo ya firmado no se puede tocar: responde 409 `FIELD_CONFLICT`.

#### Parámetros

-   `document_id` string ruta requerido
    
-   `field_id` string ruta requerido
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `name` string puede ser null
    
    Nuevo nombre (renombra sus huecos hermanos).
    
    de 1 a 120 caracteres
    
-   `page` integer puede ser null
    
    Nueva página 1-based.
    
    mín. 1
    
-   `rect` objeto puede ser null
    
    Nuevo rectángulo.
    
    Ver 4 atributos hijos
    
    -   `rect.x` number requerido
        
        X izquierdo, porcentaje del ancho de la página.
        
        entre 0 y 100
        
    -   `rect.y` number requerido
        
        Y superior, porcentaje del alto de la página.
        
        entre 0 y 100
        
    -   `rect.width` number requerido
        
        Ancho en porcentaje de la página.
        
        entre 0 y 100
        
    -   `rect.height` number requerido
        
        Alto en porcentaje de la página.
        
        entre 0 y 100
        
    
-   `role` string puede ser null
    
    Nuevo rol (`null` lo deja sin rol).
    
    máx. 120 caracteres
    
-   `signer` string puede ser null
    
    Nuevo firmante dueño (`sgr_…`); el campo hereda su rol. `null` lo deja sin dueño. No lo combines con `role`.
    
-   `required` boolean puede ser null
    
    Si es obligatorio.
    
-   `label` string puede ser null
    
    Etiqueta para el firmante.
    
    máx. 200 caracteres
    
-   `options` array de string puede ser null
    
    Opciones.
    
-   `group` string puede ser null
    
    Grupo.
    
    máx. 120 caracteres
    
-   `value` string o boolean puede ser null
    
    Prellenar (texto o casilla).
    
-   `readOnly` boolean puede ser null
    
    Bloquear el valor prellenado para el firmante.
    
-   `fixedWidth` boolean puede ser null
    
    Ancho fijo (`true`) o que el campo se alargue con el texto (`false`).
    
-   `placeholder` string puede ser null
    
    Texto de ejemplo, solo en campos de texto; se comparte con los huecos del mismo nombre. Vacío o `null` lo quita.
    
    máx. 200 caracteres
    
-   `maxLength` integer puede ser null
    
    Cuántos caracteres admite (1 a 500), solo en campos de texto; se comparte con los huecos del mismo nombre. `null` quita el límite. Un valor ya guardado más largo no se recorta.
    
    entre 1 y 500
    

#### Devuelve

**200** El campo ya actualizado, con `value`, `filledBy` y `filledAt`.

Ver los 22 atributos de la respuesta

-   `id` string requerido
    
    ID del campo (`fie_…`).
    
-   `object` string, siempre "document\_field"
    
    Siempre `"document_field"`.
    
-   `name` string requerido
    
    Nombre del campo (igual al widget del PDF).
    
-   `type` enum requerido
    
    Tipo de campo.
    
    Valores: `text` `date` `checkbox` `radio` `select` `signature` `initials` `stamp`
    
-   `role` string puede ser null
    
    Rol dueño, o `null` si nadie lo ha reclamado.
    
-   `signerId` string puede ser null
    
    Firmante (`sgr_…`) que lo llena, si el rol ya tiene firmante.
    
-   `required` boolean
    
    Si debe llenarse antes de firmar.
    
    default true
    
-   `label` string puede ser null
    
    Etiqueta que ve el firmante.
    
-   `options` array de string puede ser null
    
    Opciones de `select` / `radio`.
    
-   `group` string puede ser null
    
    Grupo de exclusión mutua.
    
-   `source` enum puede ser null
    
    De dónde nació el campo.
    
    Valores: `acroform` `drawn` `template`
    
-   `readOnly` boolean
    
    Prellenado por el emisor y bloqueado para el firmante.
    
    default false
    
-   `fixedWidth` boolean
    
    Ancho fijo: si el texto no cabe, el campo no se alarga y se encoge la letra (mínimo 6 pt).
    
    default false
    
-   `placeholder` string puede ser null
    
    Texto de ejemplo que ve el firmante en el campo vacío, o `null` si no tiene.
    
-   `maxLength` integer puede ser null
    
    Cuántos caracteres admite el campo, o `null` si no tiene límite.
    
-   `page` integer requerido
    
    Página 1-based.
    
    mín. 1
    
-   `rect` objeto requerido
    
    Rectángulo en % del papel.
    
    Ver 4 atributos hijos
    
    -   `rect.x` number requerido
        
        X izquierdo, porcentaje del ancho de la página.
        
        entre 0 y 100
        
    -   `rect.y` number requerido
        
        Y superior, porcentaje del alto de la página.
        
        entre 0 y 100
        
    -   `rect.width` number requerido
        
        Ancho en porcentaje de la página.
        
        entre 0 y 100
        
    -   `rect.height` number requerido
        
        Alto en porcentaje de la página.
        
        entre 0 y 100
        
    
-   `position` integer
    
    Posición del PDF dentro del documento (compuestos).
    
    default 1 · mín. 1
    
-   `status` enum requerido
    
    `pending` hasta que su firmante firma.
    
    Valores: `pending` `signed`
    
-   `value` objeto requerido
    
    Valor actual del campo.
    
    Ver 2 atributos hijos
    
    -   `value.text` string puede ser null
        
        Valor de texto / fecha (`YYYY-MM-DD`) / opción elegida.
        
    -   `value.checked` boolean puede ser null
        
        Estado de una casilla.
        
    
-   `filledBy` enum puede ser null
    
    Quién puso el valor: `owner` (el emisor, por API o dashboard) o `signer` (el firmante dueño, ver `signerId`). `null` si nadie lo ha llenado.
    
    Valores: `owner` `signer`
    
-   `filledAt` string (fecha-hora ISO 8601) puede ser null
    
    Cuándo se puso el valor (ISO 8601); `null` si nadie lo ha llenado.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X PATCH 'https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields/fie_5670d7b1d4b343209afb35164c4de9ce' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Content-Type: application/json" \
  -d '{
  "value": "5555550101",
  "readOnly": true
}'
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields/fie_5670d7b1d4b343209afb35164c4de9ce', {
    method: 'PATCH',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        value: '5555550101',
        readOnly: true,
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.patch(
    "https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields/fie_5670d7b1d4b343209afb35164c4de9ce",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
    json={
        "value": "5555550101",
        "readOnly": True,
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "id": "fie_5670d7b1d4b343209afb35164c4de9ce",
  "object": "document_field",
  "name": "telefono",
  "type": "text",
  "role": "Cliente",
  "signerId": "sgr_0bc65682c186474ca97666dfdba23652",
  "required": false,
  "label": null,
  "options": null,
  "group": null,
  "source": "drawn",
  "readOnly": true,
  "fixedWidth": false,
  "placeholder": null,
  "maxLength": null,
  "page": 1,
  "rect": {
    "x": 10,
    "y": 80,
    "width": 30,
    "height": 4
  },
  "position": 1,
  "status": "pending",
  "value": {
    "text": "5555550101",
    "checked": null
  },
  "filledBy": "owner",
  "filledAt": "2026-07-11T18:00:01.615000Z"
}
```

**Respuesta · 409 · DOCUMENT_CONFLICT**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_CONFLICT",
  "title": "Conflict",
  "status": 409,
  "detail": "Este documento ya terminó (ANULADO): sus campos ya no se pueden crear, mover, reasignar ni borrar.",
  "instance": "/v3/documents/doc_6b7fc763d2bc430980ae397679f7a465/fields/fie_fb20c7c439fc4902b6b6bbc9bbca55cc",
  "code": "DOCUMENT_CONFLICT",
  "requestId": "req_55b09c55654746338f3f811e0ced82a7",
  "reason": "document_terminal"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/campos.ejemplos.spec.ts`

## Delete document field

DELETE `/documents/{document_id}/fields/{field_id}`

Quita un campo del documento. Un campo ya firmado no se puede borrar (409 `FIELD_CONFLICT`).

#### Parámetros

-   `document_id` string ruta requerido
    
-   `field_id` string ruta requerido
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**204** Campo eliminado.

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X DELETE 'https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields/fie_5670d7b1d4b343209afb35164c4de9ce' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields/fie_5670d7b1d4b343209afb35164c4de9ce', {
    method: 'DELETE',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status);
```

**Python**

```
import os

import requests

respuesta = requests.delete(
    "https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields/fie_5670d7b1d4b343209afb35164c4de9ce",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code)
```

**Respuesta · 204**

*Sin cuerpo.*

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/campos.ejemplos.spec.ts`

## Assign fields to a role

POST `/documents/{document_id}/fields:assign-role`

Asigna varios campos a un rol de una sola vez (o `role: null` para dejarlos sin rol). Si el rol ya tiene firmante, los campos pasan a ese firmante en el mismo paso. Un campo ya firmado responde 409.

#### Parámetros

-   `document_id` string ruta requerido
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `fieldIds` array de string requerido
    
    Campos (`fie_…`) a reasignar.
    
    mín. 1 elementos
    
-   `role` string puede ser null
    
    Rol destino; `null` los deja sin rol.
    
    máx. 120 caracteres
    
-   `signer` string puede ser null
    
    Firmante destino (`sgr_…`); los campos heredan su rol. Manda `role` o `signer`, no ambos.
    

#### Devuelve

**200** Cuántos campos cambiaron y cómo quedaron.

Ver los 5 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "document\_fields\_assignment"
    
-   `documentId` string requerido
    
    El documento (`doc_…`).
    
-   `updated` integer requerido
    
    Cuántos campos cambiaron de rol.
    
    mín. 0
    
-   `data` array de objetos requerido
    
    Los campos ya reasignados.
    
    Ver 22 atributos hijos
    
    -   `data[].id` string requerido
        
        ID del campo (`fie_…`).
        
    -   `data[].object` string, siempre "document\_field"
        
        Siempre `"document_field"`.
        
    -   `data[].name` string requerido
        
        Nombre del campo (igual al widget del PDF).
        
    -   `data[].type` enum requerido
        
        Tipo de campo.
        
        Valores: `text` `date` `checkbox` `radio` `select` `signature` `initials` `stamp`
        
    -   `data[].role` string puede ser null
        
        Rol dueño, o `null` si nadie lo ha reclamado.
        
    -   `data[].signerId` string puede ser null
        
        Firmante (`sgr_…`) que lo llena, si el rol ya tiene firmante.
        
    -   `data[].required` boolean
        
        Si debe llenarse antes de firmar.
        
        default true
        
    -   `data[].label` string puede ser null
        
        Etiqueta que ve el firmante.
        
    -   `data[].options` array de string puede ser null
        
        Opciones de `select` / `radio`.
        
    -   `data[].group` string puede ser null
        
        Grupo de exclusión mutua.
        
    -   `data[].source` enum puede ser null
        
        De dónde nació el campo.
        
        Valores: `acroform` `drawn` `template`
        
    -   `data[].readOnly` boolean
        
        Prellenado por el emisor y bloqueado para el firmante.
        
        default false
        
    -   `data[].fixedWidth` boolean
        
        Ancho fijo: si el texto no cabe, el campo no se alarga y se encoge la letra (mínimo 6 pt).
        
        default false
        
    -   `data[].placeholder` string puede ser null
        
        Texto de ejemplo que ve el firmante en el campo vacío, o `null` si no tiene.
        
    -   `data[].maxLength` integer puede ser null
        
        Cuántos caracteres admite el campo, o `null` si no tiene límite.
        
    -   `data[].page` integer requerido
        
        Página 1-based.
        
        mín. 1
        
    -   `data[].rect` objeto requerido
        
        Rectángulo en % del papel.
        
        Ver 4 atributos hijos
        
        -   `data[].rect.x` number requerido
            
            X izquierdo, porcentaje del ancho de la página.
            
            entre 0 y 100
            
        -   `data[].rect.y` number requerido
            
            Y superior, porcentaje del alto de la página.
            
            entre 0 y 100
            
        -   `data[].rect.width` number requerido
            
            Ancho en porcentaje de la página.
            
            entre 0 y 100
            
        -   `data[].rect.height` number requerido
            
            Alto en porcentaje de la página.
            
            entre 0 y 100
            
        
    -   `data[].position` integer
        
        Posición del PDF dentro del documento (compuestos).
        
        default 1 · mín. 1
        
    -   `data[].status` enum requerido
        
        `pending` hasta que su firmante firma.
        
        Valores: `pending` `signed`
        
    -   `data[].value` objeto requerido
        
        Valor actual del campo.
        
        Ver 2 atributos hijos
        
        -   `data[].value.text` string puede ser null
            
            Valor de texto / fecha (`YYYY-MM-DD`) / opción elegida.
            
        -   `data[].value.checked` boolean puede ser null
            
            Estado de una casilla.
            
        
    -   `data[].filledBy` enum puede ser null
        
        Quién puso el valor: `owner` (el emisor, por API o dashboard) o `signer` (el firmante dueño, ver `signerId`). `null` si nadie lo ha llenado.
        
        Valores: `owner` `signer`
        
    -   `data[].filledAt` string (fecha-hora ISO 8601) puede ser null
        
        Cuándo se puso el valor (ISO 8601); `null` si nadie lo ha llenado.
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields:assign-role' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Content-Type: application/json" \
  -d '{
  "fieldIds": [
    "fie_5670d7b1d4b343209afb35164c4de9ce"
  ],
  "role": null
}'
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields:assign-role', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        fieldIds: [
            'fie_5670d7b1d4b343209afb35164c4de9ce',
        ],
        role: null,
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_6c14cce88de246d4b322520d14f4b07f/fields:assign-role",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
    json={
        "fieldIds": [
            "fie_5670d7b1d4b343209afb35164c4de9ce",
        ],
        "role": None,
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "document_fields_assignment",
  "documentId": "doc_6c14cce88de246d4b322520d14f4b07f",
  "updated": 1,
  "data": [
    {
      "id": "fie_5670d7b1d4b343209afb35164c4de9ce",
      "object": "document_field",
      "name": "telefono",
      "type": "text",
      "role": null,
      "signerId": null,
      "required": false,
      "label": null,
      "options": null,
      "group": null,
      "source": "drawn",
      "readOnly": true,
      "fixedWidth": false,
      "placeholder": null,
      "maxLength": null,
      "page": 1,
      "rect": {
        "x": 10,
        "y": 80,
        "width": 30,
        "height": 4
      },
      "position": 1,
      "status": "pending",
      "value": {
        "text": "5555550101",
        "checked": null
      },
      "filledBy": "owner",
      "filledAt": "2026-07-11T18:00:01.615000Z"
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/campos.ejemplos.spec.ts`

## List document roles

GET `/documents/{document_id}/roles`

Los roles del documento, en orden, con cuántos campos le pertenecen a cada uno (`fieldCount`) y quién lo ocupa (`signerId`, o `null` si nadie lo ha tomado). En un documento `sequential` cada rol trae su etapa (`stage`); en paralelo, `null`. El `id` (`rol_…`) es estable aunque renombres el rol, y es el que usa `DELETE /documents/{id}/roles/{roleId}`.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Los roles del documento.

Ver los 5 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "list"
    
    Siempre `"list"`.
    
-   `documentId` string requerido
    
    El documento dueño de los roles (`doc_…`).
    
-   `data` array de objetos requerido
    
    Roles del documento, en orden.
    
    Ver 7 atributos hijos
    
    -   `data[].object` string, siempre "document\_role"
        
        Siempre `"document_role"`.
        
    -   `data[].id` string requerido
        
        Id del rol (`rol_…`), estable aunque lo renombres.
        
    -   `data[].name` string requerido
        
        Nombre del rol, tal como lo traen los campos en su `role`.
        
    -   `data[].kind` string
        
        Papel del participante (token opaco): `signer`, `witness`, `notary`, `carbon_copy`, `approver` o `in_person_signer`.
        
        default "signer"
        
    -   `data[].stage` integer puede ser null
        
        Etapa de firma (1 = primera). `null` en orden paralelo. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
        
        mín. 1
        
    -   `data[].fieldCount` integer requerido
        
        Cuántos campos del documento le pertenecen.
        
        mín. 0
        
    -   `data[].signerId` string puede ser null
        
        Firmante que lo ocupa (`sgr_…`), o `null` si nadie lo ha tomado.
        
    
-   `hasMore` boolean
    
    Siempre `false` en esta colección acotada.
    
    default false
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/roles' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/roles', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/roles",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "list",
  "documentId": "doc_cb8538f977be47d597896fd6a71f8f17",
  "data": [
    {
      "object": "document_role",
      "id": "rol_187ecb9317994c59ac5b7c4b53483bd5",
      "name": "Cliente",
      "kind": "signer",
      "stage": 1,
      "fieldCount": 1,
      "signerId": "sgr_f2f4eea4da414a38a7aeec6c22ba4bf1"
    },
    {
      "object": "document_role",
      "id": "rol_ba9ece92ec6045afab273dd78ee02d76",
      "name": "Director",
      "kind": "signer",
      "stage": 2,
      "fieldCount": 1,
      "signerId": "sgr_0dcad5b836254b2791fab1bb6e6995f2"
    }
  ],
  "hasMore": false
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Delete a document role

DELETE `/documents/{document_id}/roles/{role_id}`

Borra un rol que **nadie ocupa**. Sus campos y variables no se borran: quedan sin rol, y la respuesta los lista en `unassignedFields` y `unassignedVariables` para que los asignes antes de enviar a firmar. Si el rol ya tiene firmante responde 409 `ROLE_OCCUPIED`: quita primero al firmante y luego el rol.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `role_id` string ruta requerido
    
    ID del rol (`rol_…`), tal como lo devuelve `GET /documents/{id}/roles`.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** El rol borrado, con los campos y variables que quedaron sin rol.

Ver los 7 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "document\_role"
    
    Siempre `"document_role"`.
    
-   `id` string requerido
    
    Id del rol borrado (`rol_…`).
    
-   `name` string requerido
    
    Nombre que tenía el rol.
    
-   `deleted` string, siempre "true"
    
    Siempre `true`.
    
-   `unassignedFields` integer requerido
    
    Campos que quedaron sin rol; asígnalos antes de enviar a firmar.
    
    mín. 0
    
-   `unassignedVariables` integer requerido
    
    Variables que quedaron sin rol.
    
    mín. 0
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X DELETE 'https://api.allsign.io/v3/documents/doc_2abcccc1b53249348a14e6a17c3ebe28/roles/rol_518f1d58084948bfbff538c43b72e996' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_2abcccc1b53249348a14e6a17c3ebe28/roles/rol_518f1d58084948bfbff538c43b72e996', {
    method: 'DELETE',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.delete(
    "https://api.allsign.io/v3/documents/doc_2abcccc1b53249348a14e6a17c3ebe28/roles/rol_518f1d58084948bfbff538c43b72e996",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "document_role",
  "id": "rol_518f1d58084948bfbff538c43b72e996",
  "name": "Cliente",
  "deleted": true,
  "unassignedFields": 1,
  "unassignedVariables": 0
}
```

**Respuesta · 404 · ROLE_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#ROLE_NOT_FOUND",
  "title": "Not Found",
  "status": 404,
  "detail": "Role not found in this document.",
  "instance": "/v3/documents/doc_d60c6183f829411b8d033f2fc4c9477d/roles/rol_1d2abe482f0045a8b0fc16c94d49005f",
  "code": "ROLE_NOT_FOUND",
  "requestId": "req_6724d101e4b248a7bd87d2f7ffd6e6ac"
}
```

**Respuesta · 409 · ROLE_OCCUPIED**

```
{
  "type": "https://allsign.io/developers/docs/errors#ROLE_OCCUPIED",
  "title": "Conflict",
  "status": 409,
  "detail": "Role 'Arrendador' is held by a signer. Remove the signer first, then delete the role.",
  "instance": "/v3/documents/doc_d60c6183f829411b8d033f2fc4c9477d/roles/rol_00823ecb9d294d13869402400226758e",
  "code": "ROLE_OCCUPIED",
  "requestId": "req_8704c255f6cf49999ae7d48dfa1ace21"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:14 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/errores.ejemplos.spec.ts`

## Import signing fields from a document

POST `/documents/{document_id}/fields:from-document`

Copia las cajas de firma (posiciones por rol) de otro documento ya firmado a este documento. Sirve para repetir un layout sin plantilla de por medio. Solo viaja la geometría, convertida a la hoja de este documento; ningún valor del documento origen.

#### Parámetros

-   `document_id` string ruta requerido
    
-   `Idempotency-Key` string header
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `documentId` string puede ser null
    
    Documento (`doc_…`) del que se copian los campos de firma.
    
-   `consolidate` boolean
    
    Si es `true`, consolida campos de documentos comparables al documento destino (mismo origen/plantilla, mismo archivo o mismo hash) en vez de copiar uno solo.
    
    default false
    

#### Devuelve

**200** Los campos del documento después de la copia.

Ver los 7 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "document\_signing\_fields\_import"
    
    Siempre `"document_signing_fields_import"`.
    
-   `documentId` string requerido
    
    El documento destino (`doc_…`).
    
-   `matchedCount` integer requerido
    
    Campos que encajaron al calcular la disposición.
    
    mín. 0
    
-   `totalCount` integer requerido
    
    Campos considerados.
    
    mín. 0
    
-   `unmatched` array de objetos
    
    Campos que no encajaron, con su rol/tipo/página.
    
    Ver 3 atributos hijos
    
    -   `unmatched[].roleName` string requerido
        
        Rol del campo que no encajó.
        
    -   `unmatched[].kind` string requerido
        
        Tipo del campo que no encajó.
        
    -   `unmatched[].page` integer requerido
        
        Página 1-based del campo que no encajó.
        
        mín. 1
        
    
-   `fields` array de objetos
    
    Campos de firma creados en el documento destino (nuevos; los ya existentes no se repiten).
    
    Ver 5 atributos hijos
    
    -   `fields[].id` string requerido
        
        ID del campo de firma creado (`fie_…`).
        
    -   `fields[].roleName` string requerido
        
        Rol al que pertenece el campo.
        
    -   `fields[].kind` string requerido
        
        Tipo de campo: `signature`, `initials`, `name`, `date` o `vobo`.
        
    -   `fields[].page` integer requerido
        
        Página 1-based.
        
        mín. 1
        
    -   `fields[].rect` objeto requerido
        
        Rectángulo del campo, en % del papel.
        
        Ver 4 atributos hijos
        
        -   `fields[].rect.x` number requerido
            
            X izquierdo, porcentaje del ancho de la página.
            
            entre 0 y 100
            
        -   `fields[].rect.y` number requerido
            
            Y superior, porcentaje del alto de la página.
            
            entre 0 y 100
            
        -   `fields[].rect.width` number requerido
            
            Ancho en porcentaje de la página.
            
            entre 0 y 100
            
        -   `fields[].rect.height` number requerido
            
            Alto en porcentaje de la página.
            
            entre 0 y 100
            
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors) [503](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_f4334b6d04314ba99d7c3e974dfd273f/fields:from-document' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "documentId": "doc_b723b46d90a64d309c8a5a0bb747a9a9"
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_f4334b6d04314ba99d7c3e974dfd273f/fields:from-document', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        documentId: 'doc_b723b46d90a64d309c8a5a0bb747a9a9',
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_f4334b6d04314ba99d7c3e974dfd273f/fields:from-document",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "documentId": "doc_b723b46d90a64d309c8a5a0bb747a9a9",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "document_signing_fields_import",
  "documentId": "doc_f4334b6d04314ba99d7c3e974dfd273f",
  "matchedCount": 1,
  "totalCount": 1,
  "unmatched": [],
  "fields": [
    {
      "id": "fie_2e744958f0da493c9d63927e1a9c1fae",
      "roleName": "Cliente",
      "kind": "signature",
      "page": 1,
      "rect": {
        "x": 13.0719,
        "y": 78.2828,
        "width": 32.6797,
        "height": 12.6263
      }
    }
  ]
}
```

**Respuesta · 409 · DOCUMENT_NOT_EDITABLE**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_NOT_EDITABLE",
  "title": "Conflict",
  "status": 409,
  "detail": "This document is already in signing; its fields can no longer be imported.",
  "instance": "/v3/documents/doc_19deea649a6e421585db7e09bdc1faa4/fields:from-document",
  "code": "DOCUMENT_NOT_EDITABLE",
  "requestId": "req_1cd7885fff374f8bb522d76be322ad0e"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Download document file

GET `/documents/{document_id}/file`

El PDF del documento **antes de enviarlo**: con `format=form` conserva los widgets vivos con lo prellenado (para que el emisor lo revise en Acrobat); con `format=flat` lo hornea con los valores actuales. Después de la firma, el PDF con validez legal es la evidencia (`GET /documents/{id}/evidence`).

#### Parámetros

-   `document_id` string ruta requerido
    
-   `format` enum query
    
    `form` (default) conserva los widgets; `flat` los hornea con lo prellenado.
    
    Valores: `form` `flat`
    
    default "form"
    
-   `position` integer query
    
    Posición del PDF dentro de un expediente compuesto (default 1).
    
    default 1 · mín. 1
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** El PDF (`application/pdf`, `Content-Disposition: attachment`).

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/file' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
import { writeFileSync } from 'node:fs';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/file', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
writeFileSync('descarga.pdf', Buffer.from(await respuesta.arrayBuffer()));
```

**Python**

```
import os
from pathlib import Path

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/file",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
Path("descarga.pdf").write_bytes(respuesta.content)
```

**Respuesta · 200**

```
<archivo application/pdf>
```

**Respuesta · 404 · DOCUMENT_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_NOT_FOUND",
  "title": "Document not found",
  "status": 404,
  "detail": "Document not found",
  "instance": "/v3/documents/doc_9c9f2f6749794c8c8717b0fd5458f074/file",
  "code": "DOCUMENT_NOT_FOUND",
  "requestId": "req_9099fea09e7e4822a33e00dde0d7dc14"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:17 (hora CDMX) · test `docs-checks-v3/tests/recetas/descarga-el-pdf-firmado-y-la-evidencia.receta.spec.ts`

## Get document values

GET `/documents/{document_id}/values`

Los valores de las **variables** `{{ }}` de un documento creado desde una plantilla DOCX: los `templateValues` con los que se creó y lo que llenaste después con `PATCH …/values`. Todas las variables las llena el remitente. Para los campos del formulario PDF, que sí llena el firmante, usa `GET …/fields`.

#### Parámetros

-   `document_id` string ruta requerido
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Mapa `nombre → valor` con quién lo llenó.

Ver los 4 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "document\_values"
    
    Siempre `"document_values"`.
    
-   `documentId` string requerido
    
    El documento (`doc_…`).
    
-   `data` array de objetos
    
    Valores actuales del documento.
    
    Ver 2 atributos hijos
    
    -   `data[].name` string requerido
        
        Nombre de la variable — llave natural de `templateValues`, nunca camelizada.
        
    -   `data[].value` string puede ser null
        
        Valor actual, o `null` si aún no se llena.
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_1ce40ec34cf7454e83862318509bef29/values' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_1ce40ec34cf7454e83862318509bef29/values', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_1ce40ec34cf7454e83862318509bef29/values",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "document_values",
  "documentId": "doc_1ce40ec34cf7454e83862318509bef29",
  "data": [
    {
      "name": "comprador_nombre",
      "value": null
    },
    {
      "name": "comprador_rfc",
      "value": null
    },
    {
      "name": "fecha",
      "value": null
    },
    {
      "name": "monto",
      "value": null
    },
    {
      "name": "vendedor_nombre",
      "value": "Ana Martínez"
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:16 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/plantillas.ejemplos.spec.ts`

## Update document values

PATCH `/documents/{document_id}/values`

Escribe valores de variables `{{ }}` en un documento que todavía no se envía (`draft`) y regenera su PDF. Todas las variables las llena el remitente; los valores propuestos al firmante (`proposals`) se retiraron. Una vez enviado, los valores quedan fijos: responde `409 DOCUMENT_CONFLICT` y no cambia nada — excepto en `collecting_data` (variables obligatorias ligadas a un rol de un documento anterior a este cambio, que los firmantes todavía están llenando): ahí solo acepta variables de un firmante (las del dueño responden `409` con `lockedVariables`), y cuando ya están todas el documento pasa a firma. Solo variables; los campos del formulario PDF se prellenan con `PATCH …/fields/{id}` o con `values` al crear.

#### Parámetros

-   `document_id` string ruta requerido
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `values` objeto (llave → valor)
    
    Mapa nombre→valor a fusionar. Las llaves son los `name` de las variables y conservan su forma natural (`nombre_completo`): nunca se camelizan. Un valor de un dato con `slots` se escribe en todos los huecos.
    

#### Devuelve

**200** Los valores ya mezclados.

Ver los 4 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "document\_values"
    
    Siempre `"document_values"`.
    
-   `documentId` string requerido
    
    El documento (`doc_…`).
    
-   `data` array de objetos
    
    Valores actuales del documento.
    
    Ver 2 atributos hijos
    
    -   `data[].name` string requerido
        
        Nombre de la variable — llave natural de `templateValues`, nunca camelizada.
        
    -   `data[].value` string puede ser null
        
        Valor actual, o `null` si aún no se llena.
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X PATCH 'https://api.allsign.io/v3/documents/doc_1ce40ec34cf7454e83862318509bef29/values' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Content-Type: application/json" \
  -d '{
  "values": {
    "comprador_nombre": "Luis Pérez",
    "comprador_rfc": "XAXX010101000"
  }
}'
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_1ce40ec34cf7454e83862318509bef29/values', {
    method: 'PATCH',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        values: {
            comprador_nombre: 'Luis Pérez',
            comprador_rfc: 'XAXX010101000',
        },
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.patch(
    "https://api.allsign.io/v3/documents/doc_1ce40ec34cf7454e83862318509bef29/values",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
    json={
        "values": {
            "comprador_nombre": "Luis Pérez",
            "comprador_rfc": "XAXX010101000",
        },
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "document_values",
  "documentId": "doc_1ce40ec34cf7454e83862318509bef29",
  "data": [
    {
      "name": "comprador_nombre",
      "value": "Luis Pérez"
    },
    {
      "name": "comprador_rfc",
      "value": "XAXX010101000"
    },
    {
      "name": "fecha",
      "value": null
    },
    {
      "name": "monto",
      "value": null
    },
    {
      "name": "vendedor_nombre",
      "value": "Ana Martínez"
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:16 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/plantillas.ejemplos.spec.ts`

## Save the document as a template version

POST `/documents/{document_id}/save-to-template`

Guarda el documento tal como está —campos, roles, variables, orden de firma y ajustes— como una versión nueva de la plantilla. Con `templateId` se agrega una versión a esa plantilla (`created: false`); sin él se crea una plantilla nueva a partir del documento (`created: true`). Las personas se guardan **sólo** con `rememberSigners: true`: sin eso el layout conserva los roles («Parte 1», «Parte 2»…) pero no quién los ocupó. Los valores que llenó el DUEÑO se guardan **sólo** con `rememberFieldValues: true`; lo que llenó un firmante nunca se guarda, tenga este flag el valor que tenga. Un documento con al menos una firma responde 409 `DOCUMENT_ALREADY_SIGNED`. `formView` (`fill` o `edit`) es la vista con la que abrirá el formulario de los documentos que nazcan de la versión, y queda en `layout.settings.formView`. Si se omite, la versión hereda la de la última versión con layout de la plantilla. El documento queda ligado a la plantilla y a la versión guardada, así que `GET /documents/{id}` ya responde con `templateId` y `templateVersionId`.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento a guardar (`doc_…`).
    
-   `Idempotency-Key` string header
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `templateId` string puede ser null
    
    Plantilla a la que se guarda una versión nueva (`tmpl_…`). Si se omite, se crea una plantilla nueva a partir del documento.
    
-   `name` string puede ser null
    
    Nombre de la plantilla nueva. Si se omite, se toma el del documento.
    
-   `rememberSigners` boolean
    
    Si es `true`, el layout guarda a las personas que hoy tienen cada rol para que el siguiente documento nazca con ellas.
    
    default false
    
-   `rememberFieldValues` boolean
    
    Si es `true`, la plantilla guarda los valores que el DUEÑO llenó (campos y variables) como default para el siguiente documento. Nunca guarda lo que llenó un firmante, tenga este flag el valor que tenga.
    
    default false
    
-   `formView` enum puede ser null
    
    Vista del formulario que guarda la versión en `layout.settings.formView`: `fill` (Llenar) o `edit` (Editar campos). Si se omite o es `null`, la versión hereda la de la última versión con layout de la plantilla; si no hay de dónde heredar, queda `null` y el formulario abre en `edit`.
    
    Valores: `fill` `edit`
    

#### Devuelve

**201** La plantilla y la versión guardada, con `created` para saber si la plantilla es nueva.

Ver los 5 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "template\_snapshot"
    
    Siempre `"template_snapshot"`.
    
-   `template` objeto requerido
    
    La plantilla destino.
    
    Ver 2 atributos hijos
    
    -   `template.id` string requerido
        
        La plantilla (`tmpl_…`).
        
    -   `template.name` string requerido
        
        Nombre de la plantilla.
        
    
-   `version` objeto requerido
    
    La versión que se acaba de guardar.
    
    Ver 2 atributos hijos
    
    -   `version.id` string requerido
        
        La versión guardada (`tv_…`).
        
    -   `version.versionNumber` integer requerido
        
        Número de versión guardada.
        
        mín. 1
        
    
-   `created` boolean requerido
    
    `true` si la plantilla se creó en esta llamada; `false` si ya existía.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_b723b46d90a64d309c8a5a0bb747a9a9/save-to-template' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "v3audit-ejemplos plantilla guardada"
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_b723b46d90a64d309c8a5a0bb747a9a9/save-to-template', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: 'v3audit-ejemplos plantilla guardada',
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_b723b46d90a64d309c8a5a0bb747a9a9/save-to-template",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "name": "v3audit-ejemplos plantilla guardada",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 201**

```
{
  "livemode": false,
  "object": "template_snapshot",
  "template": {
    "id": "tmpl_2822486b40e747a5b8110d665fb4454e",
    "name": "v3audit-ejemplos plantilla guardada"
  },
  "version": {
    "id": "tv_2e7ac3c7970443b6ab43e446ca7527e4",
    "versionNumber": 1
  },
  "created": true
}
```

**Respuesta · 409 · DOCUMENT_ALREADY_SIGNED**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_ALREADY_SIGNED",
  "title": "Document already signed",
  "status": 409,
  "detail": "A document with signatures already on it cannot be saved as a template.",
  "instance": "/v3/documents/doc_f225e42012ba44dd853a06e460b02674/save-to-template",
  "code": "DOCUMENT_ALREADY_SIGNED",
  "requestId": "req_6d22adad6f034dcb857a752eed5af7a9"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos-firmados.ejemplos.spec.ts`

## List events

GET `/documents/{document_id}/events`

Lista la bitácora de eventos de un documento (creación, envío, firmas, etc.), paginada por cursor. `type` es un token del catálogo de eventos con namespace punteado `recurso.enPasado` (ej. `document.created`).

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `limit` integer query
    
    Resultados por página (1–100, default `20`).
    
    default 20 · entre 1 y 100
    
-   `startingAfter` string query
    
    Cursor: eventos después de este `id` (`evt_…`).
    
-   `endingBefore` string query
    
    Cursor: eventos antes de este `id` (`evt_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Sobre de paginación por cursor con la bitácora de eventos del documento.

Ver los 6 atributos de la respuesta

-   `object` string, siempre "list"
    
    Siempre `"list"`.
    
-   `data` array de objetos requerido
    
    Arreglo de eventos del documento, más recientes primero.
    
    Ver 11 atributos hijos
    
    -   `data[].livemode` boolean requerido
        
        `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
        
    -   `data[].id` string requerido
        
        ID del evento (`evt_…`).
        
    -   `data[].object` string, siempre "event"
        
        Siempre `"event"`.
        
    -   `data[].type` string requerido
        
        Tipo de evento (ej. `document.created`, `signer.signed`).
        
    -   `data[].documentId` string requerido
        
        Documento asociado (`doc_…`).
        
    -   `data[].success` boolean requerido
        
        Si el evento fue exitoso.
        
    -   `data[].message` string puede ser null
        
        Mensaje legible del evento.
        
    -   `data[].actorType` string puede ser null
        
        Tipo de actor que originó el evento.
        
    -   `data[].signatureId` string puede ser null
        
        Firma asociada (`sgr_…`), si aplica.
        
    -   `data[].data` objeto (llave → valor)
        
        Payload del evento. Solo las llaves de primer nivel se camelizan; los datos anidados quedan intactos.
        
    -   `data[].createdAt` string (fecha-hora ISO 8601) requerido
        
        Momento del evento (ISO 8601).
        
    
-   `hasMore` boolean requerido
    
    `true` si hay más eventos después de esta página.
    
-   `nextCursor` string puede ser null
    
    Cursor para la siguiente página (pásalo como `startingAfter`).
    
-   `previousCursor` string puede ser null
    
    Cursor para la página anterior (pásalo como `endingBefore`).
    
-   `limit` integer requerido
    
    El límite aplicado a esta página.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_e15d0f67a79b4ea788fb7bcbd1a09607/events' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_e15d0f67a79b4ea788fb7bcbd1a09607/events', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_e15d0f67a79b4ea788fb7bcbd1a09607/events",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "object": "list",
  "data": [
    {
      "livemode": false,
      "id": "evt_a7820888aca541eba86deff6a273b819",
      "object": "event",
      "type": "signature.requested",
      "documentId": "doc_e15d0f67a79b4ea788fb7bcbd1a09607",
      "success": true,
      "message": "Invitación enviada a sig***@s***.io",
      "actorType": "user",
      "signatureId": null,
      "data": {
        "channel": "email",
        "isReminder": false,
        "phoneNumber": null,
        "signerEmail": "signer-success@sandbox.allsign.io"
      },
      "createdAt": "2026-07-11T18:00:03.608000Z"
    },
    {
      "livemode": false,
      "id": "evt_c7b0605e3d124e6f95eb01a305af1108",
      "object": "event",
      "type": "signature.consent_given",
      "documentId": "doc_e15d0f67a79b4ea788fb7bcbd1a09607",
      "success": true,
      "message": "sig***@s***.io consintió firmar electrónicamente",
      "actorType": "user",
      "signatureId": "sgr_b256e83390914aba9d8d6ef0c2f3560a",
      "data": {
        "channel": "autografa",
        "userAgent": "allsign-sandbox-autosign",
        "fieldsUpdated": 0,
        "signaturesAdded": 0
      },
      "createdAt": "2026-07-11T17:59:59.966000Z"
    },
    {
      "livemode": false,
      "id": "evt_8a915752dcc04f46b43306adbdb5193f",
      "object": "event",
      "type": "signature.signed",
      "documentId": "doc_e15d0f67a79b4ea788fb7bcbd1a09607",
      "success": true,
      "message": "Documento firmado por sig***@s***.io",
      "actorType": "user",
      "signatureId": "sgr_b256e83390914aba9d8d6ef0c2f3560a",
      "data": {
        "channel": "autografa",
        "userAgent": "allsign-sandbox-autosign",
        "fieldsUpdated": 0,
        "signaturesAdded": 0
      },
      "createdAt": "2026-07-11T17:59:59.966000Z"
    },
    {
      "livemode": false,
      "id": "evt_2022c6518f414336a06b576876d7611a",
      "object": "event",
      "type": "document.created",
      "documentId": "doc_e15d0f67a79b4ea788fb7bcbd1a09607",
      "success": true,
      "message": "Documento creado por ana@ejemplo.com desde API",
      "actorType": "api",
      "signatureId": null,
      "data": {
        "channel": "API",
        "tenantId": "898959ba-7619-4e3b-bc85-04964b7400a3",
        "apiKeyId": "2f5e7098-fc3d-48cc-aa98-50dbf92123ed",
        "userEmail": "ana@ejemplo.com"
      },
      "createdAt": "2026-07-11T17:59:55.661000Z"
    }
  ],
  "hasMore": false,
  "nextCursor": null,
  "previousCursor": null,
  "limit": 20
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos-firmados.ejemplos.spec.ts`

## Get evidence bundle

GET `/documents/{document_id}/evidence`

Los 2 archivos de respaldo de un documento: el PDF sellado con todas las firmas (`evidencePdf`) y la constancia de conservación NOM-151 (`nom151`, `null` si el documento no es `livemode`). Ambos son `null` hasta que **todos** los firmantes completan — el workflow de Temporal que los genera termina unos segundos después de la última firma, así que haz *poll* de `available` en vez de asumir que ya existen justo al completarse el flujo.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** El bundle de evidencia — `available` indica si ya están listos los archivos.

Ver los 8 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `documentId` string requerido
    
    ID del documento (`doc_…`).
    
-   `available` boolean requerido
    
    `true` una vez que todos los firmantes completaron.
    
-   `evidencePdf` objeto puede ser null
    
    PDF sellado con todas las firmas y la bitácora de auditoría.
    
    Ver 2 atributos hijos
    
    -   `evidencePdf.url` string requerido
        
        URL firmada para descargar el archivo (vigente 24 horas).
        
    -   `evidencePdf.sha256` string puede ser null
        
        Hash SHA-256 del archivo, si ya se calculó.
        
    
-   `nom151` objeto puede ser null
    
    Constancia de conservación NOM-151 (timestamp + cadena de hash). `null` si el documento no es `livemode`.
    
    Ver 2 atributos hijos
    
    -   `nom151.url` string requerido
        
        URL firmada para descargar el archivo (vigente 24 horas).
        
    -   `nom151.sha256` string puede ser null
        
        Hash SHA-256 del archivo, si ya se calculó.
        
    
-   `reason` enum puede ser null
    
    Por qué `available` es false: `document_not_signed` (falta firma; no sirve poll-ear), `evidence_generating` (todos firmaron, el PDF se está armando; sí poll-ea), `presigned_url_failed` (el archivo existe pero no se pudo firmar la URL; reintenta).
    
    Valores: `document_not_signed` `evidence_generating` `presigned_url_failed`
    
-   `signedCount` integer
    
    Cuántos firmantes ya firmaron.
    
    default 0
    
-   `totalSigners` integer
    
    Firmantes del documento (incluye pendientes).
    
    default 0
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/evidence' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/evidence', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_c18e3aaf505d4e8aa839591f6d38f7b9/evidence",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "documentId": "doc_c18e3aaf505d4e8aa839591f6d38f7b9",
  "available": true,
  "evidencePdf": {
    "url": "<url-firmada>",
    "sha256": "8a6bf4a711f5204bcce37981400b4a4030d969b33d24e7f2ad78748ca1e68725"
  },
  "nom151": null,
  "reason": null,
  "signedCount": 1,
  "totalSigners": 1
}
```

**Respuesta · 400 · INVALID_ID**

```
{
  "type": "https://allsign.io/developers/docs/errors#INVALID_ID",
  "title": "Malformed identifier",
  "status": 400,
  "detail": "Invalid document id.",
  "instance": "/v3/documents/doc_123/evidence",
  "code": "INVALID_ID",
  "requestId": "req_8a1bc74e22d945a6ad9358d2f8b27ec2"
}
```

**Respuesta · 404 · DOCUMENT_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_NOT_FOUND",
  "title": "Document not found",
  "status": 404,
  "detail": "No document was found with that id.",
  "instance": "/v3/documents/doc_9c9f2f6749794c8c8717b0fd5458f074/evidence",
  "code": "DOCUMENT_NOT_FOUND",
  "requestId": "req_f004c5b00c5e41eba0d4a03491fdf499"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:17 (hora CDMX) · test `docs-checks-v3/tests/recetas/descarga-el-pdf-firmado-y-la-evidencia.receta.spec.ts`

## Attach an annex

POST `/documents/{document_id}/annexes`

Crea un documento **nuevo** —un anexo— colgado de un documento que ya firmaron todos. El cuerpo es el mismo de `POST /documents` (archivo o plantilla, firmantes, campos…) y el anexo tiene su propio ciclo de firma; el original no se toca. La respuesta es el anexo, con `parentDocumentId` apuntando al original. Solo se anexa al documento **raíz**: anexar a un anexo responde 409 `ANNEX_OF_ANNEX_NOT_ALLOWED`, y un documento al que todavía le faltan firmas, 409 `DOCUMENT_NOT_FULLY_SIGNED`. `Idempotency-Key` obligatoria: un reintento con la misma llave devuelve el mismo anexo en vez de crear otro. Para ver el original con todos sus anexos usa `GET /documents/{id}/family`.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento original, ya firmado por todos (`doc_…`).
    
-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `source` enum puede ser null
    
    Discriminador: `template`, `file` o `compound`. Opcional (se infiere), pero si lo mandas debe concordar con el campo presente.
    
    Valores: `template` `file` `compound`
    
-   `templateId` string puede ser null
    
    ID de una plantilla existente (`tmpl_…`). Requerido cuando `source` es `template`.
    
-   `templateValues` objeto (llave → valor) puede ser null
    
    Mapa de valores para las variables de la plantilla, con llaves naturales del negocio (ej. `nombre_completo`). Nunca se camelizan.
    
-   `values` objeto (llave → valor) puede ser null
    
    Prellenado de campos del formulario PDF por nombre de campo, para cualquier rol. Los `values` de cada firmante tienen prioridad sobre estos.
    
-   `readOnly` array de string puede ser null
    
    Nombres de campos prellenados que ningún firmante puede cambiar.
    
-   `file` objeto puede ser null
    
    Archivo inline cuando `source` es `file`. Mutuamente exclusivo con `templateId`/`documents`.
    
    Ver 3 atributos hijos
    
    -   `file.content` string requerido
        
        Contenido del archivo codificado en Base64. Máximo 10 MB decodificados.
        
    -   `file.fileType` string
        
        Tipo de archivo. Default `pdf`.
        
        default "pdf"
        
    -   `file.name` string puede ser null
        
        Nombre del archivo (ej. `contrato.pdf`). Se valida contra path traversal.
        
    
-   `documents` array de objetos puede ser null
    
    Expediente compound: 1..N piezas (archivo o plantilla). Mutuamente exclusivo con el `file`/`templateId` de un solo origen. Mismo cerebro que `POST /v2/documents/` con `documents[]`.
    
    Ver 7 atributos hijos
    
    -   `documents[].file` objeto puede ser null
        
        Archivo inline (PDF/DOCX en base64). Mutuamente exclusivo con `templateId`.
        
        Ver 3 atributos hijos
        
        -   `documents[].file.content` string requerido
            
            Contenido del archivo codificado en Base64. Máximo 10 MB decodificados.
            
        -   `documents[].file.fileType` string
            
            Tipo de archivo. Default `pdf`.
            
            default "pdf"
            
        -   `documents[].file.name` string puede ser null
            
            Nombre del archivo (ej. `contrato.pdf`). Se valida contra path traversal.
            
        
    -   `documents[].templateId` string puede ser null
        
        ID de plantilla (`tmpl_…`). Mutuamente exclusivo con `file`.
        
    -   `documents[].templateValues` objeto (llave → valor) puede ser null
        
        Valores owner-fixed para variables de este item (llaves naturales, no camelCase).
        
    -   `documents[].name` string puede ser null
        
        Nombre visible de esta pieza dentro del expediente.
        
        máx. 255 caracteres
        
    -   `documents[].kind` enum
        
        Rol de la pieza: `main`, `attachment` o `cover`.
        
        Valores: `main` `attachment` `cover`
        
        default "main"
        
    -   `documents[].position` integer puede ser null
        
        Orden 1-based de concatenación. Si se omite, se asigna 1..N por índice.
        
        mín. 1
        
    -   `documents[].dedupeScope` enum
        
        `document` comparte variables entre piezas; `pdf` las aísla a este item.
        
        Valores: `document` `pdf`
        
        default "document"
        
    
-   `fields` array de objetos puede ser null
    
    Campos de firma a colocar al crear (`anchorString` o `position`). Cada `email`/`phone` debe coincidir con un `signers[]`. En compound usa `documentPdfPosition` para anclar a una pieza.
    
    Ver 10 atributos hijos
    
    -   `fields[].email` string puede ser null
        
        Correo del firmante (debe coincidir con un `signers[].email`).
        
    -   `fields[].phone` string puede ser null
        
        WhatsApp del firmante (debe coincidir con un `signers[].phone`).
        
    -   `fields[].pageNumber` integer puede ser null
        
        Página 1-based. En anclas, acota la búsqueda a esa página.
        
    -   `fields[].documentPdfPosition` integer puede ser null
        
        Compound: posición 1-based del PDF de `documents[]` al que pertenece este campo.
        
    -   `fields[].anchorString` string puede ser null
        
        Texto ancla en el PDF. Mutuamente exclusivo con `position`.
        
    -   `fields[].anchorHorizontalAlignment` enum
        
        Alineación horizontal sobre el ancla. Ignorado en modo coordenadas.
        
        Valores: `left` `center` `right`
        
        default "left"
        
    -   `fields[].anchorVerticalAlignment` enum
        
        Alineación vertical sobre el ancla. Ignorado en modo coordenadas.
        
        Valores: `top` `center` `bottom`
        
        default "center"
        
    -   `fields[].position` objeto puede ser null
        
        Coordenadas {x,y} en puntos PDF. Mutuamente exclusivo con `anchorString`.
        
        Ver 2 atributos hijos
        
        -   `fields[].position.x` number requerido
            
        -   `fields[].position.y` number requerido
            
        
    -   `fields[].height` number
        
        Alto del campo en puntos. El ancho es 2×.
        
        default 100 · mayor que 0
        
    -   `fields[].includeInAllPages` boolean
        
        Solo modo coordenadas: repetir el campo en todas las páginas.
        
        default false
        
    
-   `sendInvitations` boolean
    
    Si es true, dispara invitaciones al crear (equivale a v2 `config.sendInvitations`). Fuerza `startAtStep=3`.
    
    default false
    
-   `startAtStep` integer
    
    Paso inicial: 1=borrador, 2=campos, 3=esperando firmas (cobra al crear).
    
    default 1 · entre 1 y 3
    
-   `folderId` string puede ser null
    
    Carpeta destino (`fld_…`).
    
-   `ownerEmail` string puede ser null
    
    Dueño del documento (email de un user del tenant). Equivale a v2 `permissions.ownerEmail`.
    
-   `name` string puede ser null
    
    Nombre visible del documento. Si se omite, se deriva de la plantilla o del archivo.
    
-   `signers` array de objetos puede ser null
    
    Firmantes a adjuntar al crear el documento.
    
    Ver 10 atributos hijos
    
    -   `signers[].email` string puede ser null
        
        Correo del firmante. Manda `email` o `phone`, no los dos: cada firmante recibe su invitación por un solo canal (422 `VALIDATION_ERROR` si llegan ambos).
        
    -   `signers[].phone` string puede ser null
        
        Teléfono del firmante (para invitación por WhatsApp). Excluye a `email`: un firmante lleva un solo canal.
        
        máx. 32 caracteres
        
    -   `signers[].name` string puede ser null
        
        Nombre del firmante.
        
        máx. 255 caracteres
        
    -   `signers[].roleName` string puede ser null
        
        Rol semántico del firmante (ej. `proveedor`), usado para auto-asignar variables de plantilla marcadas con ese rol. Opcional — si se omite, las variables deben asignarse manualmente.
        
        máx. 255 caracteres
        
    -   `signers[].values` objeto (llave → valor) puede ser null
        
        Prellenado de campos del formulario PDF por nombre de campo (texto o casilla). Sólo aplica a plantillas PDF con campos; las llaves nunca se camelizan.
        
    -   `signers[].readOnly` array de string puede ser null
        
        Nombres de campos prellenados que el firmante no puede cambiar.
        
    -   `signers[].routingOrder` integer puede ser null
        
        Etapa de firma (1 = primera). Firmantes con el mismo número firman en paralelo. Solo aplica con `signingOrder: "sequential"`. Con `signingOrder: "sequential"` es **obligatorio en todos** los firmantes: si le falta a alguno, la creación se rechaza con 422 `VALIDATION_ERROR` diciendo en cuál falta, en vez de repartir etapas por su cuenta. Dentro del producto un firmante sin número cuenta como etapa 1, pero la API v3 no asume ese default: un `sequential` a medio numerar sería un documento que firma todo el mundo a la vez sin decirlo. Después de crear, la etapa se cambia con `PATCH /v3/documents/{documentId}/signers/{signerId}`. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
        
        mín. 1
        
    -   `signers[].kind` enum
        
        `signer` (default) firma. `carbon_copy` es un observador: nunca firma ni recibe campos, solo los avisos de `events` y, con `capability: notify_and_view`, un enlace de solo lectura. Un observador necesita `email` y no lleva `roleName`, `routingOrder`, `values` ni `readOnly`. Después de crear se administran con `/v3/documents/{documentId}/observers`.
        
        Valores: `signer` `carbon_copy`
        
        default "signer"
        
    -   `signers[].capability` enum puede ser null
        
        Solo observadores: `notify` (default) o `notify_and_view`.
        
        Valores: `notify` `notify_and_view`
        
    -   `signers[].events` array de string puede ser null
        
        Solo observadores: avisos que recibe. `document.completed` (default), `document.expired`, `document.voided`.
        
        máx. 10 elementos
        
    
-   `signatureValidation` objeto puede ser null
    
    Nivel de validez legal (autógrafa/NOM-151/FEA/biometría/videofirma). Por default: solo autógrafa.
    
    Ver 6 atributos hijos
    
    -   `signatureValidation.autografa` boolean
        
        Firma autógrafa (trazo en pantalla).
        
        default true
        
    -   `signatureValidation.nom151` boolean
        
        Constancia de conservación NOM-151.
        
        default false
        
    -   `signatureValidation.fea` boolean
        
        Firma Electrónica Avanzada (FEA/e.firma SAT).
        
        default false
        
    -   `signatureValidation.biometricSignature` boolean
        
        Verificación biométrica (selfie vs. identificación, anti-deepfake).
        
        default false
        
    -   `signatureValidation.idScan` boolean
        
        Escaneo de identificación oficial (INE, pasaporte).
        
        default false
        
    -   `signatureValidation.videofirma` boolean
        
        Graba video del firmante durante el proceso de firma.
        
        default false
        
    
-   `expiresAt` string (fecha-hora ISO 8601) puede ser null
    
    Fecha límite de firma (ISO 8601).
    
-   `mode` enum puede ser null
    
    Pasa `draft` para crear el documento sin cobrar ni enviar invitaciones (fuerza `startAtStep=1`). Si se omite, se conserva el comportamiento actual.
    
    Valores: `draft`
    
-   `signingOrder` enum puede ser null
    
    `parallel` (default): todos los firmantes reciben su invitación a la vez. `sequential`: cada firmante trae `routingOrder` y solo la etapa activa puede firmar; la siguiente se invita cuando la anterior termina. `sequential` exige `routingOrder` en **cada** firmante (422 `VALIDATION_ERROR` si falta alguno) y `parallel` no lo admite en ninguno. El modo no se puede cambiar después; las etapas sí, con `PATCH /v3/documents/{documentId}/signers/{signerId}`. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
    
    Valores: `parallel` `sequential`
    

#### Devuelve

**201** El anexo creado (mismo shape que Retrieve document), con `parentDocumentId`. — [el objeto Document](#objeto-document)

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [402](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [413](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_f225e42012ba44dd853a06e460b02674/annexes' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "v3audit-ejemplos anexo",
  "file": {
    "content": "'"$(base64 < contrato.pdf | tr -d '\n')"'",
    "fileType": "pdf",
    "name": "contrato.pdf"
  },
  "signers": [
    {
      "email": "signer-success@sandbox.allsign.io",
      "name": "Ana Torres"
    }
  ]
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';
import { readFileSync } from 'node:fs';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_f225e42012ba44dd853a06e460b02674/annexes', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: 'v3audit-ejemplos anexo',
        file: {
            content: readFileSync('contrato.pdf').toString('base64'),
            fileType: 'pdf',
            name: 'contrato.pdf',
        },
        signers: [
            {
                email: 'signer-success@sandbox.allsign.io',
                name: 'Ana Torres',
            },
        ],
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import base64
import os
import uuid
from pathlib import Path

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_f225e42012ba44dd853a06e460b02674/annexes",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "name": "v3audit-ejemplos anexo",
        "file": {
            "content": base64.b64encode(Path("contrato.pdf").read_bytes()).decode(),
            "fileType": "pdf",
            "name": "contrato.pdf",
        },
        "signers": [
            {
                "email": "signer-success@sandbox.allsign.io",
                "name": "Ana Torres",
            },
        ],
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 201**

```
{
  "livemode": false,
  "id": "doc_c4115305932549ef94df72521eaf2d20",
  "object": "document",
  "name": "v3audit-ejemplos anexo",
  "status": "draft",
  "documentType": "EDITABLE",
  "signerCount": 1,
  "signedCount": 0,
  "ownerId": "usr_1aad26c4fef446eb95197ba6c5edaa0a",
  "orgId": "39335bc4-0297-48dc-914f-76c58bbe2921",
  "folderId": null,
  "expiresAt": null,
  "signingOrder": "parallel",
  "currentStage": null,
  "expirationReminders": null,
  "templateId": null,
  "templateVersionId": null,
  "parentDocumentId": "doc_f225e42012ba44dd853a06e460b02674",
  "createdAt": "2026-07-11T18:00:00.000000Z",
  "updatedAt": "2026-07-11T18:00:00.000000Z"
}
```

**Respuesta · 409 · DOCUMENT_NOT_FULLY_SIGNED**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_NOT_FULLY_SIGNED",
  "title": "Conflict",
  "status": 409,
  "detail": "Annexes can only be attached to a fully signed document. This document's current status does not allow it.",
  "instance": "/v3/documents/doc_78e3621115ea4fbc88605ae1c3118ec6/annexes",
  "code": "DOCUMENT_NOT_FULLY_SIGNED",
  "requestId": "req_3f16b52d15ec400c8cc87067adfef964"
}
```

**Respuesta · 409 · ANNEX_OF_ANNEX_NOT_ALLOWED**

```
{
  "type": "https://allsign.io/developers/docs/errors#ANNEX_OF_ANNEX_NOT_ALLOWED",
  "title": "Conflict",
  "status": 409,
  "detail": "This document is itself an annex. Attach the new annex to the root document instead.",
  "instance": "/v3/documents/doc_aa07ee47bbea45edb879fdc2ac9db8e7/annexes",
  "code": "ANNEX_OF_ANNEX_NOT_ALLOWED",
  "requestId": "req_afd05ccadf4e4d4e8c22a38f25e3d8c7"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos-firmados.ejemplos.spec.ts`

## Get a document's family

GET `/documents/{document_id}/family`

El documento original y todos sus anexos, en orden de creación. Puedes pedirla con el id de cualquier miembro: `rootId` siempre es el original. Cada miembro trae su `status`, si es `original` o `annex` (`kind`) y de quién es anexo (`parentDocumentId`).

#### Parámetros

-   `document_id` string ruta requerido
    
    ID de cualquier documento de la familia (`doc_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** El original y sus anexos.

Ver los 4 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "document\_family"
    
    Siempre `"document_family"`.
    
-   `rootId` string requerido
    
    El documento original de la familia (`doc_…`).
    
-   `data` array de objetos requerido
    
    El original y todos sus anexos, en orden cronológico ascendente.
    
    Ver 5 atributos hijos
    
    -   `data[].id` string requerido
        
        ID del documento (`doc_…`).
        
    -   `data[].status` enum requerido
        
        Estado del ciclo de vida de este documento.
        
        Valores: `draft` `collecting_data` `awaiting_signatures` `correcting` `processing` `completed` `expired` `voided` `error`
        
    -   `data[].kind` enum requerido
        
        `original` (sin padre) o `annex` (tiene `parentDocumentId`).
        
        Valores: `original` `annex`
        
    -   `data[].parentDocumentId` string puede ser null
        
        Documento del que este es anexo (`doc_…`), o `null` si es el original.
        
    -   `data[].createdAt` string (fecha-hora ISO 8601) requerido
        
        Fecha de creación (ISO 8601).
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_f225e42012ba44dd853a06e460b02674/family' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_f225e42012ba44dd853a06e460b02674/family', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_f225e42012ba44dd853a06e460b02674/family",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "document_family",
  "rootId": "doc_f225e42012ba44dd853a06e460b02674",
  "data": [
    {
      "id": "doc_f225e42012ba44dd853a06e460b02674",
      "status": "completed",
      "kind": "original",
      "parentDocumentId": null,
      "createdAt": "2026-07-11T17:59:52.015000Z"
    },
    {
      "id": "doc_c4115305932549ef94df72521eaf2d20",
      "status": "draft",
      "kind": "annex",
      "parentDocumentId": "doc_f225e42012ba44dd853a06e460b02674",
      "createdAt": "2026-07-11T18:00:00.000000Z"
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos-firmados.ejemplos.spec.ts`

## Remind signer

POST `/documents/{document_id}/signers/{signer_id}/remind`

Reenvía la invitación (email o WhatsApp, según cómo se agregó el firmante) a UN firmante que todavía no completa. Exige `Idempotency-Key`: un reintento de red con la misma llave devuelve la primera respuesta y no manda un segundo correo. Además hay un freno de un recordatorio cada 4 horas por firmante. La respuesta `200` trae `nextAllowedAt`: guárdala y no vuelvas a recordar antes de esa hora. Si lo haces, la respuesta es `429 RATE_LIMITED` con la hora solo dentro de `detail` y sin `Retry-After`, así que no la reintentes con backoff.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `signer_id` string ruta requerido
    
    ID del firmante a recordar (`sgr_…`).
    
-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Confirmación del recordatorio — incluye `nextAllowedAt`.

Ver los 6 atributos de la respuesta

-   `documentId` string requerido
    
    ID del documento (`doc_…`).
    
-   `signerId` string requerido
    
    ID del firmante recordado (`sgr_…`).
    
-   `sentAt` string (fecha-hora ISO 8601) requerido
    
    Cuándo se procesó el recordatorio.
    
-   `nextAllowedAt` string (fecha-hora ISO 8601) requerido
    
    Antes de esta fecha, un nuevo recordatorio a este firmante responde 429.
    
-   `channel` string requerido
    
    Canal de entrega: `email` o `whatsapp`.
    
-   `delivered` boolean requerido
    
    `true` si el envío tuvo éxito. `false` no falla la petición — el remitente puede reintentar.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers/sgr_80189c3a228a438cbb36757ed5f4738c/remind' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers/sgr_80189c3a228a438cbb36757ed5f4738c/remind', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({}),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers/sgr_80189c3a228a438cbb36757ed5f4738c/remind",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={},
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "documentId": "doc_d0a1551c68d6457294e702fb25d07e4e",
  "signerId": "sgr_80189c3a228a438cbb36757ed5f4738c",
  "sentAt": "2026-07-11T18:00:00.000000Z",
  "nextAllowedAt": "2026-07-11T18:00:00.000000Z",
  "channel": "email",
  "delivered": false
}
```

**Respuesta · 404 · SIGNER_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#SIGNER_NOT_FOUND",
  "title": "Not Found",
  "status": 404,
  "detail": "Signer '8bc0129e-c73d-4d49-b5d2-c0335a209b8d' not found in this document.",
  "instance": "/v3/documents/doc_ca783e90f0444172a7fbe75400ab5ebc/signers/sgr_8bc0129ec73d4d49b5d2c0335a209b8d/remind",
  "code": "SIGNER_NOT_FOUND",
  "requestId": "req_aa688e8a2b7e46ab88bb8e67a281ba61"
}
```

**Respuesta · 409 · INVALID_STATE_TRANSITION**

```
{
  "type": "https://allsign.io/developers/docs/errors#INVALID_STATE_TRANSITION",
  "title": "Conflict",
  "status": 409,
  "detail": "Document is in terminal state 'ANULADO' — cannot remind.",
  "instance": "/v3/documents/doc_ca783e90f0444172a7fbe75400ab5ebc/signers/sgr_f70f3376d8fc450a97111874e086f6b6/remind",
  "code": "INVALID_STATE_TRANSITION",
  "requestId": "req_18baf385999e4893975db73d70c38511",
  "reason": "document_terminal"
}
```

**Respuesta · 409 · NOT_YOUR_TURN**

```
{
  "type": "https://allsign.io/developers/docs/errors#NOT_YOUR_TURN",
  "title": "Conflict",
  "status": 409,
  "detail": "Signer belongs to stage 3 and stage 1 has not finished — nothing to remind yet.",
  "instance": "/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/signers/sgr_0dcad5b836254b2791fab1bb6e6995f2/remind",
  "code": "NOT_YOUR_TURN",
  "requestId": "req_fda92aa97e3743a9805cbc1eaee1292c",
  "reason": "not_your_turn"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Remind all pending signers

POST `/documents/{document_id}/signers/remind-all`

Reenvía el recordatorio a TODOS los firmantes pendientes del documento de una sola llamada — la versión masiva de `POST .../remind`. Cada firmante conserva su propio enfriamiento de 4h y su propio turno de orden de firma: uno en cooldown, o que todavía no le toca, nunca bloquea a los demás — aparece en `results[]` con su propio `status` (`sent` | `failed` | `rate_limited` | `skipped`) en vez de fallar toda la petición. Solo falla como un todo si el DOCUMENTO no existe (**404**) o está en un estado terminal (**409**, `reason: document_terminal`) — ahí no hay nada que recordarle a nadie.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Un resultado por firmante pendiente en `results[]`, cada uno con su `status` (`sent`, `failed`, `rate_limited` o `skipped`); `sentCount` cuenta solo los recordatorios que sí salieron.

Ver los 3 atributos de la respuesta

-   `documentId` string requerido
    
    ID del documento (`doc_…`).
    
-   `sentCount` integer requerido
    
    Cuántos firmantes SÍ recibieron el recordatorio.
    
-   `results` array de objetos requerido
    
    Ver 7 atributos hijos
    
    -   `results[].signerId` string requerido
        
        ID del firmante (`sgr_…`).
        
    -   `results[].signerName` string puede ser null
        
        Nombre para mostrar del firmante, si se conoce.
        
    -   `results[].status` string requerido
        
        `sent` | `failed` | `rate_limited` | `skipped`.
        
    -   `results[].delivered` boolean
        
        `true` si el envío tuvo éxito (solo aplica cuando status=sent).
        
        default false
        
    -   `results[].channel` string puede ser null
        
        Canal de entrega, cuando status=sent.
        
    -   `results[].nextAllowedAt` string (fecha-hora ISO 8601) puede ser null
        
        Cuándo se puede volver a recordar a este firmante.
        
    -   `results[].detail` string puede ser null
        
        Motivo legible cuando status != sent.
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/signers/remind-all' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/signers/remind-all', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({}),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_cb8538f977be47d597896fd6a71f8f17/signers/remind-all",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={},
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "documentId": "doc_cb8538f977be47d597896fd6a71f8f17",
  "sentCount": 0,
  "results": [
    {
      "signerId": "sgr_0dcad5b836254b2791fab1bb6e6995f2",
      "signerName": "Ana Torres",
      "status": "skipped",
      "delivered": false,
      "channel": null,
      "nextAllowedAt": null,
      "detail": "Signer belongs to stage 3 and stage 1 has not finished — nothing to remind yet."
    },
    {
      "signerId": "sgr_f2f4eea4da414a38a7aeec6c22ba4bf1",
      "signerName": "Luis Ramírez",
      "status": "rate_limited",
      "delivered": false,
      "channel": null,
      "nextAllowedAt": null,
      "detail": "Reminder rate-limited. Next allowed at 2026-07-11T21:59:59.909000+00:00."
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Reassign signer

POST `/documents/{document_id}/signers/{signer_id}/reassign`

Cambia a la **persona** detrás de un firmante sin perder su lugar: el `sgr_…` es el mismo, sus campos y su etapa en el orden de firma sobreviven, y su rol conserva nombre y cajas. Manda exactamente uno de `email` o `phone` (correo → WhatsApp y de regreso están soportados, una llamada a la vez). Lo que el firmante anterior había capturado se descarta — sus campos vuelven a vacío, su verificación de identidad no se hereda y sus ligas vivas se revocan; lo que prellenó el emisor se conserva. Si ya había capturado algo, la API exige `confirm: true` (409 `INVALID_STATE_TRANSITION` con `reason: "confirmation_required"` si falta). Si el documento ya está enviado y es el turno de ese firmante, la invitación sale sola al nuevo contacto; al anterior no se le avisa. Un firmante que ya firmó no se puede reasignar (409). `Idempotency-Key` obligatorio: un reintento con la misma llave devuelve la misma respuesta sin volver a mover nada.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `signer_id` string ruta requerido
    
    ID del firmante a reasignar (`sgr_…`). Es el que se conserva.
    
-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `email` string puede ser null
    
    Nuevo correo del firmante.
    
-   `phone` string puede ser null
    
    Nuevo teléfono (E.164) del firmante.
    
-   `name` string puede ser null
    
    Nombre a mostrar mientras no haya IDV.
    
-   `reason` string puede ser null
    
    Motivo — queda en el historial del documento.
    
    máx. 500 caracteres
    
-   `confirm` boolean
    
    El firmante anterior ya capturó algo (campos, verificación de identidad). Pásalo en `true` para confirmar que se descarta.
    
    default false
    

#### Devuelve

**200** El firmante ya con la persona nueva: mismo `id`, `email`/`phone`/`name` nuevos, `status` reinicia a `pending` o `sent` según si la invitación salió.

Ver los 11 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `id` string requerido
    
    ID del firmante (`sgr_…`).
    
-   `object` string, siempre "signer"
    
    Siempre `"signer"`.
    
-   `documentId` string requerido
    
    Documento al que pertenece (`doc_…`).
    
-   `email` string puede ser null
    
    Correo del firmante.
    
-   `phone` string puede ser null
    
    Teléfono del firmante.
    
-   `name` string puede ser null
    
    Nombre del firmante.
    
-   `status` enum requerido
    
    Estado por firmante: `pending`, `sent`, `signed`, `cancelled`, `waiting_turn`.
    
    Valores: `pending` `sent` `signed` `cancelled` `waiting_turn`
    
-   `signedAt` string (fecha-hora ISO 8601) puede ser null
    
    Momento de la firma (ISO 8601), o `null` si aún no firma.
    
-   `routingOrder` integer puede ser null
    
    Etapa de firma en un documento `sequential`; `null` en paralelo. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
    
-   `delivery` objeto puede ser null
    
    Entrega de la última invitación vigente (no revocada). `null` si no hay nada rastreado: invitaciones por correo sin rebote, anteriores al seguimiento, o un firmante recién reasignado.
    
    Ver 5 atributos hijos
    
    -   `delivery.channel` enum requerido
        
        Canal de la última invitación: `whatsapp` o `email`.
        
        Valores: `whatsapp` `email`
        
    -   `delivery.status` enum requerido
        
        Estado de entrega según el proveedor: `sent`, `delivered`, `read` o `failed`. En correo solo se informa `failed` (rebote).
        
        Valores: `sent` `delivered` `read` `failed`
        
    -   `delivery.reason` enum puede ser null
        
        Por qué falló, en un catálogo estable de AllSign: `provider_payment_issue`, `undeliverable`, `bounced` u `other`. `null` si no falló.
        
        Valores: `provider_payment_issue` `undeliverable` `bounced` `other`
        
    -   `delivery.providerCode` integer puede ser null
        
        Código de error original del proveedor (p. ej. de WhatsApp), o `null`.
        
    -   `delivery.updatedAt` string (fecha-hora ISO 8601) requerido
        
        Momento del último cambio de estado (ISO 8601).
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers/sgr_80189c3a228a438cbb36757ed5f4738c/reassign' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "signer-pending+relevo@sandbox.allsign.io",
  "name": "Luis Ramírez",
  "reason": "Cambió el representante legal"
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers/sgr_80189c3a228a438cbb36757ed5f4738c/reassign', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        email: 'signer-pending+relevo@sandbox.allsign.io',
        name: 'Luis Ramírez',
        reason: 'Cambió el representante legal',
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_d0a1551c68d6457294e702fb25d07e4e/signers/sgr_80189c3a228a438cbb36757ed5f4738c/reassign",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "email": "signer-pending+relevo@sandbox.allsign.io",
        "name": "Luis Ramírez",
        "reason": "Cambió el representante legal",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "id": "sgr_80189c3a228a438cbb36757ed5f4738c",
  "object": "signer",
  "documentId": "doc_d0a1551c68d6457294e702fb25d07e4e",
  "email": "signer-pending+relevo@sandbox.allsign.io",
  "phone": null,
  "name": "Luis Ramírez",
  "status": "pending",
  "signedAt": null,
  "routingOrder": null,
  "delivery": null
}
```

**Respuesta · 409 · INVALID_STATE_TRANSITION**

```
{
  "type": "https://allsign.io/developers/docs/errors#INVALID_STATE_TRANSITION",
  "title": "Conflict",
  "status": 409,
  "detail": "No se puede reasignar a un firmante que ya firmó.",
  "instance": "/v3/documents/doc_b7b43220a55940578a9feaef6c618cf5/signers/sgr_7d4f43e179d1487aab88d212de9def03/reassign",
  "code": "INVALID_STATE_TRANSITION",
  "requestId": "req_560c08b2d31f4128b8762eeec30fbf4e",
  "reason": "already_signed"
}
```

**Respuesta · 404 · SIGNER_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#SIGNER_NOT_FOUND",
  "title": "Not Found",
  "status": 404,
  "detail": "Firmante no encontrado.",
  "instance": "/v3/documents/doc_1dc79b7f4dd64d08ba9d3ed7a5626977/signers/sgr_bea9964ea0ca474592e3bd980042cc9e/reassign",
  "code": "SIGNER_NOT_FOUND",
  "requestId": "req_49cdadde120a49b9973885cb14f8c49e"
}
```

**Respuesta · 422 · SIGNER_INVALID**

```
{
  "type": "https://allsign.io/developers/docs/errors#SIGNER_INVALID",
  "title": "Signer invalid",
  "status": 422,
  "detail": "Es la misma persona; no hay nada que reasignar.",
  "instance": "/v3/documents/doc_1dc79b7f4dd64d08ba9d3ed7a5626977/signers/sgr_ea59f1a241c543029768ecb7f38a65bb/reassign",
  "code": "SIGNER_INVALID",
  "requestId": "req_922f9a91fb0c491495d387fe0f98bc12",
  "reason": "same_person"
}
```

**Respuesta · 422 · DUPLICATE_SIGNER**

```
{
  "type": "https://allsign.io/developers/docs/errors#DUPLICATE_SIGNER",
  "title": "Duplicate signer",
  "status": 422,
  "detail": "Esa persona ya es firmante de este documento.",
  "instance": "/v3/documents/doc_1dc79b7f4dd64d08ba9d3ed7a5626977/signers/sgr_ea59f1a241c543029768ecb7f38a65bb/reassign",
  "code": "DUPLICATE_SIGNER",
  "requestId": "req_3851c69baf2940bf874d02b256d8021a"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:14 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/errores.ejemplos.spec.ts`

## Sign as a signer (sandbox only)

POST `/sandbox/signers/{signer_id}/sign`

Firma por un firmante en **sandbox**, como si hubiera abierto su liga: estampa su firma en sus cajas y lo deja `signed`. Responde **200** en el momento, con el firmante ya firmado; si era el último, en la misma llamada el documento queda `completed` con su PDF de evidencia (en sandbox, con una constancia NOM-151 simulada, sin validez legal). Emite los mismos webhooks que una firma real: `signer.signed` y, si era el último, `document.completed`. Úsalo con `signer-pending@sandbox.allsign.io`, que nunca firma solo y no recibe correo, para recorrer a tu ritmo el ciclo real: `awaiting_signatures` → `signer.signed` → `completed` (ver [Entornos](https://allsign.io/developers/docs/environments#firmantes-magicos)). **Solo existe en sandbox.** Con una key live responde **409** `ENVIRONMENT_MISMATCH` y no cambia nada: en producción cada firmante firma con su propia liga. **409** `INVALID_STATE_TRANSITION` cuando el estado lo impide, con `reason`: `never_invited` (el documento todavía no se envía), `document_terminal` (ya terminó, se anuló, venció o está en corrección), `signer_terminal` (ese firmante ya firmó o fue cancelado) o `variables_pending` (faltan variables requeridas de su rol). En un documento `sequential`, **409** `NOT_YOUR_TURN` si su etapa todavía no abre. Un `signerId` que no existe, de otra organización o de otro entorno responde **404** `SIGNER_NOT_FOUND`. `Idempotency-Key` es opcional. Si la mandas, un reintento con la misma llave te devuelve la respuesta original (con `Idempotency-Replayed: true`) en vez del 409 que daría volver a firmar a alguien que ya firmó.

#### Parámetros

-   `signer_id` string ruta requerido
    
    ID del firmante (`sgr_…`), el que devuelve `GET /documents/{documentId}/signers`.
    
-   `Idempotency-Key` string header
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** El firmante ya firmado (`status: "signed"`). Si era el último, el documento ya está `completed`.

Ver los 11 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `id` string requerido
    
    ID del firmante (`sgr_…`).
    
-   `object` string, siempre "signer"
    
    Siempre `"signer"`.
    
-   `documentId` string requerido
    
    Documento al que pertenece (`doc_…`).
    
-   `email` string puede ser null
    
    Correo del firmante.
    
-   `phone` string puede ser null
    
    Teléfono del firmante.
    
-   `name` string puede ser null
    
    Nombre del firmante.
    
-   `status` enum requerido
    
    Estado por firmante: `pending`, `sent`, `signed`, `cancelled`, `waiting_turn`.
    
    Valores: `pending` `sent` `signed` `cancelled` `waiting_turn`
    
-   `signedAt` string (fecha-hora ISO 8601) puede ser null
    
    Momento de la firma (ISO 8601), o `null` si aún no firma.
    
-   `routingOrder` integer puede ser null
    
    Etapa de firma en un documento `sequential`; `null` en paralelo. Disponible sólo si el orden de firma está habilitado en el entorno; si no, pedir `sequential` responde 403 `SEQUENTIAL_NOT_AVAILABLE` y todo documento firma en paralelo.
    
-   `delivery` objeto puede ser null
    
    Entrega de la última invitación vigente (no revocada). `null` si no hay nada rastreado: invitaciones por correo sin rebote, anteriores al seguimiento, o un firmante recién reasignado.
    
    Ver 5 atributos hijos
    
    -   `delivery.channel` enum requerido
        
        Canal de la última invitación: `whatsapp` o `email`.
        
        Valores: `whatsapp` `email`
        
    -   `delivery.status` enum requerido
        
        Estado de entrega según el proveedor: `sent`, `delivered`, `read` o `failed`. En correo solo se informa `failed` (rebote).
        
        Valores: `sent` `delivered` `read` `failed`
        
    -   `delivery.reason` enum puede ser null
        
        Por qué falló, en un catálogo estable de AllSign: `provider_payment_issue`, `undeliverable`, `bounced` u `other`. `null` si no falló.
        
        Valores: `provider_payment_issue` `undeliverable` `bounced` `other`
        
    -   `delivery.providerCode` integer puede ser null
        
        Código de error original del proveedor (p. ej. de WhatsApp), o `null`.
        
    -   `delivery.updatedAt` string (fecha-hora ISO 8601) requerido
        
        Momento del último cambio de estado (ISO 8601).
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/sandbox/signers/sgr_d64e1ca6bcf64eebac2d35da21d23c88/sign' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)"
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/sandbox/signers/sgr_d64e1ca6bcf64eebac2d35da21d23c88/sign', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/sandbox/signers/sgr_d64e1ca6bcf64eebac2d35da21d23c88/sign",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "id": "sgr_d64e1ca6bcf64eebac2d35da21d23c88",
  "object": "signer",
  "documentId": "doc_fdde14eeff0b4444acec4d6b10736068",
  "email": "signer-pending@sandbox.allsign.io",
  "phone": null,
  "name": "Ana Torres",
  "status": "signed",
  "signedAt": "2026-07-11T18:01:06.969000Z",
  "routingOrder": null,
  "delivery": null
}
```

**Respuesta · 409 · INVALID_STATE_TRANSITION**

```
{
  "type": "https://allsign.io/developers/docs/errors#INVALID_STATE_TRANSITION",
  "title": "Conflict",
  "status": 409,
  "detail": "The document has not been sent yet. Send it first with POST /v3/documents/{documentId}/send.",
  "instance": "/v3/sandbox/signers/sgr_592c7816786d4e70bb676a8be0648b5b/sign",
  "code": "INVALID_STATE_TRANSITION",
  "requestId": "req_c1f762446ffa48c2a620e3c8297daa1f",
  "reason": "never_invited"
}
```

**Respuesta · 409 · NOT_YOUR_TURN**

```
{
  "type": "https://allsign.io/developers/docs/errors#NOT_YOUR_TURN",
  "title": "Conflict",
  "status": 409,
  "detail": "Signer belongs to stage 2 and stage 1 has not finished — sign that stage first.",
  "instance": "/v3/sandbox/signers/sgr_da9664ed9de849219e7bd3defea3700e/sign",
  "code": "NOT_YOUR_TURN",
  "requestId": "req_d29e50a055114b728bdde26ba79637cb",
  "reason": "not_your_turn"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:19 (hora CDMX) · test `docs-checks-v3/tests/recetas/primer-documento-a-firma.receta.spec.ts`

## List document observers

GET `/documents/{document_id}/observers`

Lista quién observa el documento: los observadores agregados a **este** documento (`origin: "document"`, con su `id` `rol_…`) y los de la organización, que observan todos los documentos (`origin: "organization"`, `id: null` y `locked: true`; esos se quitan desde Ajustes → Observadores, no por documento). Un observador **nunca firma**: recibe los avisos que eligió en `events` y, con `capability: "notify_and_view"`, un enlace de solo lectura. `status` vale `pending_verification` mientras el correo de un observador de organización no confirme la regla. Es una colección acotada: `hasMore` siempre es `false`.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** Lista (`object: "list"`) con `documentId` y los observadores en `data`.

Ver los 5 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "list"
    
    Siempre `"list"`.
    
-   `documentId` string requerido
    
    El documento (`doc_…`).
    
-   `data` array de objetos requerido
    
    Observadores del documento y de la organización.
    
    Ver 10 atributos hijos
    
    -   `data[].object` string, siempre "document\_observer"
        
        Siempre `"document_observer"`.
        
    -   `data[].id` string puede ser null
        
        Id del observador (`rol_…`). `null` en los de la organización: esos se quitan desde Ajustes → Observadores, no por documento.
        
    -   `data[].origin` enum requerido
        
        `document` si se agregó a este documento, `organization` si observa todos.
        
        Valores: `document` `organization`
        
    -   `data[].email` string puede ser null
        
        Correo del observador.
        
    -   `data[].name` string puede ser null
        
        Nombre del observador.
        
    -   `data[].capability` enum requerido
        
        `notify`: solo avisos. `notify_and_view`: avisos y un enlace de solo lectura.
        
        Valores: `notify` `notify_and_view`
        
    -   `data[].events` array de string requerido
        
        Avisos que recibe: `document.completed` (default), `document.expired` y `document.voided`.
        
    -   `data[].locked` boolean requerido
        
        `true` cuando viene de la organización y no se puede quitar aquí.
        
    -   `data[].status` string
        
        `active`, o `pending_verification` si el correo aún no confirma la regla global.
        
        default "active"
        
    -   `data[].createdAt` string (fecha-hora ISO 8601) puede ser null
        
        Cuándo se agregó.
        
    
-   `hasMore` boolean
    
    Siempre `false` en esta colección acotada.
    
    default false
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "list",
  "documentId": "doc_f2344cc1b9b24ba2954715812b3d7242",
  "data": [
    {
      "object": "document_observer",
      "id": "rol_9f8c7b2441a646b5aacbd925b2d3b6d9",
      "origin": "document",
      "email": "luis@ejemplo.com",
      "name": "Luis Ramírez",
      "capability": "notify_and_view",
      "events": [
        "document.completed",
        "document.voided"
      ],
      "locked": false,
      "status": "active",
      "createdAt": "2026-07-11T18:00:01.027000Z"
    }
  ],
  "hasMore": false
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:18 (hora CDMX) · test `docs-checks-v3/tests/recetas/observadores-y-transferencia.receta.spec.ts`

## Add document observer

POST `/documents/{document_id}/observers`

Agrega a alguien que **nunca firma** y solo recibe avisos del documento. Manda `email` (obligatorio) y, si quieres, `name`, `capability` —`notify` (default, solo avisos) o `notify_and_view` (avisos y un enlace de solo lectura)— y `events`, los avisos que recibe (default `["document.completed"]`). Es idempotente por correo: si ese correo ya observa el documento, se actualizan sus ajustes y la respuesta trae `created: false`; pasar de `notify_and_view` a `notify` revoca sus enlaces de solo lectura. Un observador nuevo recibe un correo de aviso, y los webhooks suscritos reciben `document.observer_added` cuando se agrega o cambian sus ajustes. Un firmante del documento no puede ser también observador (409 `OBSERVER_IS_SIGNER`) y un documento anulado ya no acepta observadores (409 `DOCUMENT_CONFLICT`). Requiere la función `document-observers` activa en tu cuenta; sin ella responde 403 `FEATURE_NOT_AVAILABLE` y no cambia nada.

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `email` string requerido
    
    Correo del observador. Un firmante no puede observar.
    
    máx. 320 caracteres
    
-   `name` string puede ser null
    
    Nombre del observador.
    
    máx. 255 caracteres
    
-   `capability` enum
    
    `notify` (default) o `notify_and_view` (avisos y enlace de solo lectura).
    
    Valores: `notify` `notify_and_view`
    
-   `events` array de string puede ser null
    
    Avisos que recibe: `document.completed` (default), `document.expired` y `document.voided`.
    
    máx. 10 elementos
    

#### Devuelve

**201** Siempre `201`: el observador agregado o actualizado en `observer`, y `created` en `false` si ese correo ya observaba y solo cambiaron sus ajustes.

Ver los 3 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `observer` objeto requerido
    
    El observador agregado o actualizado.
    
    Ver 10 atributos hijos
    
    -   `observer.object` string, siempre "document\_observer"
        
        Siempre `"document_observer"`.
        
    -   `observer.id` string puede ser null
        
        Id del observador (`rol_…`). `null` en los de la organización: esos se quitan desde Ajustes → Observadores, no por documento.
        
    -   `observer.origin` enum requerido
        
        `document` si se agregó a este documento, `organization` si observa todos.
        
        Valores: `document` `organization`
        
    -   `observer.email` string puede ser null
        
        Correo del observador.
        
    -   `observer.name` string puede ser null
        
        Nombre del observador.
        
    -   `observer.capability` enum requerido
        
        `notify`: solo avisos. `notify_and_view`: avisos y un enlace de solo lectura.
        
        Valores: `notify` `notify_and_view`
        
    -   `observer.events` array de string requerido
        
        Avisos que recibe: `document.completed` (default), `document.expired` y `document.voided`.
        
    -   `observer.locked` boolean requerido
        
        `true` cuando viene de la organización y no se puede quitar aquí.
        
    -   `observer.status` string
        
        `active`, o `pending_verification` si el correo aún no confirma la regla global.
        
        default "active"
        
    -   `observer.createdAt` string (fecha-hora ISO 8601) puede ser null
        
        Cuándo se agregó.
        
    
-   `created` boolean requerido
    
    `false` si ya observaba y solo se actualizaron sus ajustes.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "luis@ejemplo.com",
  "name": "Luis Ramírez",
  "capability": "notify_and_view",
  "events": [
    "document.completed",
    "document.voided"
  ]
}'
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        email: 'luis@ejemplo.com',
        name: 'Luis Ramírez',
        capability: 'notify_and_view',
        events: [
            'document.completed',
            'document.voided',
        ],
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
    json={
        "email": "luis@ejemplo.com",
        "name": "Luis Ramírez",
        "capability": "notify_and_view",
        "events": [
            "document.completed",
            "document.voided",
        ],
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 201**

```
{
  "livemode": false,
  "observer": {
    "object": "document_observer",
    "id": "rol_9f8c7b2441a646b5aacbd925b2d3b6d9",
    "origin": "document",
    "email": "luis@ejemplo.com",
    "name": "Luis Ramírez",
    "capability": "notify_and_view",
    "events": [
      "document.completed",
      "document.voided"
    ],
    "locked": false,
    "status": "active",
    "createdAt": "2026-07-11T18:00:01.027000Z"
  },
  "created": true
}
```

**Respuesta · 409 · DOCUMENT_CONFLICT**

```
{
  "type": "https://allsign.io/developers/docs/errors#DOCUMENT_CONFLICT",
  "title": "Conflict",
  "status": 409,
  "detail": "The document was voided; it no longer takes observers.",
  "instance": "/v3/documents/doc_09bf1cccce9b463691037861ca4eea6f/observers",
  "code": "DOCUMENT_CONFLICT",
  "requestId": "req_77042c955bec4f2b8bd00e6388216505"
}
```

**Respuesta · 409 · OBSERVER_IS_SIGNER**

```
{
  "type": "https://allsign.io/developers/docs/errors#OBSERVER_IS_SIGNER",
  "title": "Conflict",
  "status": 409,
  "detail": "ana@ejemplo.com already signs this document; a signer cannot also be an observer.",
  "instance": "/v3/documents/doc_5dbd1cc097404878a5668c6a00774830/observers",
  "code": "OBSERVER_IS_SIGNER",
  "requestId": "req_68de996d2d6442b981652319043cc610"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:14 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/errores.ejemplos.spec.ts`

## Remove document observer

DELETE `/documents/{document_id}/observers/{observer_id}`

Quita un observador agregado a este documento y revoca sus enlaces de solo lectura; los webhooks suscritos reciben `document.observer_removed`. Solo quita observadores de documento: los de la organización (`origin: "organization"`) no tienen `id` y se quitan desde Ajustes → Observadores. Requiere la función `document-observers` activa en tu cuenta (403 `FEATURE_NOT_AVAILABLE`).

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `observer_id` string ruta requerido
    
    ID del observador (`rol_…`): el `id` que devuelven la lista o el alta.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** `object: "document_observer"`, el `id` quitado y `deleted: true`.

Ver los 4 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `object` string, siempre "document\_observer"
    
    Siempre `"document_observer"`.
    
-   `id` string requerido
    
    Id del observador quitado (`rol_…`).
    
-   `deleted` string, siempre "true"
    
    Siempre `true`.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X DELETE 'https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers/rol_9f8c7b2441a646b5aacbd925b2d3b6d9' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers/rol_9f8c7b2441a646b5aacbd925b2d3b6d9', {
    method: 'DELETE',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.delete(
    "https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/observers/rol_9f8c7b2441a646b5aacbd925b2d3b6d9",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "livemode": false,
  "object": "document_observer",
  "id": "rol_9f8c7b2441a646b5aacbd925b2d3b6d9",
  "deleted": true
}
```

**Respuesta · 404 · OBSERVER_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#OBSERVER_NOT_FOUND",
  "title": "Not Found",
  "status": 404,
  "detail": "Observer not found in this document. Organization observers are removed from Settings → Observers.",
  "instance": "/v3/documents/doc_5dbd1cc097404878a5668c6a00774830/observers/rol_245aa9e7229547b5b3e5cf30afe54094",
  "code": "OBSERVER_NOT_FOUND",
  "requestId": "req_22602288f4704ad2857ebd2b3dfa1468"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:18 (hora CDMX) · test `docs-checks-v3/tests/recetas/observadores-y-transferencia.receta.spec.ts`

## Transfer document owner

POST `/documents/{document_id}/transfer-owner`

Pasa el documento a otro miembro del **mismo** espacio de trabajo, nunca a otro espacio. Lo puede hacer el dueño actual o un owner/admin del espacio; cualquier otro recibe 403 `PERMISSION_DENIED`. Manda exactamente uno de `ownerUserId` (`usr_…`) u `ownerEmail`. Firmas, evidencia, constancias NOM-151 y quién creó el documento no cambian. La bitácora gana un evento `document.owner_transferred` (con tu `reason`, si la mandas) y los webhooks suscritos reciben el mismo evento. Con `keepPreviousOwnerAccess` (default `true`) el dueño anterior conserva acceso de lectura; en `false` lo pierde. Si el documento pertenece a una cadena, manda `transferChain: true` (409 `DOCUMENT_CONFLICT` si falta): se traspasa la cadena completa y `documentIds` dice cuáles cambiaron. `Idempotency-Key` obligatoria. Repetir el traspaso hacia quien ya es dueño responde `transferred: false`, igual que reintentar con la misma llave. Requiere la función `document-owner-transfer` activa en tu cuenta (403 `FEATURE_NOT_AVAILABLE`).

#### Parámetros

-   `document_id` string ruta requerido
    
    ID del documento (`doc_…`).
    
-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `ownerUserId` string puede ser null
    
    Nuevo dueño (`usr_…`). Debe ser miembro del espacio del documento.
    
-   `ownerEmail` string puede ser null
    
    Nuevo dueño por correo. Alternativa a `ownerUserId`; manda solo uno.
    
-   `keepPreviousOwnerAccess` boolean
    
    Si es `true`, el dueño anterior conserva acceso de lectura. Si es `false`, pierde el acceso.
    
    default true
    
-   `transferChain` boolean
    
    Obligatorio en `true` si el documento pertenece a una cadena: se traspasa la cadena completa.
    
    default false
    
-   `reason` string puede ser null
    
    Motivo del traspaso. Queda en la bitácora del documento y en el webhook `document.owner_transferred`.
    
    máx. 500 caracteres
    

#### Devuelve

**200** `documentId`, `ownerId` y `previousOwnerId` (`usr_…`), `transferred` y `documentIds`, los documentos que cambiaron de dueño.

Ver los 5 atributos de la respuesta

-   `documentId` string requerido
    
    Documento pedido (`doc_…`).
    
-   `ownerId` string requerido
    
    Dueño después del traspaso (`usr_…`).
    
-   `previousOwnerId` string requerido
    
    Dueño antes del traspaso (`usr_…`).
    
-   `transferred` boolean requerido
    
    `false` si el documento ya era de ese dueño o la misma `Idempotency-Key` ya lo había traspasado.
    
-   `documentIds` array de string
    
    Documentos que cambiaron de dueño: el pedido y, con `transferChain`, el resto de su cadena.
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/transfer-owner' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "ownerUserId": "usr_b478f972e8574a739be5fb7364382c33",
  "reason": "Cambio de responsable de la cuenta"
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/transfer-owner', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        ownerUserId: 'usr_b478f972e8574a739be5fb7364382c33',
        reason: 'Cambio de responsable de la cuenta',
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/doc_f2344cc1b9b24ba2954715812b3d7242/transfer-owner",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "ownerUserId": "usr_b478f972e8574a739be5fb7364382c33",
        "reason": "Cambio de responsable de la cuenta",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "documentId": "doc_f2344cc1b9b24ba2954715812b3d7242",
  "ownerId": "usr_b478f972e8574a739be5fb7364382c33",
  "previousOwnerId": "usr_550487c74d4a4061ba2af6b802dcacde",
  "transferred": true,
  "documentIds": [
    "doc_f2344cc1b9b24ba2954715812b3d7242"
  ]
}
```

**Respuesta · 422 · VALIDATION_ERROR**

```
{
  "type": "https://allsign.io/developers/docs/errors#VALIDATION_ERROR",
  "title": "Validation failed",
  "status": 422,
  "detail": "The new owner must be a member of this workspace.",
  "instance": "/v3/documents/doc_5dbd1cc097404878a5668c6a00774830/transfer-owner",
  "code": "VALIDATION_ERROR",
  "requestId": "req_156c01d6c0fd40f982ae571ecb18cce4"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:18 (hora CDMX) · test `docs-checks-v3/tests/recetas/observadores-y-transferencia.receta.spec.ts`

## Transfer documents owner

POST `/documents/transfer-owner`

Traspasa varios documentos al miembro `toUserId` (`usr_…`) del mismo espacio, en una sola llamada síncrona de hasta 500 documentos. Manda exactamente uno de `documentIds` (máximo 500) o `fromUserId`, que toma todos los documentos de ese dueño en el espacio y en el entorno de tu API key. Si `fromUserId` tiene más de 500, responde 422 `VALIDATION_ERROR` y no mueve nada: pártelos en tandas con `documentIds`. **Éxito parcial por diseño**: un documento que no existe, de otro espacio o entorno, que no puedes administrar o de una cadena sin `transferChains: true` falla solo su elemento (`items[].status: "error"` con el motivo en `error`). Un `200` no significa que todo se movió: revisa `items[]` y los contadores. Todos los documentos traspasados comparten el mismo `batchId` en su bitácora y en su webhook `document.owner_transferred`. `keepPreviousOwnerAccess` y `reason` funcionan igual que en el traspaso de uno. `Idempotency-Key` obligatoria. Requiere la función `document-owner-transfer` activa en tu cuenta (403 `FEATURE_NOT_AVAILABLE`).

#### Parámetros

-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `fromUserId` string puede ser null
    
    Traspasa todos los documentos de este dueño (`usr_…`) en el espacio. Alternativa a `documentIds`.
    
-   `documentIds` array de string puede ser null
    
    Documentos a traspasar (`doc_…`, máximo 500 por petición). Alternativa a `fromUserId`.
    
    máx. 500 elementos · mín. 1 elementos
    
-   `toUserId` string requerido
    
    Nuevo dueño (`usr_…`). Debe ser miembro del espacio.
    
-   `keepPreviousOwnerAccess` boolean
    
    Si es `false`, cada dueño anterior pierde el acceso a lo traspasado.
    
    default true
    
-   `transferChains` boolean
    
    Permite traspasar documentos de cadenas (con la cadena completa). Sin él, esos documentos fallan.
    
    default false
    
-   `reason` string puede ser null
    
    Motivo del traspaso. Queda en la bitácora del documento y en el webhook `document.owner_transferred`.
    
    máx. 500 caracteres
    

#### Devuelve

**200** `batchId`, `totalCount`, `transferredCount`, `unchangedCount`, `errorCount` e `items[]`, con `status` `transferred`, `unchanged` o `error` por documento.

Ver los 6 atributos de la respuesta

-   `batchId` string requerido
    
    Identificador del lote; viaja como `batchId` en la bitácora y en cada webhook.
    
-   `totalCount` integer requerido
    
    Documentos considerados.
    
-   `transferredCount` integer requerido
    
    Cuántos cambiaron de dueño.
    
-   `unchangedCount` integer requerido
    
    Cuántos ya eran del nuevo dueño.
    
-   `errorCount` integer requerido
    
    Cuántos no se pudieron traspasar.
    
-   `items` array de objetos requerido
    
    Resultado por documento.
    
    Ver 3 atributos hijos
    
    -   `items[].documentId` string requerido
        
        El id tal como se pidió.
        
    -   `items[].status` enum requerido
        
        Open enum: clients MUST tolerate values not in this list.
        
        Valores: `transferred` `unchanged` `error`
        
    -   `items[].error` string puede ser null
        
        Motivo si `status` es `error`.
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/transfer-owner' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "toUserId": "usr_550487c74d4a4061ba2af6b802dcacde",
  "documentIds": [
    "doc_f2344cc1b9b24ba2954715812b3d7242"
  ],
  "reason": "Regresa a su responsable original"
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';

const respuesta = await fetch('https://api.allsign.io/v3/documents/transfer-owner', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        toUserId: 'usr_550487c74d4a4061ba2af6b802dcacde',
        documentIds: [
            'doc_f2344cc1b9b24ba2954715812b3d7242',
        ],
        reason: 'Regresa a su responsable original',
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os
import uuid

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/transfer-owner",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "toUserId": "usr_550487c74d4a4061ba2af6b802dcacde",
        "documentIds": [
            "doc_f2344cc1b9b24ba2954715812b3d7242",
        ],
        "reason": "Regresa a su responsable original",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "batchId": "7dd2209a-5de4-4e64-ac28-c0d62da264b9",
  "totalCount": 1,
  "transferredCount": 1,
  "unchangedCount": 0,
  "errorCount": 0,
  "items": [
    {
      "documentId": "doc_f2344cc1b9b24ba2954715812b3d7242",
      "status": "transferred",
      "error": null
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:18 (hora CDMX) · test `docs-checks-v3/tests/recetas/observadores-y-transferencia.receta.spec.ts`

## Bulk delete documents

DELETE `/documents/bulk`

Elimina hasta 100 documentos en una sola petición. Éxito parcial por diseño (igual que v2): un id mal formado, un id de otro tenant, o un documento en un estado no eliminable (ya firmado o en progreso) falla SOLO ese elemento — nunca todo el lote. Revisa `items[].status` por cada id, nunca asumas éxito total por un `200`.

#### Parámetros

-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `documentIds` array de string requerido
    
    IDs de los documentos a eliminar (`doc_…`, máximo 100 por petición).
    
    máx. 100 elementos · mín. 1 elementos
    

#### Devuelve

**200** Resultado por elemento (`totalCount`/`successCount`/`errorCount`/`items[]`) — mismo vocabulario que Create bulk send.

Ver los 4 atributos de la respuesta

-   `totalCount` integer requerido
    
    Documentos pedidos.
    
-   `successCount` integer requerido
    
    Cuántos se eliminaron.
    
-   `errorCount` integer requerido
    
    Cuántos no se pudieron eliminar.
    
-   `items` array de objetos requerido
    
    Resultado por documento, en el orden pedido.
    
    Ver 3 atributos hijos
    
    -   `items[].documentId` string requerido
        
        El id tal como se envió en la petición.
        
    -   `items[].status` enum requerido
        
        Per-document outcome. Open enum — same vocabulary shape as BulkSendItemStatus on purpose: bulk-delete and bulk-send speak one vocabulary for "result per item of a bulk op". Open enum: clients MUST tolerate values not in this list.
        
        Valores: `deleted` `error`
        
    -   `items[].error` string puede ser null
        
        Motivo si `status` es `error` (id inválido, no encontrado, no eliminable).
        
    

Errores posibles (problem+json): [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X DELETE 'https://api.allsign.io/v3/documents/bulk' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Content-Type: application/json" \
  -d '{
  "documentIds": [
    "doc_82fa050abbc44b9587b71c8f84e8f923"
  ]
}'
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/bulk', {
    method: 'DELETE',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        documentIds: [
            'doc_82fa050abbc44b9587b71c8f84e8f923',
        ],
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.delete(
    "https://api.allsign.io/v3/documents/bulk",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
    json={
        "documentIds": [
            "doc_82fa050abbc44b9587b71c8f84e8f923",
        ],
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 200**

```
{
  "totalCount": 1,
  "successCount": 1,
  "errorCount": 0,
  "items": [
    {
      "documentId": "doc_82fa050abbc44b9587b71c8f84e8f923",
      "status": "deleted",
      "error": null
    }
  ]
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:12 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/documentos.ejemplos.spec.ts`

## Create bulk send

POST `/documents/bulk-sends`

Sube un PDF una sola vez y crea N documentos independientes, uno por destinatario, cada uno con su propio enlace de firma. **Asíncrono**: valida todo de forma síncrona (créditos, tamaño de archivo, forma del body; un correo de destinatario inválido es `422 VALIDATION_ERROR` y no se crea ni se cobra nada) y agenda el trabajo pesado — la respuesta es un **202** con el lote en `processing` y cada `items[].status` en `pending`. Haz *poll* de `GET /documents/bulk-sends/{id}` (Get bulk send) hasta que `status` cambie a `completed` o `partialError`. Cada documento del lote nace con una caja de firma para su destinatario, las mismas cajas automáticas que pone Create document cuando recibe `signers` sin `fields`. **Costo**: cada documento creado se cobra lo mismo que enviarlo por separado con `POST /documents/{id}/send` (los créditos de su `signatureValidation` en tu plan), aunque mandes `sendInvites: false`; no es 1 crédito por documento. El saldo de todo el lote se revisa antes de agendar (`402 INSUFFICIENT_CREDITS`). `Idempotency-Key` es **obligatorio**: un reintento con la misma key devuelve el MISMO 202 + el mismo id de lote (`Idempotency-Replayed: true`) en vez de agendar el trabajo dos veces — nunca cobra créditos ni invita dos veces por un retry.

#### Parámetros

-   `Idempotency-Key` string header requerido
    
    Clave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Cuerpo de la petición

application/json

-   `name` string requerido
    
    Nombre del documento (aparece en el email de invitación de cada destinatario).
    
    de 1 a 255 caracteres
    
-   `file` objeto requerido
    
    El PDF a enviar — el mismo archivo para todos los destinatarios.
    
    Ver 3 atributos hijos
    
    -   `file.content` string requerido
        
        Contenido del archivo codificado en Base64. Máximo 10 MB decodificados.
        
    -   `file.fileType` string
        
        Tipo de archivo. Default `pdf`.
        
        default "pdf"
        
    -   `file.name` string puede ser null
        
        Nombre del archivo (ej. `contrato.pdf`). Se valida contra path traversal.
        
    
-   `recipients` array de objetos requerido
    
    Destinatarios; cada uno recibe su propio documento y enlace de firma. Máximo 200.
    
    máx. 200 elementos · mín. 1 elementos
    
    Ver 3 atributos hijos
    
    -   `recipients[].email` string requerido
        
        Correo del destinatario.
        
    -   `recipients[].name` string puede ser null
        
        Nombre del destinatario (opcional).
        
    -   `recipients[].role` string puede ser null
        
        Nombre del rol del documento al que se enlaza este destinatario. Sin él, el firmante estrena un rol propio y no hereda los campos del rol de la plantilla.
        
    
-   `signatureValidation` objeto puede ser null
    
    Nivel de validez legal, aplicado a cada documento del lote.
    
    Ver 6 atributos hijos
    
    -   `signatureValidation.autografa` boolean
        
        Firma autógrafa (trazo en pantalla).
        
        default true
        
    -   `signatureValidation.nom151` boolean
        
        Constancia de conservación NOM-151.
        
        default false
        
    -   `signatureValidation.fea` boolean
        
        Firma Electrónica Avanzada (FEA/e.firma SAT).
        
        default false
        
    -   `signatureValidation.biometricSignature` boolean
        
        Verificación biométrica (selfie vs. identificación, anti-deepfake).
        
        default false
        
    -   `signatureValidation.idScan` boolean
        
        Escaneo de identificación oficial (INE, pasaporte).
        
        default false
        
    -   `signatureValidation.videofirma` boolean
        
        Graba video del firmante durante el proceso de firma.
        
        default false
        
    
-   `sendInvites` boolean
    
    Si es `false`, crea los documentos sin despachar la invitación de firma todavía.
    
    default true
    

#### Devuelve

**202** El lote agendado — header `Location` apunta a Get bulk send; `status: "processing"`, cada item `pending`.

Ver los 7 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `id` string requerido
    
    ID del lote de envío (`bat_…`).
    
-   `status` enum requerido
    
    Batch-level outcome. `createBulkSend` is asynchronous: it returns `processing` immediately and the client polls `getBulkSend` until `completed` or `partialError`. Open enum (`x-extensible-enum`) — a tolerant reader must not hard-fail on a value it doesn't recognise. Open enum: clients MUST tolerate values not in this list.
    
    Valores: `processing` `completed` `partial_error`
    
-   `totalCount` integer requerido
    
    Destinatarios pedidos.
    
-   `successCount` integer requerido
    
    Documentos creados exitosamente.
    
-   `errorCount` integer requerido
    
    Destinatarios que fallaron — ver `items[].error`.
    
-   `items` array de objetos requerido
    
    Resultado por destinatario, en el orden pedido.
    
    Ver 4 atributos hijos
    
    -   `items[].recipientEmail` string requerido
        
        El correo tal como se envió en la petición.
        
    -   `items[].documentId` string puede ser null
        
        ID del documento creado (`doc_…`). `null` si este destinatario falló.
        
    -   `items[].status` enum requerido
        
        Per-recipient outcome. Open enum — see BulkSendStatus. Open enum: clients MUST tolerate values not in this list.
        
        Valores: `pending` `sent` `created` `error`
        
    -   `items[].error` string puede ser null
        
        Motivo si `status` es `error`.
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [402](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [409](https://allsign.io/developers/docs/errors) [413](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl -X POST 'https://api.allsign.io/v3/documents/bulk-sends' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "v3audit-ejemplos lote",
  "file": {
    "content": "'"$(base64 < contrato.pdf | tr -d '\n')"'",
    "fileType": "pdf",
    "name": "contrato.pdf"
  },
  "recipients": [
    {
      "email": "ana@ejemplo.com",
      "name": "Ana Torres"
    }
  ]
}'
```

**Node**

```
import { randomUUID } from 'node:crypto';
import { readFileSync } from 'node:fs';

const respuesta = await fetch('https://api.allsign.io/v3/documents/bulk-sends', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
        'Idempotency-Key': randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: 'v3audit-ejemplos lote',
        file: {
            content: readFileSync('contrato.pdf').toString('base64'),
            fileType: 'pdf',
            name: 'contrato.pdf',
        },
        recipients: [
            {
                email: 'ana@ejemplo.com',
                name: 'Ana Torres',
            },
        ],
    }),
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import base64
import os
import uuid
from pathlib import Path

import requests

respuesta = requests.post(
    "https://api.allsign.io/v3/documents/bulk-sends",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "name": "v3audit-ejemplos lote",
        "file": {
            "content": base64.b64encode(Path("contrato.pdf").read_bytes()).decode(),
            "fileType": "pdf",
            "name": "contrato.pdf",
        },
        "recipients": [
            {
                "email": "ana@ejemplo.com",
                "name": "Ana Torres",
            },
        ],
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 403 · DEV_FEATURE_RESTRICTED**

```
{
  "type": "https://allsign.io/developers/docs/errors#DEV_FEATURE_RESTRICTED",
  "title": "Forbidden",
  "status": 403,
  "detail": "The feature 'bulk_send' is not available with your current API key (environment: test).",
  "instance": "/v3/documents/bulk-sends",
  "code": "DEV_FEATURE_RESTRICTED",
  "requestId": "req_87e254c1249946cfbdc8516819d10deb",
  "featureRequested": "bulk_send",
  "environment": "test",
  "allowedFeatures": [
    "firma_autografa",
    "firma_simple",
    "embedded_signing"
  ],
  "allowedFeaturesDisplay": [
    "Firma Autógrafa (Wet Signature)",
    "Firma Simple (Click-to-sign)",
    "Embedded Signing Widget"
  ],
  "upgradeMessage": "This feature is only available with a production key (allsign_live_sk_…). Create a live key in your AllSign dashboard under Developers → API Keys.",
  "upgradeUrl": "https://allsign.io/pricing"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:16 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/sistema.ejemplos.spec.ts`

## Get bulk send

GET `/documents/bulk-sends/{batch_id}`

Consulta el resultado de un `createBulkSend` asíncrono. Usa el MISMO objeto que la respuesta 202 original — `status` empieza en `processing` (todos los items `pending`) y se asienta en `completed` o `partialError` una vez que cada destinatario fue intentado.

#### Parámetros

-   `batch_id` string ruta requerido
    
    ID del lote (`bat_…`), del header `Location` de Create bulk send.
    
-   `AllSign-Version` enum header
    
    Fecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400 `UNSUPPORTED_API_VERSION`.
    
    Valores: `2026-07-11`
    

#### Devuelve

**200** El lote — `status`/`items[]` reflejan el progreso más reciente.

Ver los 7 atributos de la respuesta

-   `livemode` boolean requerido
    
    `true` en entorno `live`, `false` en `test`/`dev` (marca de agua, sin validez legal).
    
-   `id` string requerido
    
    ID del lote de envío (`bat_…`).
    
-   `status` enum requerido
    
    Batch-level outcome. `createBulkSend` is asynchronous: it returns `processing` immediately and the client polls `getBulkSend` until `completed` or `partialError`. Open enum (`x-extensible-enum`) — a tolerant reader must not hard-fail on a value it doesn't recognise. Open enum: clients MUST tolerate values not in this list.
    
    Valores: `processing` `completed` `partial_error`
    
-   `totalCount` integer requerido
    
    Destinatarios pedidos.
    
-   `successCount` integer requerido
    
    Documentos creados exitosamente.
    
-   `errorCount` integer requerido
    
    Destinatarios que fallaron — ver `items[].error`.
    
-   `items` array de objetos requerido
    
    Resultado por destinatario, en el orden pedido.
    
    Ver 4 atributos hijos
    
    -   `items[].recipientEmail` string requerido
        
        El correo tal como se envió en la petición.
        
    -   `items[].documentId` string puede ser null
        
        ID del documento creado (`doc_…`). `null` si este destinatario falló.
        
    -   `items[].status` enum requerido
        
        Per-recipient outcome. Open enum — see BulkSendStatus. Open enum: clients MUST tolerate values not in this list.
        
        Valores: `pending` `sent` `created` `error`
        
    -   `items[].error` string puede ser null
        
        Motivo si `status` es `error`.
        
    

Errores posibles (problem+json): [400](https://allsign.io/developers/docs/errors) [401](https://allsign.io/developers/docs/errors) [403](https://allsign.io/developers/docs/errors) [404](https://allsign.io/developers/docs/errors) [422](https://allsign.io/developers/docs/errors) [429](https://allsign.io/developers/docs/errors)

**cURL**

```
curl 'https://api.allsign.io/v3/documents/bulk-sends/bat_e6282f72d60345d384d2b16cf0700624' \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/documents/bulk-sends/bat_e6282f72d60345d384d2b16cf0700624', {
    headers: {
        Authorization: `Bearer ${process.env.ALLSIGN_API_KEY}`,
        'AllSign-Version': '2026-07-11',
    },
});
console.log(respuesta.status, await respuesta.json());
```

**Python**

```
import os

import requests

respuesta = requests.get(
    "https://api.allsign.io/v3/documents/bulk-sends/bat_e6282f72d60345d384d2b16cf0700624",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 404 · BATCH_NOT_FOUND**

```
{
  "type": "https://allsign.io/developers/docs/errors#BATCH_NOT_FOUND",
  "title": "Bulk-send batch not found",
  "status": 404,
  "detail": "No bulk-send batch was found with that id.",
  "instance": "/v3/documents/bulk-sends/bat_e6282f72d60345d384d2b16cf0700624",
  "code": "BATCH_NOT_FOUND",
  "requestId": "req_7e1406b4cbd74967a85f8b8844351fe6"
}
```

Grabado en el entorno interno de AllSign con una key de sandbox · backend `24c0469` · 8 oct 2026, 06:16 (hora CDMX) · test `docs-checks-v3/tests/ejemplos/sistema.ejemplos.spec.ts`
