# Referencia completa del contexto plz

> Referencia completa del contexto plz

Source: https://docs.plazbot.com/kb/referencia-completa-del-contexto-plz

Este documento describe todo lo que un worker de Plazbot puede usar: los tipos de worker, el objeto `plz` que recibe cada handler, todos sus módulos y métodos, y **todos los campos del contacto** que devuelve `plz.contacts`.

* * *

## 1\. Tipos de worker

Todos se importan de `plazbot/workers`. El handler puede llamarse `handler` o `run` (el runtime acepta los dos).

Función

Qué hace

Firma del handler

`defineTool`

Herramienta que un agente IA ejecuta durante una conversación.

`handler(input, plz)`

`defineWorker`

Escucha eventos de la plataforma (mensaje recibido, contacto creado, etc.).

`handler(event, plz)`

`defineWebhook`

Endpoint HTTP público que recibe llamadas de apps externas.

`handler(request, plz)`

`defineSchedule`

Tarea programada con expresión cron.

`handler(plz)`

`defineSync`

Sincroniza datos de un sistema externo hacia los contactos.

`fetch(plz)` + `map(item)`

### Campos comunes de configuración

Campo

Tipo

Descripción

`name`

`string`

Nombre único del worker (slug). Obligatorio.

`reference`

`string`

Descripción de lo que hace. En un tool, el agente IA la usa para decidir cuándo invocarlo.

### `defineTool`

Campo

Tipo

Descripción

`parameters`

`object`

Parámetros que el agente extrae de la conversación. Cada uno: `type` (`string`, `number`, `boolean`, `date`, `email`, `phone`), `description`, `promptHint` (pregunta que hace el agente si falta el dato), `required`, `enum`, `default`.

`handler(input, plz)`

función

Devuelve `{ result, data?, actions? }`.

Respuesta del tool:

Campo

Tipo

Descripción

`result`

`string`

Texto que el agente usa para formular su respuesta.

`data`

`object`

Datos estructurados opcionales.

`actions`

`array`

Acciones automáticas sobre el contacto: `{ type, value, code? }` con `type` = `tag`, `removeTag`, `setVariable` (usa `code`), `setStage`, `setSegmentation`, `assignAgent` o `resolve`.

### `defineWorker` (eventos)

Campo

Tipo

Descripción

`events`

`string[]`

Eventos que lo disparan. Al menos uno.

Eventos disponibles: `message.received`, `message.image.received`, `message.audio.received`, `message.document.received`, `contact.created`, `contact.existing`, `contact.deleted`, `contact.blocked`, `contact.from.ad`, `conversation.assigned`, `conversation.resolved`, `conversation.reopened`.

### `defineWebhook`

Campo

Tipo

Descripción

`method`

`string`

`GET`, `POST`, `PUT`, `PATCH` o `DELETE`.

URL generada: `https://workers.plazbot.com/<workspaceId>/<name>`.

El `request` trae `method`, `headers`, `query`, `body`, `ip` y `url`. El handler devuelve `{ status, headers?, body? }`.

### `defineSchedule`

Campo

Tipo

Descripción

`cron`

`string`

Expresión cron de 5 campos. Ej: `'0 22 * * *'` todos los días a las 10 p. m.; `'0 9 * * 1-5'` lunes a viernes a las 9 a. m.; `'0 */4 * * *'` cada 4 horas.

`timezone`

`string`

Zona horaria IANA opcional (ej. `America/Lima`).

### `defineSync`

Campo

Tipo

Descripción

`source`

`string`

Nombre del sistema origen (HubSpot, Stripe, etc.).

`schedule`

`string`

Expresión cron de ejecución.

`fetch(plz)`

función

Trae los registros del sistema externo. Puede usar `plz.cursor` y `plz.setCursor()`.

`map(item)`

función

Convierte un registro en `{ match: { phone?, email?, id? }, variables?, contact?: { name?, tags?, stage?, segmentation? } }`. Devolver `null` para saltarlo.

`onComplete(stats, plz)`

función

