# Contactos

## Listar contactos

`GET /v1/c/{slug}/contacts` · Alcances: `contacts:read`

Los más activos primero. `q` busca por nombre o teléfono; `tag` filtra por etiqueta; `before` (el `lastActivityAt` del último) trae la página siguiente.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |

### Parámetros de consulta

| Campo | Tipo | Obligatorio | Detalles |
|---|---|---|---|
| `q` | string | no | hasta 200 caracteres |
| `limit` | integer | no | hasta 100; mínimo 1; default `50` |
| `before` | string (date-time) | no |  |
| `tag` | string (uuid) | no |  |

### Ejemplo de solicitud

```bash
curl -X GET "https://api.donetalk.com/v1/c/demo/contacts" \
  -H "Authorization: Bearer $DONETALK_KEY"
```

### Respuesta 200

```json
{
  "contacts": [
    {
      "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
      "displayName": "Ana Souza",
      "address": "5548999990001",
      "channelKind": "whatsapp",
      "source": "api",
      "externalRef": "erp-88213",
      "fields": {
        "cpf": "529.982.247-25",
        "plano": "anual"
      },
      "isBlocked": false,
      "lastActivityAt": "2026-10-22T18:40:02.000Z",
      "createdAt": "2026-09-23T22:19:30.396Z",
      "tags": [
        {
          "id": "01a12150-3610-7c00-b680-188c2b4c7313",
          "name": {
            "pt-BR": "VIP",
            "en": "VIP",
            "es": "VIP"
          },
          "color": "#92400e"
        }
      ]
    }
  ]
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `422` `validation_failed`
- `429` `rate_limited`

## Crear un contacto

`POST /v1/c/{slug}/contacts` · Alcances: `contacts:write`

Para crear o actualizar varios a la vez (o uno que quizás exista), use `POST /contacts/import`.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |

### Cuerpo de la solicitud

| Campo | Tipo | Obligatorio | Detalles |
|---|---|---|---|
| `displayName` | string | sí | hasta 200 caracteres |
| `phone` | string | sí |  |
| `locale` | uno de `pt-BR`, `es`, `en` | no |  |
| `fields` | object | no |  |
| `externalRef` | string | no | hasta 200 caracteres |

### Ejemplo de solicitud

```bash
curl -X POST "https://api.donetalk.com/v1/c/demo/contacts" \
  -H "Authorization: Bearer $DONETALK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "displayName": "Ana Souza",
  "phone": "+5548999990001",
  "externalRef": "erp-88213",
  "fields": {
    "cpf": "529.982.247-25"
  }
}'
```

### Respuesta 201

```json
{
  "contact": {
    "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
    "displayName": "Ana Souza",
    "address": "5548999990001"
  }
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `409` `contact_exists`
- `422` `validation_failed`
- `429` `rate_limited`

## Crear o actualizar contactos (hasta 1.000)

`POST /v1/c/{slug}/contacts/import` · Alcances: `contacts:write`

Por teléfono: los existentes se actualizan (nombre, campos, etiquetas), los nuevos se crean. Cada fila vuelve con el id del contacto. Una fila con problema no detiene las demás.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |

### Cuerpo de la solicitud

| Campo | Tipo | Obligatorio | Detalles |
|---|---|---|---|
| `rows` | lista de objeto | sí | hasta 1000 |
| `rows[].phone` | string | sí | hasta 40 caracteres |
| `rows[].name` | string | no | hasta 200 caracteres |
| `rows[].fields` | object | no |  |
| `rows[].tags` | lista de string | no | hasta 20 |
| `rows[].externalRef` | string | no | hasta 200 caracteres |
| `rows[].marketingOptIn` | boolean | no |  |

### Ejemplo de solicitud

```bash
curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/import" \
  -H "Authorization: Bearer $DONETALK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "rows": [
    {
      "phone": "+5548999990001",
      "name": "Ana Souza",
      "tags": [
        "VIP"
      ],
      "externalRef": "erp-88213"
    },
    {
      "phone": "48 99999-0002",
      "name": "Bruno Lima",
      "fields": {
        "plano": "mensal"
      },
      "marketingOptIn": true
    }
  ]
}'
```

### Respuesta 200

```json
{
  "created": 1,
  "updated": 1,
  "errors": [
    {
      "row": 2,
      "reason": "invalid_phone"
    }
  ],
  "contacts": [
    {
      "row": 0,
      "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
      "created": false
    },
    {
      "row": 1,
      "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9",
      "created": true
    }
  ]
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `422` `validation_failed`
- `429` `rate_limited`

## Ver un contacto

`GET /v1/c/{slug}/contacts/{id}` · Alcances: `contacts:read`

El contacto con sus campos, números, consentimientos, últimas conversaciones y etiquetas, y las definiciones de campos de la empresa.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |

### Ejemplo de solicitud

```bash
curl -X GET "https://api.donetalk.com/v1/c/demo/contacts/:id" \
  -H "Authorization: Bearer $DONETALK_KEY"
```

### Respuesta 200

```json
{
  "contact": {
    "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
    "displayName": "Ana Souza",
    "address": "5548999990001",
    "channelKind": "whatsapp",
    "source": "api",
    "externalRef": "erp-88213",
    "fields": {
      "cpf": "529.982.247-25",
      "plano": "anual"
    },
    "isBlocked": false,
    "lastActivityAt": "2026-10-22T18:40:02.000Z",
    "createdAt": "2026-09-23T22:19:30.396Z",
    "firstName": "Ana",
    "lastName": "Souza",
    "locale": "pt-BR",
    "timezone": null,
    "blockedReason": null
  },
  "identities": [
    {
      "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9",
      "channel_kind": "whatsapp",
      "address": "5548999990001",
      "external_id": null,
      "provider_display_name": "Ana",
      "is_primary": true,
      "last_seen_at": "2026-10-22T18:40:02.000Z"
    }
  ],
  "consents": [
    {
      "purpose": "marketing",
      "channel_kind": "whatsapp",
      "status": "opted_in",
      "source": "api",
      "occurred_at": "2026-10-01T10:00:00.000Z"
    }
  ],
  "conversations": [
    {
      "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
      "status": "closed",
      "source_kind": "campaign",
      "imported_from": null,
      "created_at": "2026-10-24T12:00:04.000Z",
      "closed_at": "2026-10-24T12:20:41.000Z",
      "channel_id": "01a0cccc-0000-7000-8000-000000000002",
      "outcome_code": "converted",
      "is_success": true
    }
  ],
  "tags": [
    {
      "id": "01a12150-3610-7c00-b680-188c2b4c7313",
      "name": {
        "pt-BR": "VIP",
        "en": "VIP",
        "es": "VIP"
      },
      "color": "#92400e"
    }
  ],
  "fieldDefinitions": [
    {
      "key": "cpf",
      "label": {
        "pt-BR": "CPF",
        "en": "CPF",
        "es": "CPF"
      },
      "type": "cpf",
      "options": null,
      "ai_extractable": true,
      "required": false,
      "sort": 1
    }
  ]
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `404` `contact_not_found`
- `422` `validation_failed`
- `429` `rate_limited`

## Editar un contacto

`PATCH /v1/c/{slug}/contacts/{id}` · Alcances: `contacts:write`

`fields` se combina con los campos del contacto; envíe `null` en un campo para borrarlo.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |

### Cuerpo de la solicitud

| Campo | Tipo | Obligatorio | Detalles |
|---|---|---|---|
| `displayName` | string | no | hasta 200 caracteres |
| `firstName` | string | no | hasta 100 caracteres; null |
| `lastName` | string | no | hasta 100 caracteres; null |
| `locale` | uno de `pt-BR`, `es`, `en` | no | null |
| `externalRef` | string | no | hasta 200 caracteres; null |
| `fields` | object | no |  |
| `isBlocked` | boolean | no |  |
| `blockedReason` | string | no | hasta 200 caracteres; null |

### Ejemplo de solicitud

```bash
curl -X PATCH "https://api.donetalk.com/v1/c/demo/contacts/:id" \
  -H "Authorization: Bearer $DONETALK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fields": {
    "plano": "anual"
  },
  "externalRef": "erp-88213"
}'
```

### Respuesta 200

```json
{
  "ok": true
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `404` `contact_not_found`
- `422` `validation_failed`
- `429` `rate_limited`

## Registrar consentimiento

`POST /v1/c/{slug}/contacts/{id}/consents` · Alcances: `contacts:write`

Opt-in u opt-out por finalidad (atención, utilidad, marketing). Un opt-out de marketing saca al contacto de las campañas de marketing.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |

### Cuerpo de la solicitud

| Campo | Tipo | Obligatorio | Detalles |
|---|---|---|---|
| `purpose` | uno de `service`, `utility`, `marketing` | sí |  |
| `status` | uno de `opted_in`, `opted_out` | sí |  |
| `source` | uno de `form`, `import`, `api`, `message`, `keyword` | no | default `"form"` |
| `evidence` | object | no |  |

### Ejemplo de solicitud

```bash
curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/:id/consents" \
  -H "Authorization: Bearer $DONETALK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "purpose": "marketing",
  "status": "opted_in",
  "source": "api"
}'
```

### Respuesta 201

```json
{
  "ok": true
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `404` `contact_not_found`
- `422` `validation_failed`
- `429` `rate_limited`

## Poner una etiqueta

`PUT /v1/c/{slug}/contacts/{id}/tags/{tagId}` · Alcances: `contacts:write`

Puede iniciar los flujos que empiezan cuando se pone esta etiqueta.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |
| `tagId` | El id de la etiqueta. |

### Ejemplo de solicitud

```bash
curl -X PUT "https://api.donetalk.com/v1/c/demo/contacts/:id/tags/:tagId" \
  -H "Authorization: Bearer $DONETALK_KEY"
```

### Respuesta 200

```json
{
  "ok": true
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `422` `validation_failed`
- `429` `rate_limited`

## Quitar una etiqueta

`DELETE /v1/c/{slug}/contacts/{id}/tags/{tagId}` · Alcances: `contacts:write`

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |
| `tagId` | El id de la etiqueta. |

### Ejemplo de solicitud

```bash
curl -X DELETE "https://api.donetalk.com/v1/c/demo/contacts/:id/tags/:tagId" \
  -H "Authorization: Bearer $DONETALK_KEY"
```

### Respuesta 200

```json
{
  "ok": true
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `422` `validation_failed`
- `429` `rate_limited`

## Fichas de contexto

`GET /v1/c/{slug}/contacts/{id}/context-cards` · Alcances: `contacts:read`

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |

### Ejemplo de solicitud

```bash
curl -X GET "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards" \
  -H "Authorization: Bearer $DONETALK_KEY"
```

### Respuesta 200

```json
{
  "cards": [
    {
      "key": "erp",
      "source": "ERP Captei",
      "title": "Cliente desde 2023",
      "status": "Plano anual",
      "tone": "success",
      "fields": [
        {
          "label": "Pedidos",
          "value": "14"
        }
      ],
      "link": {
        "url": "https://erp.captei.com.br/clientes/88213",
        "label": "Abrir no ERP"
      },
      "updatedAt": "2026-10-23T13:02:11.000Z"
    }
  ]
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `422` `validation_failed`
- `429` `rate_limited`

## Mostrar una ficha a quien atiende

`PUT /v1/c/{slug}/contacts/{id}/context-cards/{key}` · Alcances: `contacts:write`

Una ficha de su sistema que aparece junto a la conversación (plan, pedidos, saldo). La misma `key` reemplaza la anterior.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |
| `key` | La clave (del campo o de la ficha). |

### Cuerpo de la solicitud

| Campo | Tipo | Obligatorio | Detalles |
|---|---|---|---|
| `title` | string | sí | hasta 120 caracteres |
| `source` | string | no | hasta 60 caracteres |
| `status` | string | no | hasta 60 caracteres; null |
| `tone` | uno de `neutral`, `success`, `warning`, `danger`, `info` | no | default `"neutral"` |
| `fields` | lista de objeto | no | hasta 12; default `[]` |
| `fields[].label` | string | sí | hasta 60 caracteres |
| `fields[].value` | string | sí | hasta 300 caracteres |
| `link` | objeto | no | null |
| `link.url` | string (uri) | sí | hasta 2000 caracteres |
| `link.label` | string | no | hasta 60 caracteres |

### Ejemplo de solicitud

```bash
curl -X PUT "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards/:key" \
  -H "Authorization: Bearer $DONETALK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Cliente desde 2023",
  "source": "ERP Captei",
  "status": "Plano anual",
  "tone": "success",
  "fields": [
    {
      "label": "Pedidos",
      "value": "14"
    }
  ],
  "link": {
    "url": "https://erp.captei.com.br/clientes/88213",
    "label": "Abrir no ERP"
  }
}'
```

### Respuesta 200

```json
{
  "card": {
    "key": "erp",
    "source": "ERP Captei",
    "title": "Cliente desde 2023",
    "status": "Plano anual",
    "tone": "success",
    "fields": [
      {
        "label": "Pedidos",
        "value": "14"
      }
    ],
    "link": {
      "url": "https://erp.captei.com.br/clientes/88213",
      "label": "Abrir no ERP"
    },
    "updatedAt": "2026-10-23T13:02:11.000Z"
  }
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `422` `validation_failed`
- `429` `rate_limited`

## Quitar una ficha

`DELETE /v1/c/{slug}/contacts/{id}/context-cards/{key}` · Alcances: `contacts:write`

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |
| `key` | La clave (del campo o de la ficha). |

### Ejemplo de solicitud

```bash
curl -X DELETE "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards/:key" \
  -H "Authorization: Bearer $DONETALK_KEY"
```

### Respuesta 200

```json
{
  "ok": true
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `422` `validation_failed`
- `429` `rate_limited`

## Borrar los datos del contacto (LGPD)

`POST /v1/c/{slug}/contacts/{id}/erase` · Alcances: `contacts:delete`

A pedido del titular: el contacto y sus mensajes se anonimizan para siempre. No se puede deshacer.

### Parámetros de la dirección

| Campo | Detalles |
|---|---|
| `slug` | El identificador de la empresa en DoneTalk (el de la clave). |
| `id` | El id del registro. |

### Ejemplo de solicitud

```bash
curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/:id/erase" \
  -H "Authorization: Bearer $DONETALK_KEY"
```

### Respuesta 200

```json
{
  "ok": true
}
```

### Errores posibles

- `401` `unauthorized`
- `403` `insufficient_scope`
- `404` `contact_not_found`
- `422` `validation_failed`
- `429` `rate_limited`

