---
title: "Avisa a alguien más y cambia al responsable de un documento — Receta de la API v3 de AllSign"
type: how-to
canonical_url: "https://allsign.io/developers/docs/recetas/observadores-y-transferencia"
api_version: "2026-07-11"
agent_rules: [webhook-no-polling, idempotency-key, una-base-url, error-por-code, reintento-429]
last_verified: "2026-10-08T12:18:28.904Z"
---

Receta

# Avisa a alguien más y cambia al responsable de un documento

**Objetivo:** Una persona de fuera se entera de cómo va un documento sin firmarlo, y otra persona de tu equipo queda como su responsable.

Para: admin · nivel inicial · 5 min · Necesitas: API key de sandbox · Un segundo miembro en tu equipo

## Para agentes y asistentes de IA

-   **Para saber que un documento quedó firmado, espera el webhook `document.completed`; no consultes `GET /v3/documents/{id}` en un bucle.** → [Webhooks](https://allsign.io/developers/docs/webhooks)
-   **Todo `POST` que crea, cobra o envía algo lleva `Idempotency-Key` con un UUID v4 nuevo por operación.** → [Idempotencia](https://allsign.io/developers/docs/idempotency)
-   **La base URL es siempre `https://api.allsign.io/v3`; no existe una URL de sandbox aparte.** → [Entornos](https://allsign.io/developers/docs/environments)
-   **Los errores son `application/problem+json` (RFC 9457) con un `code` estable y append-only; `detail` es texto técnico en inglés que puede cambiar.** → [Errores](https://allsign.io/developers/docs/errors)
-   **Ante un `429`, espera los segundos de `Retry-After` antes de reintentar; si el `429` no trae `Retry-After`, no lo reintentes.** → [Rate limits](https://allsign.io/developers/docs/rate-limits)

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`

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_…"`).

## 1 Crea el documento

POST `/documents` [ver en la referencia](https://allsign.io/developers/docs/endpoints/documents#create-document)

### Qué haces

ownerId es la persona de tu equipo responsable del documento: hoy eres tú, porque es tu key.

### Qué mirar

-   `id` = `"doc_f2344cc1b9b24ba2954715812b3d7242"`
-   `ownerId` = `"usr_550487c74d4a4061ba2af6b802dcacde"`

### En producción

Los observadores y el traspaso de dueño se activan por cuenta y en producción pueden venir apagados. Mientras no estén activos en la tuya, esas llamadas responden 403 FEATURE\_NOT\_AVAILABLE y no cambian nada; pide que los activen.

**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": "Convenio de colaboración",
  "file": {
    "content": "'"$(base64 < contrato.pdf | tr -d '\n')"'",
    "fileType": "pdf",
    "name": "contrato.pdf"
  },
  "signers": [
    {
      "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', {
    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: 'Convenio de colaboración',
        file: {
            content: readFileSync('contrato.pdf').toString('base64'),
            fileType: 'pdf',
            name: 'contrato.pdf',
        },
        signers: [
            {
                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",
    headers={
        "Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}",
        "AllSign-Version": "2026-07-11",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "name": "Convenio de colaboración",
        "file": {
            "content": base64.b64encode(Path("contrato.pdf").read_bytes()).decode(),
            "fileType": "pdf",
            "name": "contrato.pdf",
        },
        "signers": [
            {
                "email": "ana@ejemplo.com",
                "name": "Ana Torres",
            },
        ],
    },
)
print(respuesta.status_code, respuesta.json())
```

**Respuesta · 201**

```
{
  "livemode": false,
  "id": "doc_f2344cc1b9b24ba2954715812b3d7242",
  "object": "document",
  "name": "Convenio de colaboración",
  "status": "draft",
  "documentType": "EDITABLE",
  "signerCount": 1,
  "signedCount": 0,
  "ownerId": "usr_550487c74d4a4061ba2af6b802dcacde",
  "orgId": "c313ca9b-d63c-4c74-a3ab-2d9f2f98a61b",
  "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"
}
```

## 2 Agrega a alguien que solo observa

POST `/documents/{document_id}/observers` [ver en la referencia](https://allsign.io/developers/docs/endpoints/documents#add-document-observer)

### Qué haces

Un observador nunca firma ni recibe campos: solo los avisos que eliges en events. En cuanto lo agregas le llega un correo que se lo dice; con notify\_and\_view ese correo trae la liga para abrir el documento, y con notify (el predeterminado) solo recibe los avisos.

### Qué mirar

-   `observer.id` = `"rol_9f8c7b2441a646b5aacbd925b2d3b6d9"`
-   `observer.capability` = `"notify_and_view"`
-   `created` = `true`

**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
}
```

## 3 Revisa quién observa el documento

GET `/documents/{document_id}/observers` [ver en la referencia](https://allsign.io/developers/docs/endpoints/documents#list-document-observers)

### Qué haces

Los observadores no aparecen entre los firmantes ni cuentan en signerCount.

### Qué mirar

-   `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"}]`

**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
}
```

## 4 Quita al observador

DELETE `/documents/{document_id}/observers/{observer_id}` [ver en la referencia](https://allsign.io/developers/docs/endpoints/documents#remove-document-observer)

### Qué haces

Desde este momento ya no recibe avisos de este documento.

### Qué mirar

-   `deleted` = `true`

**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
}
```

## 5 Busca a quién pasarle el documento

GET `/users/team` [ver en la referencia](https://allsign.io/developers/docs/endpoints/users#list-team-members)

### Qué haces

El nuevo responsable tiene que ser miembro de tu equipo: toma su id de esta lista.

### Qué mirar

-   `data` = `[{"id":"usr_550487c74d4a4061ba2af6b802dcacde","name":"Sofía Herrera","email":"sofia@ejemplo.com","role":"owner"},{"id":"usr_b478f972e8574a739be5fb7364382c33","name":"Carlos Méndez","email":"carlos@ejemplo.com","role":"developer"}]`

**cURL**

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

**Node**

```
const respuesta = await fetch('https://api.allsign.io/v3/users/team', {
    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/users/team",
    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": [
    {
      "id": "usr_550487c74d4a4061ba2af6b802dcacde",
      "name": "Sofía Herrera",
      "email": "sofia@ejemplo.com",
      "role": "owner"
    },
    {
      "id": "usr_b478f972e8574a739be5fb7364382c33",
      "name": "Carlos Méndez",
      "email": "carlos@ejemplo.com",
      "role": "developer"
    }
  ],
  "hasMore": false,
  "nextCursor": null,
  "previousCursor": null,
  "limit": null
}
```

## 6 Traspasa el documento

POST `/documents/{document_id}/transfer-owner` [ver en la referencia](https://allsign.io/developers/docs/endpoints/documents#transfer-document-owner)

### Qué haces

El documento, sus firmantes y su historial no cambian: solo quién es su responsable. reason queda en la bitácora del documento.

### Qué mirar

-   `ownerId` = `"usr_b478f972e8574a739be5fb7364382c33"`
-   `previousOwnerId` = `"usr_550487c74d4a4061ba2af6b802dcacde"`
-   `transferred` = `true`

**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"
  ]
}
```

## 7 Traspasa varios de una vez

POST `/documents/transfer-owner` [ver en la referencia](https://allsign.io/developers/docs/endpoints/documents#transfer-documents-owner)

### Qué haces

Manda documentIds con la lista que quieres mover, o fromUserId para mover todos los documentos de una persona, por ejemplo cuando deja la empresa. keepPreviousOwnerAccess es true por defecto: el dueño anterior conserva el acceso; mándalo en false para quitárselo.

### Qué mirar

-   `transferredCount` = `1`
-   `items` = `[{"documentId":"doc_f2344cc1b9b24ba2954715812b3d7242","status":"transferred","error":null}]`

**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
    }
  ]
}
```

## Errores comunes de esta receta

Errores reales que el test de esta receta provocó a propósito en sandbox, sobre sus mismos pasos. Cada uno enlaza a su explicación en [Errores](https://allsign.io/developers/docs/errors).

`OBSERVER_IS_SIGNER` · 409 · en el paso 2 (Agrega a alguien que solo observa)

Agrega como observador a quien ya firma. [Qué significa y qué hacer](https://allsign.io/developers/docs/errors#OBSERVER_IS_SIGNER)

**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:18 (hora CDMX) · test `docs-checks-v3/tests/recetas/observadores-y-transferencia.receta.spec.ts`

`OBSERVER_NOT_FOUND` · 404 · en el paso 4 (Quita al observador)

Quita un observador que no existe. [Qué significa y qué hacer](https://allsign.io/developers/docs/errors#OBSERVER_NOT_FOUND)

**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`

`VALIDATION_ERROR` · 422 · en el paso 6 (Traspasa el documento)

Traspasa a alguien fuera de tu equipo. [Qué significa y qué hacer](https://allsign.io/developers/docs/errors#VALIDATION_ERROR)

**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`

## Siguiente

-   [Recibe y verifica los webhooks de AllSign](https://allsign.io/developers/docs/recetas/recibe-y-verifica-webhooks) — Un endpoint que recibe los eventos de AllSign, comprueba que de verdad los firmó AllSign y sobrevive a sus propias caídas y a la rotación del secreto.