Opcional. `stats`: `total`, `created`, `updated`, `skipped`, `errors`, `duration`.

* * *

## 2\. El objeto `plz`

Propiedad

Descripción

`plz.workspaceData.id`

ID del workspace (sin llamada a la API).

`plz.contacts`

Contactos: listar, buscar, crear, editar, variables, etiquetas, fases, agente.

`plz.whatsapp`

Enviar mensajes, archivos y plantillas de WhatsApp.

`plz.conversations`

Mensajes de un contacto, notas, resolver y reabrir.

`plz.agents`

Agentes IA: obtener, listar y conversar.

`plz.templates`

Plantillas de WhatsApp.

`plz.workspace`

Datos maestros: variables, etiquetas, fases, segmentaciones y miembros.

`plz.sheets`

Google Sheets (integración conectada).

`plz.calendar`

Google Calendar (integración conectada).

`plz.docs`

Google Docs (integración conectada).

`plz.kv`

Almacén clave-valor persistente del workspace.

`plz.api`

Llamadas autenticadas a cualquier endpoint de la API de Plazbot.

`plz.fetch`

`fetch` estándar para APIs externas.

`plz.log`

Logs visibles en el historial del worker.

`plz.env`

Secrets del workspace (`plz.env.MI_KEY`).

`plz.cursor` / `plz.setCursor()`

Cursor de sincronización (solo en `defineSync`).

* * *

## 3\. `plz.contacts`

### Métodos

Método

Devuelve

Descripción

`get(id)`

Contacto

Un contacto por su ID, con todos sus campos.

`list({ filter?, limit?, offset? })`

Contacto\[\]

Contactos ordenados por último mensaje (más reciente primero). `limit` default 20, tope 1000.

`listPage({ cursor?, pageSize? })`

`{ items, nextCursor }`

Una página de contactos. Repetir con `nextCursor` hasta que llegue `null`. `pageSize` de 1 a 100 (default 20).

`search({ phone })`

respuesta API

Busca por número (`internalWhatsappNumber`, coincidencia exacta). Los contactos vienen en `res.data.data`.

`search({ email })`

respuesta API

Busca por email exacto. Los contactos vienen en `res.data.data`.

`create(data)`

respuesta API

Crea un contacto. Ver campos de creación más abajo.

`update(id, data)`

respuesta API

Actualiza cualquier campo editable del contacto (ver tabla de campos).

`delete(ids)`

respuesta API

Elimina varios contactos por ID.

`getVariable(contactId, code)`

`string | null`

Valor de una variable personalizada.

`setVariable(contactId, code, value)`

respuesta API

Crea o actualiza una variable personalizada. `null` la deja vacía.

`addTag(contactId, tag)`

respuesta API

Agrega una etiqueta por **nombre o ID**. Falla si la etiqueta no existe en el workspace.

`removeTag(contactId, tag)`

respuesta API

Quita una etiqueta por nombre o ID.

`setStage(contactId, stage)`

respuesta API

Cambia la fase por nombre o ID.

`bulkUpdateStage(fromStage, toStage)`

respuesta API

Mueve **todos** los contactos de una fase a otra (nombre o ID).

`setSegmentation(contactId, segmentation)`

respuesta API

Cambia la segmentación por nombre o ID.

`assignAgent(contactId, agent)`

respuesta API

Asigna un agente por email, nombre, nombre completo o ID de usuario.

`resolve(contactId)`

respuesta API

Marca la conversación como resuelta.

"Respuesta API" significa el formato estándar `{ success, code, message, data }`.

### Filtros de `list`

Filtro

Tipo

Coincide con

`tags`

`string[]`

Contactos que tienen **todas** las etiquetas (por ID o nombre).

`stage`

`string`

ID de la fase (`stageId`).

`isSolved`

`boolean`

Resuelto (`true`) o pendiente (`false`).

`assignedAgentId`

`string`

ID del agente asignado.

`search`

`string`

Texto contenido en `name`, `lastname`, `email`, `phoneNumber` o `internalWhatsappNumber`.

**Importante:** `list` y `listPage` no devuelven contactos **archivados** (`isArchived = true`) ni **ocultos del chat** (`isShowInChat = false`). Para esos, usa `get(id)` o `search`.

Los filtros de `list` se aplican después de leer cada página, así que filtros muy restrictivos sobre workspaces grandes pueden hacer muchas llamadas (tope interno de 100 páginas de 100 contactos).

* * *

## 4\. Campos del contacto

Esto es lo que devuelven `get`, `list`, `listPage` y `search`.

### Identidad y datos básicos

Campo

Tipo

Descripción

`id`

`string`

ID único del contacto.

`workspaceId`

`string`

Workspace al que pertenece.

`name`

`string`

Nombre.

`lastname`

`string`

Apellido.

`alias`

`string`

Alias o apodo.

`email`

`string`

Correo electrónico.

`phoneNumber`

`string`

Teléfono principal.

`phoneNumber2`

`string`

Teléfono secundario.

`phoneNumber3`

`string`

Tercer teléfono.

`internalWhatsappNumber`

`string`

Número/identificador del canal con el que habla el contacto (en WhatsApp, el número con código de país). Es el que usa `search({ phone })`.

`isoCountryCode`

`string`

Código ISO del país (ej. `PE`).

`phoneCountryDialCode`

`string`

Código de marcación (ej. `51`).

`documentNumber`

`string`

Número de documento (DNI, RUC, etc.).

`businessName`

`string`

Razón social o empresa.

`externalReferenceId`

`string`

ID del contacto en un sistema externo.

`avatarColor`

`string`

Color del avatar.

`creationDate`

`string` (fecha ISO)

Fecha de creación.

`extraData1` … `extraData4`

`string`

Campos libres adicionales.

### Canal y plataforma

Campo

Tipo

Descripción

`platformId`

`number`

Canal: 1 webchat, 2 WhatsApp, 3 Facebook, 4 Instagram, 5 Telegram, 6 portal, 7 código, 8 llamadas, 9 Facebook Leads, 10 Tickos, 11 TikTok.

`integrationId`

`string`

ID de la integración (línea) por la que entró.

`platformSenderId`

`string`

En el listado de WhatsApp viene reemplazado por el **alias de la línea** de WhatsApp.

`platformSenderName`

`string`

Nombre del remitente en la plataforma.

`platformSenderPhone`

`string`

Teléfono del remitente en la plataforma.

`isWhatsappBusiness`

`boolean`

Si el contacto usa WhatsApp Business.

`whatsappUsername`

`string`

Usuario de WhatsApp.

`whatsappWaId`

`string`

wa\_id de WhatsApp.

`whatsappBsuid`

`string`

Identificador BSUID de WhatsApp.

`isFromCall`

`boolean`

Contacto creado desde una llamada.

### Gestión (fase, agente, estado)

Campo

Tipo

Descripción

`stageId`

`string`

ID de la fase. Para el nombre usa `plz.workspace.getStage(stageId)`.

`segmentationId`

`string`

ID de la segmentación. Nombre con `plz.workspace.getSegmentation(id)`.

`assignedAgentId`

`string`

ID del agente asignado.

`assignedAgentName`

`string`

Nombre del agente asignado.

`assignedAgentDate`

`string` (fecha)

Fecha de la última asignación.

`alternAgents`

`array`

Agentes alternos: `[{ AgentId }]`.

`isSolved`

`boolean`

Conversación resuelta.

`solvedByAgentId`

`string`

Quién la resolvió.

`solvedDate`

`string` (fecha)

Cuándo se resolvió.

`isRead`

`boolean`

Si el último mensaje fue leído.

`isBotEnabled`

`boolean`

Si el bot/agente IA está activo para este contacto.

`isBlocked`

`boolean`

Contacto bloqueado.

`isManuallyAdded`

`boolean`

Creado a mano (no por mensaje entrante).

`isShowInChat`

`boolean`

Si aparece en la bandeja de chats.

`isArchived`

`boolean`

Contacto archivado.

`archivedByAgentId`

`string`

Quién lo archivó.

`archivedDate`

`string` (fecha)

Cuándo se archivó.

`rejectReasonContent`

`string`

Motivo de rechazo.

`rejectReasonDate`

`string` (fecha)

Fecha del rechazo.

`orderInCards`

`number`

Posición en la vista Kanban.

### Mensajes y actividad

Campo

Tipo

Descripción

`lastMessage`

`string`

Texto del último mensaje.

`lastMessageDate`

`string` (fecha)

Fecha del último mensaje (orden del listado).

`firstMessage`

`string`

Primer mensaje.

`firstMessageDate`

`string` (fecha)

Fecha del primer mensaje.

`firstAgentMessageDate`

`string` (fecha)

Primera respuesta de un agente.

`lastImageReceived`

`string`

URL de la última imagen recibida.

`lastAudioReceived`

`string`

URL del último audio recibido.

`last_agent_touch`

`string` (fecha)

Última acción de un agente humano desde el panel. Solo lectura.

`last_lead_activity`

`string` (fecha)

Último mensaje entrante del contacto. Solo lectura.

`last_activity`

`string` (fecha)

La más reciente de las dos anteriores. Solo lectura.

### Etiquetas, variables y archivos

Campo

Tipo

Descripción

`tags`

`array`

`[{ id, name, color, assignmentDate }]`. En el listado solo vienen etiquetas activas, con nombre y color actualizados.

`variables`

`array`

Variables personalizadas: `[{ code, val, dateUpdated }]`. Ej.: `contact.variables.find(v => v.code === 'ctc_plan')?.val`.

`files`

`array`

Archivos adjuntos: `[{ id, filename, urlFile, pathFile, userCreation, creationDate, fileSize }]`.

### Anuncios y formularios

Campo

Tipo

Descripción

`adsReferralData`

`object`

Datos del anuncio de origen: `type`, `title`, `body`, `adId`, `url`, `mediaType`, `videoUrl`, `thumbnailUrl`, `ctwaClid`, `welcomeMessage`.

`leadFormId`

`string`

ID del formulario de Meta Leads.

`leadFormName`

`string`

Nombre del formulario.

`leadsFormData`

`array`

Respuestas de formularios: `[{ formId, formName, formFields: [{ name, value }] }]`.

### Historial y seguimiento

Campo

Tipo

Descripción

`tracking`

`array`

Bitácora: `[{ type, userId, userAgentId, value, date, details }]`. `type`: `contact_assigned`, `contact_unassigned`, `stage_changed`, `segmentation_changed`, `tags_changed`, `contact_solved`, `contact_open`, `first_message_user`.

`executedRules`

`array`

Reglas ejecutadas: `[{ ruleId, ruleName, trigger, executionDate }]`.

`surveyHistory`

`array`

Encuestas respondidas: `[{ id, surveyId, score, starRating, additionalQuestion: [{ question, answer }], creationDate }]`.

`currentSequence`

`object`

Secuencia activa: `sequenceId`, `currentStepId`, `nextStepId`, `lastExecutionDate`, `nextExecutionDate`, `isActive`, `isPaused`, `isCompleted`, `pausedReason`, `endReason`, `lastError`.

`events`

`array`

Citas/eventos: `[{ id, title, description, startDate, endDate, allDay, eventStatus (pending/confirmed/cancelled), eventOrigin (agent/automation/manually), agentId, automationId, integrationId, variables }]`.

`tickets`

`array`

Tickets de Zendesk: `[{ id, subject, description, status, url, creationDate }]`.

`lastSummaryEmailDate`

`string` (fecha)

Último correo de resumen enviado.

`lastAiSummaryDate`

`string` (fecha)

Último resumen IA generado.

### Integraciones externas

Campo

Descripción

`hubspotReferenceId`

ID del contacto en HubSpot.

`zohoReferenceId`

ID en Zoho.

`mailchimpReferenceId`

ID en Mailchimp.

`activeCampaignReferenceId` / `activeCampaignReferenceHash`

ID y hash en ActiveCampaign.

`transferSourceWorkspaceId` / `transferStatus`

Transferencia entre workspaces (`InProgress`, `Completed`, `Failed`).

### Campos para `create`

Obligatorios: `name` y `platformId` (el `workspaceId` lo pone el runtime).

Opcionales: `lastname`, `email`, `phoneNumber`, `internalWhatsappNumber`, `stageId`, `isoCountryCode`, `phoneCountryDialCode`, `externalReferenceId`, `integrationId`, `customFields` (`[{ code, value }]` para variables).

### Campos que no se pueden cambiar con `update`

`id`, `workspaceId`, `internalWhatsappNumber`, `platformId`, `last_agent_touch`, `last_lead_activity` y `last_activity`. Cualquier otro campo de la tabla se puede enviar en `update(id, { ... })`.

* * *

## 5\. Los demás módulos

### `plz.whatsapp`

Método

Descripción

`send({ to, message })`

Envía un texto al número `to`.

`sendMedia({ to, url, caption?, filename? })`

Envía un archivo por URL.

`sendTemplate({ ... })`

Envía una plantilla. Campos: `to`, `template`, `variablesBody` y `variablesHeader` (`[{ variable, value }]`), `file` (`{ fileUrl, fileName }`).

`getHistory(contactId)`

Mensajes del contacto.

### `plz.conversations`

Método

Descripción

`get(contactId)` / `getMessages(contactId)`

Mensajes del contacto.

`addNote(contactId, content)`

Guarda una nota interna (no se envía al contacto).

`resolve(contactId)`

Marca resuelto.

`reopen(contactId)`

Reabre la conversación.

### `plz.agents`

Método

Descripción

`get(id)`

Un agente IA.

`list()`

Todos los agentes.

`chat({ agentId, question, sessionId })`

Pregunta al agente. Devuelve la respuesta (`answer`, `sources`, `actionsExecuted`).

### `plz.templates`

Método

Descripción

`list()`

Todas las plantillas de WhatsApp.

`getActive()`

Solo las aprobadas/activas.

### `plz.workspace`

Método

Descripción

`get()`

Datos completos del workspace.

`getVariables()`

Variables personalizadas definidas.

`getTags()` / `getTag(idONombre)`

Etiquetas activas.

`getStages()` / `getStage(idONombre)`

Fases.

`getSegmentations()` / `getSegmentation(idONombre)`

Segmentaciones.

`getMembers()`

Miembros del equipo.

### `plz.sheets` (Google Sheets)

`document` acepta el ID o la URL completa. `account` (email de Google) o `credentialId` solo hacen falta si hay más de una cuenta conectada.

Método

Descripción

`getRows({ document, sheet, filters? })`

Filas como objetos `{ "Columna": "valor" }` (fila 1 = encabezados). `filters`: `[{ column, value, connectorNext: 'AND' | 'OR' }]`, coincidencia parcial sin distinguir mayúsculas.

`appendRow({ document, sheet, values })`

Agrega una fila; `values` en el orden de las columnas.

`updateRows({ document, sheet, filters, newValues })`

Actualiza las filas que cumplen los filtros.

`getSheets({ document })`

Pestañas con sus columnas.

`findDocuments({ text? })`

Busca hojas en el Drive por nombre.

### `plz.calendar` (Google Calendar)

Método

Descripción

`getCalendars()`

Calendarios de la cuenta.

`getEvents({ calendarId, timeMin?, timeMax?, limit?, timeZone? })`

Eventos en un rango (fechas ISO).

`availability({ calendarId, timeMin?, timeMax?, timeZone? })`

Franjas ocupadas.

`createEvent({ calendarId, start, end, title?, description?, timeZone?, createMeetLink? })`

Crea un evento (opcionalmente con Meet).

`updateEvent({ calendarId, eventId, values })`

`values`: `title`, `description`, `startDate`, `endDate`.

`deleteEvent({ calendarId, eventId })`

Elimina un evento.

### `plz.docs` (Google Docs)

Método

Descripción

`findDocuments({ text? })`

Busca documentos por nombre.

`readDocument({ document })`

Devuelve `{ documentId, title, content }` en texto plano.

### `plz.kv` (almacén clave-valor)

Método

Descripción

`get(key)`

Valor o `null` (también si expiró).

`set(key, value, { ttl? })`

Guarda cualquier valor JSON; `ttl` en segundos.

`delete(key)`

Borra la clave.

`list(prefix?)`

`[{ key, value }]`, opcionalmente filtrado por prefijo.

### `plz.api`, `plz.fetch`, `plz.log`, `plz.env`

Propiedad

Descripción

`plz.api.get(path)` / `post(path, body)` / `put(path, body)` / `delete(path, body)`

Llama a la API de Plazbot ya autenticada. Ej.: `plz.api.get('/api/contact/...')`.

`plz.fetch(url, options)`

`fetch` estándar para APIs externas.

`plz.log.info / warn / error(mensaje, data?)`

Logs visibles en el historial de ejecuciones.

`plz.env`

Secrets configurados en el workspace. `PLZ_API_KEY` y `PLZ_ZONE` (`LA` o `EU`) los usa el runtime.

* * *

## 6\. Ejemplos con `plz.contacts`

### Leer un contacto y sus variables

```ts
const contact = await plz.contacts.get(contactId);
const plan = contact.variables?.find(v => v.code === 'ctc_plan')?.val;
const etiquetas = (contact.tags ?? []).map(t => t.name);
plz.log.info(`${contact.name} ${contact.lastname} · plan ${plan}`, { etiquetas });
```

### Buscar por teléfono o email

```ts
const res = await plz.contacts.search({ phone: '51987654321' });
const encontrados = res?.data?.data ?? [];
if (encontrados.length > 0) {
  await plz.contacts.addTag(encontrados[0].id, 'cliente-vip');
}
```

### Pendientes de un agente con una etiqueta

```ts
const pendientes = await plz.contacts.list({
  filter: { isSolved: false, assignedAgentId: agentId, tags: ['Interesado'] },
  limit: 200,
});
```

### Recorrer todos los contactos

```ts
import { defineSchedule } from 'plazbot/workers';

export default defineSchedule({
  name: 'recorrer-contactos',
  reference: 'Recorre todos los contactos del workspace',
  cron: '0 6 * * *',
  async handler(plz) {
    let cursor: string | null = null;
    let total = 0;

    do {
      const page = await plz.contacts.listPage({ cursor, pageSize: 100 });
      for (const contact of page.items) {
        total++;
      }
      cursor = page.nextCursor;
    } while (cursor);

    plz.log.info(`Contactos recorridos: ${total}`);
  },
});
```

### Actualizar varios campos a la vez

```ts
await plz.contacts.update(contactId, {
  email: 'cliente@correo.com',
  businessName: 'Empresa S.A.C.',
  documentNumber: '20123456789',
});
await plz.contacts.setStage(contactId, 'Negociación');
await plz.contacts.setVariable(contactId, 'ctc_ultima_compra', new Date().toISOString());
await plz.contacts.assignAgent(contactId, 'agente@empresa.com');
```

### Crear un contacto

```ts
await plz.contacts.create({
  name: 'Juan',
  lastname: 'Pérez',
  platformId: 2,
  internalWhatsappNumber: '51987654321',
  email: 'juan@correo.com',
  customFields: [{ code: 'ctc_origen', value: 'web' }],
});
```

* * *

## 7\. Límites

- Las llamadas de `plz.contacts` (y de cualquier módulo que use la API) cuentan contra el límite de la API del workspace: **120 requests por minuto**, con ráfaga de hasta 40.
- Con `pageSize: 100`, recorrer 50.000 contactos son 500 llamadas: unos 5 minutos dentro del límite.
- `setVariable`, `getVariable`, `addTag`, `removeTag`, `setStage`, `setSegmentation` y `assignAgent` hacen 2 llamadas cada uno (leen y luego escriben). Tenlo en cuenta en bucles grandes.
