penseatendeDesarrolladores
API de integración

Integración con Pense Atende

Conecte el sistema de su institución a la plataforma Pense Atende. Lea y responda mensajes, envíe boleta y documento, siga la atención y mantenga los contactos. Cuando la institución contrató, envíe también productos y reciba las ventas, por la API o por MCP.

Direcciónhttps://penseatende.com.br
AutenticaciónAuthorization: Bearer SEU_TOKEN
FormatoJSON
MCPChatGPT, Claude, n8n y otros sistemas

Última actualización de la documentación: 03/11/2026

Visión general

Actualizado el 29/10/2026

Esta guía es el contrato del token de la plataforma Pense Atende. Con él, otro sistema consulta y responde atenciones, lee mensajes (con tarjeta, CPF y CNPJ ocultos), envía el PDF de la boleta o la imagen del Pix por la sección Avisos, y mantiene los contactos. Cuando la institución contrató tienda, inventario o PDV, también envía productos y recibe ventas. El token indica de qué institución es la llamada y lo que puede hacer. Las pantallas internas del panel, como financiero, jurídico, contenido, parámetros y usuarios, no tienen llamada aquí.

  • El sistema de gestión (ERP) de la institución, que envía el catálogo y recibe las ventas.
  • Automatizaciones en n8n, Make, Zapier o Power Automate, por llamada HTTP.
  • Asistentes de IA como ChatGPT y Claude, y agentes de n8n, por el servidor MCP.
  • Código propio, en cualquier lenguaje que haga una llamada HTTP.
POST
/api/integracao/produtosEnviar productos, precios e inventario
GET
/api/integracao/produtosConsultar productos, precio e inventario
GET
/api/integracao/vendasObtener ventas, cancelaciones y devoluciones
POST
/api/integracao/vendas/confirmacaoConfirmar lo que se registró
GET
/api/integracao/conversasListar atenciones
GET
/api/integracao/conversas/{numero}Ver una atención
GET
/api/integracao/atendimento/opcoesOpciones de la atención, para los filtros
PATCH
/api/integracao/conversas/{numero}Cambiar situación, prioridad, sector o responsable, y cerrar
GET
/api/integracao/contatosConsultar contactos
PUT
/api/integracao/contatosGuardar un contacto
POST
/api/integracao/eventosEnviar boleta, Pix o documento
GET
/api/integracao/eventosVer qué pasó con un aviso
GET
/api/integracao/eventos/tiposListar los tipos de aviso
MCP
/api/integracao/mcpServidor MCP para IA y automatizaciones

Dirección base: https://penseatende.com.br

Autenticación

Actualizado el 28/10/2026

Todas las llamadas usan el encabezado Authorization con el token de la conexión. El token pertenece a una sola institución. Quien lo genera es quien está dentro de ella en el panel, en Parâmetros, pestaña Acesso por API, en el bloque Token para el desarrollador: la propia institución, o quien opera la plataforma después de entrar en ella. Para un ensayo, use Token de teste. Cuando sea el turno del cliente, entre en su institución y genere el token de ella. La clave que empieza con pmk_, en el bloque de abajo de la misma pestaña, solo envía texto o plantilla de WhatsApp y no envía boleta ni documento: eso sale por los Avisos, con este token.

Cada token tiene sus propios permisos, definidos por la institución: ver productos, editar productos, ver ventas, confirmar ventas, ver atenciones, leer los mensajes (solo con la aceptación de la institución), responder al paciente (con otra aceptación de la institución), cambiar y cerrar atenciones, ver y guardar contactos, enviar boleta, Pix o documento (avisos) y usar MCP. La institución solo le da al token lo que la persona que lo guarda también puede hacer en el panel. También puede tener fecha de vencimiento, que es obligatoria, y de como máximo un año, en el token que lee o envía mensajes. Una institución puede tener varios tokens, uno por sistema. Si uno se reemplaza, el anterior deja de funcionar al instante.

Authorization: Bearer SEU_TOKEN
Content-Type: application/json

Para probar el token:

Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/produtos?search=mouse&limit=1" \
  -H "Authorization: Bearer SEU_TOKEN"

Si devuelve 401, el token es incorrecto, venció, la conexión fue desactivada o el token es de otra institución (llamada por el dominio propio de una institución con el token de otra). Si devuelve 403, el token no tiene permiso para ese recurso, o la institución no contrató el módulo que el recurso pide (Tienda, Inventario o PDV para productos y ventas; WhatsApp, Chat o Soporte para atenciones; esos o el CRM para contactos).

Formatos y estándares

Actualizado el 22/10/2026

Cómo debe enviarse cada tipo de dato. Los números siempre usan punto decimal, como exige JSON; la tienda los muestra en formato brasileño (R$ 149,90) al cliente. Un dato fuera de formato se rechaza con 422 y el mensaje indica el campo.

DatoFormatoEjemploObservación
Fecha y horaISO 8601 con huso horario2026-10-09T10:05:00-03:00Sin huso se rechaza. La hora se guarda en UTC. Las respuestas de productos, ventas y atención salen en UTC (terminan en Z); las de los avisos salen en el huso de la institución.
Huso horarioEl desplazamiento en la propia fecha-03:00, -04:00, -05:00Cada institución tiene su huso, elegido en el panel. Brasilia y la mayor parte del país: -03:00 (America/Sao_Paulo). Mato Grosso, Mato Grosso do Sul, Amazonas, Rondônia y Roraima: -04:00. Acre: -05:00. Fernando de Noronha: -02:00. Brasil no tiene horario de verano.
TeléfonoCódigo de país, de área y número, con o sin máscara5565999998888Vale +55 (65) 99999-8888, 55 65 99999 8888 o solo los números. Se guarda solo con los dígitos. Sin el 55 de Brasil se rechaza. El celular se encuentra con y sin el noveno dígito.
CPF11 números, con o sin máscara529.982.247-25Se verifica por el dígito verificador. Se guarda solo con los números.
CNPJ14 caracteres, con o sin máscara11.222.333/0001-81Vale también el CNPJ nuevo con letras (12.ABC.345/01DE-35), de la Receita desde julio de 2026. Se verifica por el dígito verificador.
CEP (código postal)8 números, con o sin guion78005-000Se guarda solo con los números.
CorreoDirección completamaria@exemplo.com.brSin diferencia entre mayúsculas y minúsculas: se guarda en minúsculas.
Datos de los avisosTexto ya en formato brasileño"R$ 1.234,56" y "23/10/2026"Van al mensaje tal como llegan. Formatee dinero y fecha al estilo brasileño antes de enviar, a diferencia del precio de los productos, que va como número.
DineroNúmero con punto, 2 decimales, en reales149.90Sin símbolo de moneda ni separador de miles. Un texto como "149,90" se rechaza. Los decimales de más se redondean.
Inventario y cantidadNúmero, hasta 4 decimales18 o 2.5Fracciones solo para productos vendidos por peso o medida (kg, m, l).
PesoNúmero en kg, hasta 3 decimales0.250250 gramos son 0.250.
MedidasNúmero en cm, hasta 2 decimales17.5Alto, ancho y largo del paquete.
CódigosTexto o número entero"7120" o 7120product_code, variant_code y store_code. El número se vuelve texto: 7120 y "7120" son el mismo código.
SKUTexto, hasta 60 caracteres7120-1Obligatorio en cada variante.
Código de barras (ean)Texto, hasta 14 dígitos7891234567895Puede ser null.
TextosUTF-8, con acentosMouse sem fio, pretointernal_name hasta 200 caracteres; internal_description hasta 20.000.
Verdadero o falsotrue o false, sin comillastrueSe usa en is_active y pickup_in_store.
Unidad de ventaUna de la listaunun, kg, g, m, m2, l, cx, par.
Valor ausentenull o campo omitidonullSignifica "no informado": nunca borra lo que ya está en la plataforma.
Id de la plataformaNúmero entero1532No lo necesita para enviar: use sus códigos. Vuelve en la consulta y en las ventas, en product_id y variant_id.
MensajesPortugués (pt-BR)Los campos y los códigos de error están en inglés; los mensajes para personas, en portugués.

Nombres y códigos

Actualizado el 09/10/2026

En la plataforma, el producto se identifica por su id, un número que nunca cambia. Sus códigos vienen en cada respuesta, para que los compare con su sistema.

CampoQué esQuién lo defineDónde aparece
product_codeCódigo del producto en su sistema.Su sistema, en el envío. Si cambia, es otro producto.Envío, consulta y ventas.
variant_codeCódigo de la variante en su sistema. null en producto sin variantes.Su sistema, en el envío.Envío, consulta y ventas.
skuSKU de la variante.Su sistema, en el envío. Puede cambiar: el anterior sigue encontrando la variante.Envío, consulta y ventas.
eanCódigo de barras.Su sistema, en el envío.Envío, consulta y ventas.
product_idId del producto en la plataforma. Nunca cambia.La plataforma, al crear el producto.Consulta y ventas.
variant_idId de la variante en la plataforma.La plataforma, al crear la variante.Consulta y ventas.
online_codeCódigo del producto en la plataforma.En el producto creado por un envío, sale de su product_code. En el registrado en el panel, es el que eligió la institución.Consulta y ventas.
internal_nameNombre interno, como está en su sistema.Su sistema, en el envío. Se actualiza en cada envío.Envío, consulta y ventas.
internal_descriptionDescripción interna, como está en su sistema.Su sistema, en el envío. Se actualiza en cada envío.Envío.
commercial_nameNombre comercial, el que el cliente ve en la tienda.La institución, en su panel. El envío nunca lo cambia.Consulta y ventas. En las ventas viene con la variante, como "Mouse Gamer, Preto".

Ejemplo: el mouse 7120 de su sistema se convierte en la plataforma en el producto 1532. Vuelve como product_id 1532 y product_code 7120. Un producto registrado directamente en el panel viene con product_code null hasta que la institución informe el código de su sistema en el producto. En un producto nuevo, el nombre y la descripción comerciales empiezan iguales a los internos, y desde entonces son de la institución.

Cómo empezar

Actualizado el 28/10/2026

  1. Genere el token en la institución correcta. En el panel, dentro de la institución, en Parâmetros, pestaña Acesso por API, cree el token de prueba o una conexión nueva. Solo vale para esa institución. Para boleta y documento, marque avisos. Para leer y responder, marque mensajes. Copie el token en el momento: no vuelve a aparecer.
  2. Pruebe con productos nuevos. Envíe 2 o 3 productos que aún no están en la plataforma. Se crean como borrador y el cliente no los ve.
  3. Revise el resultado. La respuesta muestra lo que se creó, actualizó o rechazó. La institución también ve cada envío en el panel, campo por campo.
  4. Envíe la carga completa. Todos los productos de la institución, con load_type: "full", en lotes de hasta 2000 variantes.
  5. Después, solo lo que cambie. Use load_type: "incremental" y envíe los productos modificados y los nuevos.

Enviar productos, precios e inventario

Actualizado el 09/10/2026

Envíe los productos en el cuerpo de POST /api/integracao/produtos. La respuesta ya trae el resultado.

Cómo se identifica el producto

  • Por product_code junto con variant_code, que son los códigos de su sistema.
  • Si solo cambia el SKU, sigue siendo el mismo producto.
  • Si cambia el product_code, pasa a ser otro producto.
  • Un producto sin variantes se envía con un ítem en variants y variant_code null.

Nombre interno y nombre comercial

  • Envíe el nombre y la descripción de su sistema en internal_name y internal_description. Se actualizan en cada envío. Si ya envía name y description, puede seguir: valen como los internos.
  • El nombre y la descripción comerciales, los que el cliente ve en la tienda, los hace la institución. En un producto nuevo empiezan iguales a los internos, y la institución los ajusta en su panel. Su envío nunca cambia el nombre comercial.
  • El nombre de la variante (variants[].name, como "Preto") sigue la misma regla del nombre comercial.

Qué se actualiza

  • En cada envío: precio, promoción, costo, inventario, código de barras, SKU, activo, nombre y descripción internos.
  • Solo al crear el producto: categoría, marca, peso y medidas. Después, los gestiona la institución.
  • Un campo vacío o null no borra nada.
  • is_active: false en el producto quita de la tienda el producto entero, con todas sus variantes. En una variante, quita solo esa: en un mouse Negro, Blanco y Azul, desactivar el Azul deja el Negro y el Blanco a la venta.
  • Un producto que no viene en el envío no cambió, y queda como está.

Inventario

stock.on_hand es el inventario que tiene su sistema. Una venta hecha en la plataforma baja el inventario al instante; mientras no se registre en su sistema, la plataforma descuenta esa venta del número que usted envíe. Ejemplo: había 6, se vendieron 3 en la tienda física y 3 en línea. Su sistema envía 3 y la plataforma queda en 0. Cuando la venta se registra en su sistema y se confirma, el descuento termina.

Ejemplo

Ejemplo de llamada
curl -X POST "https://penseatende.com.br/api/integracao/produtos" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: carga-2026-10-09-1005" \
  -d @produtos.json
produtos.json
{
  "store_code": "matriz",
  "generated_at": "2026-10-09T10:05:00-03:00",
  "load_type": "full",
  "products": [
    {
      "product_code": "6561",
      "internal_name": "ADAPTADOR BLUETOOTH C/ CABO P2",
      "internal_description": "Adaptador Bluetooth 5.0 com saída P2, para som automotivo e caixa de som.",
      "brand_name": "EXEMPLO",
      "category_code": "1",
      "category_name": "GERAL",
      "sale_unit_code": "un",
      "is_active": true,
      "variants": [
        {
          "variant_code": null,
          "sku": "6561",
          "ean": "7898843500046",
          "price": 89.9,
          "cost_price": 41.2,
          "weight": 0.12,
          "height": 4,
          "width": 9,
          "length": 14,
          "is_active": true,
          "stock": {
            "on_hand": 214
          }
        }
      ]
    },
    {
      "product_code": "7120",
      "internal_name": "MOUSE GAMER RGB 7200DPI",
      "brand_name": "EXEMPLO",
      "category_code": "4",
      "category_name": "PERIFERICOS",
      "sale_unit_code": "un",
      "is_active": true,
      "variants": [
        {
          "variant_code": "1",
          "sku": "7120-1",
          "ean": "7891234567895",
          "name": "Preto",
          "color_name": "PRETO",
          "price": 149.9,
          "promo_price": 129.9,
          "promo_starts_at": "2026-10-10T00:00:00-03:00",
          "promo_ends_at": "2026-10-20T23:59:59-03:00",
          "cost_price": 72.5,
          "weight": 0.25,
          "height": 6,
          "width": 10,
          "length": 17,
          "is_active": true,
          "stock": {
            "on_hand": 18
          }
        }
      ]
    }
  ]
}

Respuesta

200 OK
{
  "batch_id": 1532,
  "status": "processed_with_errors",
  "received_at": "2026-10-09T13:05:03.000Z",
  "generated_at": "2026-10-09T13:05:00.000Z",
  "totals": {
    "received": 1200,
    "created": 12,
    "updated": 340,
    "unchanged": 846,
    "rejected": 2
  },
  "rejected": [
    {
      "product_code": "7120",
      "variant_code": "3",
      "sku": "7120-3",
      "message": "O preço precisa ser maior que zero."
    },
    {
      "product_code": "9001",
      "variant_code": null,
      "sku": "9001",
      "message": "A unidade cxa não existe na plataforma. Use un, kg, g, m, m2, l, cx ou par."
    }
  ]
}

status viene como processed (todo bien) o processed_with_errors (algún ítem rechazado). Un ítem rechazado no impide los demás.

Reglas

  • Obligatorios: store_code (el código de la tienda de la institución, normalmente "matriz"), generated_at y, en cada ítem, product_code y sku. Lo que su sistema no tenga, envíelo como null: la institución lo completa en el panel.
  • Hasta 2000 ítems de variants por envío y 120 envíos por hora por token. Cualquier llamada, también por MCP, tiene el tope de 120 por minuto por token.
  • Si necesita reenviar, use el mismo Idempotency-Key: el envío no se procesa dos veces.

Consultar productos

Actualizado el 03/11/2026

Busque por product_code, sku o search (parte del nombre, el id o el código de la plataforma). La respuesta muestra el nombre comercial (commercial_name), el nombre de su sistema (internal_name), el precio, el precio actual con promoción y el inventario disponible de cada variante, y también si el producto es kit (is_kit), el NCM, el CEST de la factura y el GTIN tributable de cada variante (tax_gtin). Es la consulta ideal para que un asistente de IA responda "¿tienen el producto X? ¿cuánto cuesta?".

Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/produtos?product_code=7120" \
  -H "Authorization: Bearer SEU_TOKEN"
200 OK
{
  "products": [
    {
      "product_id": 1532,
      "online_code": "7120",
      "product_code": "7120",
      "commercial_name": "Mouse Gamer RGB 7200 DPI",
      "internal_name": "MOUSE GAMER RGB 7200DPI",
      "status": "published",
      "is_kit": false,
      "ncm": "84716053",
      "cest": null,
      "variants": [
        {
          "variant_id": 2871,
          "variant_code": "1",
          "sku": "7120-1",
          "ean": "7891234567895",
          "name": "Preto",
          "price": 149.9,
          "promo_price": 129.9,
          "current_price": 129.9,
          "stock": 18,
          "is_active": true,
          "tax_gtin": null
        }
      ]
    }
  ]
}

Ventas

Actualizado el 22/10/2026

Funciona en tres pasos: obtener las ventas, registrarlas en su sistema y confirmar. Lo confirmado sale de la lista; lo no confirmado vuelve en la próxima consulta.

Se incluyen las ventas hechas desde el día en que la institución activó la integración. Las ventas anteriores no aparecen aquí.

1. Obtener

Devuelve hasta 100 documentos aún no confirmados, del más antiguo al más reciente: sale (venta pagada), cancel (cancelación de una venta ya confirmada) y return (devolución concluida). Consultar no cambia nada.

Cada ítem trae product_id y variant_id (el id en la plataforma), online_code (el código en la plataforma), product_code y variant_code (sus códigos), internal_name (el nombre en su sistema) y commercial_name (el nombre comercial que vio el cliente).

Entrega, retiro y canal

  • channel: site es una venta en la tienda en línea; pos es una venta en el mostrador (PDV).
  • pickup_in_store: false: entrega. La dirección de entrega viene en customer (código postal, calle, número, complemento, barrio, ciudad y estado) y el flete en shipping_cost.
  • pickup_in_store: true: retiro en la tienda. La dirección viene vacía (null) y el flete es cero.

Formas de pago

Cada venta trae la lista payments, con una línea por forma usada: una venta puede pagarse parte en efectivo y parte con tarjeta. installments es el número de cuotas. method_code es el código de la forma de pago en el registro de la institución. Estos son los códigos estándar de la plataforma; la institución puede registrar otros:

method_codeFormaCuotas
pixPIXNo
cartao_creditoCartão de créditoSí
cartao_debitoCartão de débitoNo
boletoBoletoNo
transferenciaTransferênciaNo
dinheiroDinheiroNo

El ejemplo de abajo trae una venta con Pix y entrega, una con tarjeta de crédito en 3 cuotas y retiro en la tienda, una de mostrador pagada en efectivo y débito, una cancelación y una devolución.

Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/vendas" \
  -H "Authorization: Bearer SEU_TOKEN"
200 OK
{
  "generated_at": "2026-10-09T13:10:00.000Z",
  "limit": 100,
  "documents": [
    {
      "type": "sale",
      "number": "100245",
      "channel": "site",
      "placed_at": "2026-10-09T12:41:07.000Z",
      "pickup_in_store": false,
      "customer": {
        "name": "Maria Souza",
        "document": "12345678909",
        "email": "maria@exemplo.com.br",
        "phone": "31999990000",
        "postal_code": "30140071",
        "street": "Rua da Bahia",
        "number": "1000",
        "complement": "Apto 302",
        "neighborhood": "Centro",
        "city": "Belo Horizonte",
        "state": "MG"
      },
      "items": [
        {
          "product_id": 1532,
          "variant_id": 2871,
          "online_code": "7120",
          "product_code": "7120",
          "variant_code": "1",
          "internal_name": "MOUSE GAMER RGB 7200DPI",
          "commercial_name": "Mouse Gamer RGB 7200 DPI com 6 botões, Preto",
          "sku": "7120-1",
          "ean": "7891234567895",
          "unit": "un",
          "quantity": 1,
          "unit_price": 129.9,
          "discount": 0,
          "total": 129.9,
          "unit_cost": 72.5,
          "ncm": null,
          "cest": null,
          "origin": null
        }
      ],
      "subtotal": 129.9,
      "discount": 0,
      "shipping_cost": 18.5,
      "total": 148.4,
      "payments": [
        {
          "method_code": "pix",
          "method_name": "PIX",
          "amount": 148.4,
          "installments": 1
        }
      ],
      "invoice": null
    },
    {
      "type": "sale",
      "number": "100246",
      "channel": "site",
      "placed_at": "2026-10-09T14:05:22.000Z",
      "pickup_in_store": true,
      "customer": {
        "name": "João Lima",
        "document": "98765432100",
        "email": "joao@exemplo.com.br",
        "phone": "31988887777",
        "postal_code": null,
        "street": null,
        "number": null,
        "complement": null,
        "neighborhood": null,
        "city": null,
        "state": null
      },
      "items": [
        {
          "product_id": 1532,
          "variant_id": 2871,
          "online_code": "7120",
          "product_code": "7120",
          "variant_code": "1",
          "internal_name": "MOUSE GAMER RGB 7200DPI",
          "commercial_name": "Mouse Gamer RGB 7200 DPI com 6 botões, Preto",
          "sku": "7120-1",
          "ean": "7891234567895",
          "unit": "un",
          "quantity": 2,
          "unit_price": 129.9,
          "discount": 0,
          "total": 259.8,
          "unit_cost": 72.5,
          "ncm": null,
          "cest": null,
          "origin": null
        }
      ],
      "subtotal": 259.8,
      "discount": 0,
      "shipping_cost": 0,
      "total": 259.8,
      "payments": [
        {
          "method_code": "cartao_credito",
          "method_name": "Cartão de crédito",
          "amount": 259.8,
          "installments": 3
        }
      ],
      "invoice": null
    },
    {
      "type": "sale",
      "number": "100247",
      "channel": "pos",
      "placed_at": "2026-10-09T15:30:00.000Z",
      "pickup_in_store": true,
      "customer": {
        "name": "Consumidor",
        "document": null,
        "email": null,
        "phone": null,
        "postal_code": null,
        "street": null,
        "number": null,
        "complement": null,
        "neighborhood": null,
        "city": null,
        "state": null
      },
      "items": [
        {
          "product_id": 1532,
          "variant_id": 2871,
          "online_code": "7120",
          "product_code": "7120",
          "variant_code": "1",
          "internal_name": "MOUSE GAMER RGB 7200DPI",
          "commercial_name": "Mouse Gamer RGB 7200 DPI com 6 botões, Preto",
          "sku": "7120-1",
          "ean": "7891234567895",
          "unit": "un",
          "quantity": 1,
          "unit_price": 129.9,
          "discount": 9.9,
          "total": 120,
          "unit_cost": 72.5,
          "ncm": null,
          "cest": null,
          "origin": null
        }
      ],
      "subtotal": 129.9,
      "discount": 9.9,
      "shipping_cost": 0,
      "total": 120,
      "payments": [
        {
          "method_code": "dinheiro",
          "method_name": "Dinheiro",
          "amount": 50,
          "installments": 1
        },
        {
          "method_code": "cartao_debito",
          "method_name": "Cartão de débito",
          "amount": 70,
          "installments": 1
        }
      ],
      "invoice": null
    },
    {
      "type": "cancel",
      "number": "100231",
      "canceled_at": "2026-10-09T16:02:10.000Z",
      "reason": "Cliente desistiu da compra",
      "invoice": null
    },
    {
      "type": "return",
      "number": "D100198-1",
      "order_number": "100198",
      "opened_at": "2026-10-09T16:40:00.000Z",
      "reason": "Produto com defeito",
      "restocks": false,
      "refund_amount": 129.9,
      "items": [
        {
          "product_id": 1532,
          "variant_id": 2871,
          "online_code": "7120",
          "product_code": "7120",
          "variant_code": "1",
          "internal_name": "MOUSE GAMER RGB 7200DPI",
          "commercial_name": "Mouse Gamer RGB 7200 DPI com 6 botões, Preto",
          "sku": "7120-1",
          "ean": "7891234567895",
          "quantity": 1,
          "unit_paid": 129.9,
          "unit_cost": 72.5
        }
      ],
      "invoice": null
    }
  ]
}

2. Confirmar

Envíe cada documento que registró. processed lo saca de la lista; rejected lo mantiene y muestra el motivo a la institución en el pedido.

Ejemplo de llamada
curl -X POST "https://penseatende.com.br/api/integracao/vendas/confirmacao" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d @confirmacao.json
confirmacao.json
{
  "documents": [
    {
      "type": "sale",
      "number": "100245",
      "status": "processed"
    },
    {
      "type": "sale",
      "number": "100246",
      "status": "rejected",
      "message": "Produto 7120-9 não cadastrado."
    }
  ]
}
200 OK
{
  "results": [
    {
      "type": "sale",
      "number": "100245",
      "result": "saved"
    },
    {
      "type": "sale",
      "number": "100246",
      "result": "saved"
    }
  ]
}

Para cada documento, la respuesta dice: saved (registrado), already_confirmed (ya estaba confirmado), not_found (el número no existe) o not_due (aún no se puede confirmar, como una venta no pagada).

Atenciones

Actualizado el 27/10/2026

Vea las atenciones de la institución y en qué punto está cada una: la situación, el sector, quién atiende y si se puede responder al paciente ahora. Sirve para un panel propio, un informe o un asistente de IA que responda "¿cómo va la atención del paciente X?". Para enviar al paciente el PDF de la boleta o la imagen del Pix, con el texto que aparece junto, use la sección Avisos. Esta sección solo lista y lee la atención.

No vienen aquí: el texto de los mensajes, las notas internas del equipo, los resúmenes hechos por la IA, las conversaciones de grupo, las conversaciones antiguas traídas del celular y ningún dato del equipo más allá del nombre de quien atiende.

Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/conversas?is_open=true&limit=20" \
  -H "Authorization: Bearer SEU_TOKEN"
200 OK
{
  "since": "2026-10-08T12:45:00.000Z",
  "until": "2026-10-15T12:45:00.000Z",
  "limit": 20,
  "conversations": [
    {
      "number": "2026-001532",
      "channel": {
        "code": "whatsapp",
        "name": "WhatsApp"
      },
      "status": {
        "code": "aberto",
        "name": "Aberto",
        "is_open": true
      },
      "priority": {
        "code": "normal",
        "name": "Normal"
      },
      "department": {
        "code": "vendas",
        "name": "Vendas"
      },
      "whatsapp_number": {
        "id": 3,
        "label": "Comercial, final 4321",
        "provider": "oficial"
      },
      "contact": {
        "name": "Maria Souza",
        "phone": "5532*****8888",
        "phone_masked": true,
        "username": null
      },
      "assigned_to": {
        "name": "Julia"
      },
      "created_at": "2026-10-15T12:02:11.000Z",
      "last_message_at": "2026-10-15T12:40:05.000Z",
      "last_customer_message_at": "2026-10-15T12:38:51.000Z",
      "reply_window_open": true,
      "reply_window_ends_at": "2026-10-16T12:38:51.000Z",
      "closed_at": null,
      "archived": false,
      "blocked": false,
      "whatsapp_opt_out": false
    }
  ],
  "next_cursor": null
}

Qué trae cada atención

  • number: el número de la atención, el mismo que el equipo ve en el panel.
  • status, priority, department y channel: situación, prioridad, sector y canal, con código y nombre. status.is_open dice si sigue abierta.
  • whatsapp_number: el número de WhatsApp de la institución que atiende, con provider oficial (API oficial de WhatsApp) o qr (conectado por código QR).
  • contact: nombre, teléfono y nombre de usuario del paciente. assigned_to: solo el nombre de quien atiende.
  • reply_window_open: si se puede responder al paciente por la API ahora. Vale hasta 24 horas después de su último mensaje (reply_window_ends_at), en WhatsApp oficial y también en el número por código QR: es la misma regla del envío de mensajes.
  • blocked: el contacto está bloqueado. whatsapp_opt_out: el paciente pidió no recibir ofertas ni novedades.

Filtros

  • status: una o más situaciones, separadas por coma. is_open: true trae solo las abiertas, false solo las cerradas.
  • whatsapp_number_id, department y channel: los códigos que vienen en las opciones de la atención.
  • since y until: el período, por el último mensaje, en fecha (2026-10-15, hora de Brasilia) o fecha y hora con zona horaria. Sin nada, los últimos 7 días; como máximo 92 días por búsqueda.

Páginas

Vienen hasta 50 atenciones por vez (por defecto 20), de la que tuvo el mensaje más reciente a la más antigua. Si la respuesta trae next_cursor, envíe ese valor en cursor, con los mismos filtros, para ver las siguientes. Cuando venga null, terminó.

Teléfono del paciente

Para proteger al paciente, el teléfono viene con el medio oculto (5532*****8888). Viene completo, y se puede buscar por phone, solo cuando la institución da al token también el permiso Consulta de contactos.

Una atención

Para ver una sola, ponga su número en la dirección. Un número que no existe en la institución responde 404.

Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/conversas/2026-001532" \
  -H "Authorization: Bearer SEU_TOKEN"

Opciones para los filtros

Las situaciones, prioridades, sectores, canales y números de WhatsApp de la institución, con el código de cada uno. Nadie del equipo aparece aquí.

Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/atendimento/opcoes" \
  -H "Authorization: Bearer SEU_TOKEN"
200 OK
{
  "statuses": [
    {
      "code": "aberto",
      "name": "Aberto",
      "is_open": true
    },
    {
      "code": "aguardando_cliente",
      "name": "Aguardando o paciente",
      "is_open": true
    },
    {
      "code": "resolvido",
      "name": "Resolvido",
      "is_open": false
    }
  ],
  "priorities": [
    {
      "code": "normal",
      "name": "Normal"
    },
    {
      "code": "alta",
      "name": "Alta"
    }
  ],
  "departments": [
    {
      "code": "vendas",
      "name": "Vendas"
    },
    {
      "code": "suporte",
      "name": "Suporte"
    }
  ],
  "channels": [
    {
      "code": "whatsapp",
      "name": "WhatsApp"
    },
    {
      "code": "chat",
      "name": "Chat do site"
    }
  ],
  "whatsapp_numbers": [
    {
      "id": 3,
      "label": "Comercial, final 4321",
      "provider": "oficial"
    },
    {
      "id": 7,
      "label": "Unidade Centro, final 9876",
      "provider": "qr"
    }
  ]
}

Gestión de la atención

Actualizado el 27/10/2026

Cambie la situación, la prioridad, el sector o quién atiende una atención, y ciérrela, por su número. Sirve para que su sistema pase al paciente al vendedor correcto, marque como urgente la atención de un pedido atrasado o la cierre cuando el caso se resolvió por otro camino. Es la misma regla del panel: el equipo ve el cambio al instante, con el nombre del token. Para enviar el PDF o la imagen con texto, use la sección Avisos. Aquí solo cambia la situación, la prioridad, el sector o quién atiende.

Ejemplo de llamada
curl -X PATCH "https://penseatende.com.br/api/integracao/conversas/2026-001532" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d @atendimento.json
atendimento.json
{
  "status_code": "aguardando_cliente",
  "priority_code": "alta",
  "assign_to_email": "julia@exemplo.com.br"
}
200 OK
{
  "conversation": {
    "number": "2026-001532",
    "channel": {
      "code": "whatsapp",
      "name": "WhatsApp"
    },
    "status": {
      "code": "aguardando_cliente",
      "name": "Aguardando o paciente",
      "is_open": true
    },
    "priority": {
      "code": "alta",
      "name": "Alta"
    },
    "department": {
      "code": "vendas",
      "name": "Vendas"
    },
    "whatsapp_number": {
      "id": 3,
      "label": "Comercial, final 4321",
      "provider": "oficial"
    },
    "contact": {
      "name": "Maria Souza",
      "phone": "5532*****8888",
      "phone_masked": true,
      "username": null
    },
    "assigned_to": {
      "name": "Julia"
    },
    "created_at": "2026-10-15T12:02:11.000Z",
    "last_message_at": "2026-10-15T12:40:05.000Z",
    "last_customer_message_at": "2026-10-15T12:38:51.000Z",
    "reply_window_open": true,
    "reply_window_ends_at": "2026-10-16T12:38:51.000Z",
    "closed_at": null,
    "archived": false,
    "blocked": false,
    "whatsapp_opt_out": false
  }
}

Qué se puede cambiar

  • status_code: la situación, por el código que viene en las opciones de la atención. Una situación de cierre cierra la atención.
  • priority_code: la prioridad, por el código.
  • department_code: el sector, por el código. null deja la atención sin sector.
  • assign_to_email: el correo de quien del equipo pasa a atender. Solo vale para quien es del equipo de esta institución y ve las atenciones. null devuelve la atención a la fila, sin responsable.

Cómo funciona

  • Envíe solo lo que cambia: el campo que no viene queda como está. Al menos uno de los cuatro tiene que venir.
  • Todo se verifica antes de cambiar cualquier cosa: si una parte se rechaza, nada cambia. El mismo envío repetido no cambia nada.
  • Un código que la institución no tiene activo responde 422 con invalid_option, el campo en field y los códigos válidos en options.
  • Un correo que no es de nadie del equipo de esta institución responde 422 con attendant_not_found. La respuesta no dice si el correo existe en otro lugar, y la lista del equipo nunca sale por la API.
  • Una atención cerrada o archivada solo pasa a alguien si se reabre en el mismo envío, con status_code de otra situación abierta; si no, 422 con conversation_closed.
  • La respuesta es la atención ya actualizada, en el mismo formato de la consulta.
422
{
  "code": "invalid_option",
  "message": "O código pausado não é uma situação ativa desta instituição. Use um destes: aberto, aguardando_cliente, resolvido.",
  "field": "status_code",
  "options": [
    "aberto",
    "aguardando_cliente",
    "resolvido"
  ]
}

Cerrar

Para cerrar, envíe status_code de una situación de cierre. Pasa lo mismo que con el botón del panel: la atención sale de la fila, pierde el responsable y el sector, el paciente recibe el mensaje de cierre (si la institución lo usa y la ventana de WhatsApp lo permite) y la invitación a la encuesta de satisfacción, y el resumen queda listo. Por eso cerrar junto con assign_to_email o department_code se rechaza. En MCP, la herramienta encerrar_atendimento lo hace solo con el número, usando la situación de cierre estándar de la institución.

atendimento.json
{
  "status_code": "resolvido"
}

Avisos de la atención

Si la institución suscribe estos avisos en el webhook de salida, llegan cuando el equipo cambia la atención por el panel o por la aplicación, y cuando un token la cambia por la API. Ninguno lleva el texto de los mensajes. En by viene quién lo hizo: user con el nombre de la persona, o integration con el nombre y el número del token (connection_id), para que su sistema reconozca su propio cambio. Los cambios hechos por automatización, como el robot de atención y la distribución automática, todavía no avisan.

  • conversation.assigned: alguien pasó a atender (incluso quien la asumió al responder), la atención volvió a la fila o cambió de sector. change dice qué cambió: assignee o department.
  • conversation.status_changed: la situación cambió, con la anterior en previous_status.
  • conversation.closed: la atención se cerró. Llega junto con el conversation.status_changed del mismo cierre.
conversation.assigned
{
  "id": "5e0c9a7b-2d41-4f8e-a3b6-71c2d9e4f805",
  "event": "conversation.assigned",
  "createdAt": "2026-10-15T12:45:11.000Z",
  "data": {
    "number": "2026-001532",
    "change": "assignee",
    "assigned_to": {
      "name": "Julia"
    },
    "department": {
      "code": "vendas",
      "name": "Vendas"
    },
    "at": "2026-10-15T12:45:10.000Z",
    "by": {
      "type": "integration",
      "name": "ERP da instituição",
      "connection_id": 12
    }
  }
}
conversation.status_changed
{
  "id": "5e0c9a7b-2d41-4f8e-a3b6-71c2d9e4f805",
  "event": "conversation.status_changed",
  "createdAt": "2026-10-15T13:02:45.000Z",
  "data": {
    "number": "2026-001532",
    "status": {
      "code": "resolvido",
      "name": "Resolvido",
      "is_open": false
    },
    "previous_status": {
      "code": "aberto",
      "name": "Aberto",
      "is_open": true
    },
    "at": "2026-10-15T13:02:44.000Z",
    "by": {
      "type": "user",
      "name": "Julia",
      "connection_id": null
    }
  }
}
conversation.closed
{
  "id": "5e0c9a7b-2d41-4f8e-a3b6-71c2d9e4f805",
  "event": "conversation.closed",
  "createdAt": "2026-10-15T13:02:45.000Z",
  "data": {
    "number": "2026-001532",
    "status": {
      "code": "resolvido",
      "name": "Resolvido"
    },
    "closed_at": "2026-10-15T13:02:44.000Z",
    "by": {
      "type": "user",
      "name": "Julia",
      "connection_id": null
    }
  }
}

Contactos

Actualizado el 27/10/2026

Encuentre un contacto por teléfono, por correo o por parte del nombre, y mantenga el nombre, el correo y el pedido de no recibir mensajes al día con su sistema. Sirve para su CRM, para una automatización después de una venta o para un asistente de IA que responda "¿quién es el paciente de este teléfono?". Para enviar el PDF de la boleta o la imagen del Pix, con el texto junto, al teléfono de este contacto, use la sección Avisos. Guardar el contacto no envía archivo.

No vienen aquí: documento (CPF o CNPJ), dirección, pedidos, género ni ningún dato del equipo.

Consultar

Envíe uno, y solo uno, de estos tres:

  • phone: el teléfono con código de país y de área, como 5532999998888. Encuentra el celular brasileño con y sin el noveno dígito.
  • email: el correo completo, sin diferencia de mayúsculas.
  • search: parte del nombre o del correo, con al menos 3 letras. Vienen hasta 20 contactos, del que habló por último al más antiguo.
Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/contatos?phone=5532999998888" \
  -H "Authorization: Bearer SEU_TOKEN"
200 OK
{
  "contacts": [
    {
      "phone": "5532999998888",
      "name": "Maria Souza",
      "email": "maria@exemplo.com.br",
      "whatsapp_consent": "aceito",
      "customer": {
        "name": "Maria Souza",
        "has_account": true
      },
      "conversations": [
        {
          "number": "2026-001532",
          "status": {
            "code": "aberto",
            "name": "Aberto",
            "is_open": true
          },
          "last_message_at": "2026-10-15T12:40:05.000Z"
        },
        {
          "number": "2026-001190",
          "status": {
            "code": "resolvido",
            "name": "Resolvido",
            "is_open": false
          },
          "last_message_at": "2026-10-02T18:11:47.000Z"
        }
      ]
    }
  ]
}

Qué trae cada contacto

  • phone, name y email: el teléfono (solo números, con el país), el nombre y el correo.
  • whatsapp_consent: si el contacto acepta mensajes de ofertas y novedades por WhatsApp: aceito (aceptado), recusado (rechazado, incluso quien respondió SAIR) o sem_registro (sin registro).
  • customer: el cliente de la tienda vinculado al contacto, solo el nombre y si tiene contraseña para entrar (has_account).
  • conversations: hasta 5 atenciones, de la más reciente a la más antigua, con el número, la situación y el último mensaje, sin el texto.

Guardar

Envíe el contacto en el cuerpo de un PUT, en la misma dirección. El teléfono es la clave: si ya existe, el contacto se actualiza; si no, se crea.

Ejemplo de llamada
curl -X PUT "https://penseatende.com.br/api/integracao/contatos" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d @contato.json
contato.json
{
  "phone": "5532999998888",
  "name": "Maria Souza",
  "email": "maria@exemplo.com.br",
  "whatsapp_consent": null
}
200 OK
{
  "contact": {
    "phone": "5532999998888",
    "name": "Maria Souza",
    "email": "maria@exemplo.com.br",
    "whatsapp_consent": "sem_registro",
    "created": false,
    "changed": [
      "name",
      "email"
    ]
  }
}
  • El teléfono se guarda solo con números y el país, y el celular brasileño se encuentra con y sin el noveno dígito.
  • name y email nulos o ausentes mantienen lo que ya está guardado. Nada se borra.
  • El nombre nuevo vale también en las conversaciones y atenciones de ese teléfono: es el nombre que el equipo ve en la fila.
  • La respuesta dice si el contacto fue creado (created) y qué cambió (changed). El mismo envío repetido no cambia nada.

Pedido de no recibir mensajes

Para registrar que el contacto ya no quiere mensajes de ofertas y novedades por WhatsApp, envíe whatsapp_consent: "recusado". Vale como si hubiera respondido SAIR, y el registro guarda el nombre del token. Por la API no se puede registrar la aceptación: aceito responde 422 con consent_grant_not_allowed y nada del envío se graba, porque la aceptación debe venir de la propia persona, por el formulario o por la conversación.

Aviso de contacto guardado

Si la institución suscribe el aviso contact.saved en el webhook de salida, llega cada vez que un contacto se crea o se cambia por la API, con el teléfono, el nombre, el consentimiento, qué cambió y el número del token que lo guardó (connection_id), para que su sistema reconozca su propio envío.

contact.saved
{
  "id": "8d3f2c1e-5b7a-4c9d-9e10-2f6a7b8c9d01",
  "event": "contact.saved",
  "createdAt": "2026-10-15T12:41:00.000Z",
  "data": {
    "phone": "5532999998888",
    "name": "Maria Souza",
    "whatsapp_consent": "sem_registro",
    "created": false,
    "changed": [
      "name"
    ],
    "source": "api_integracao",
    "connection_id": 12
  }
}

Avisos de su sistema al WhatsApp

Actualizado el 29/10/2026

Su sistema sigue encargándose de todo: la boleta, la fecha de vencimiento, el cobro y el registro del paciente. Cuando el paciente necesita recibir la boleta o el Pix, llama a una dirección de Pense Atende y envía el archivo en sí, con el texto que aparece junto: la imagen del código QR del Pix y el PDF de la boleta. Quien prefiere envía solo el enlace, en el dato link_boleto. Pense Atende guarda el aviso y hace el envío por WhatsApp, correo o SMS, con el texto y la hora que la institución registró en el panel.

Paso a paso

  • Su sistema llama a POST /api/integracao/eventos con el token, una vez por paciente y por aviso. Ejemplo: la boleta de María vence mañana.
  • En el cuerpo van el código del aviso (elegido por usted, como boleto_vence_hoje), la clave del aviso en su sistema, el teléfono y el nombre del paciente. El PDF de la boleta va en el campo document, con el texto en document_text. La imagen del Pix va en el campo image, con el texto en image_text. El enlace, cuando usa enlace en vez de archivo, va en variables, en el dato link_boleto.
  • La primera vez que llega un código, aparece en el panel de Pense Atende, en Automatizaciones, con el disparador Aviso de otro sistema. Allí la institución escribe el mensaje (en WhatsApp, elige la plantilla aprobada por Meta), dice por dónde sale y cuánto esperar.
  • Desde entonces, cada aviso con ese código se vuelve mensaje al paciente, al momento o en la fecha y hora que su sistema envíe en send_at. Así los recordatorios ya salen programados.
  • Mientras el mensaje del aviso no esté registrado en el panel, el aviso queda guardado (estado sem_automacao) y no se envía nada.
  • Para enviar la imagen del Pix y el PDF de la boleta, use el formulario de la sección Imagen y PDF. El JSON sigue para el aviso que es solo texto y enlace.

Imagen y PDF

Sistema de escritorio, sin URL: el archivo no entra en el JSON y no existe link_boleto. La imagen del código QR del Pix va en el campo image, con image_text. El PDF de la boleta va en el campo document, con document_text. Los dos pueden ir en la misma llamada, en formulario (multipart/form-data). link_boleto solo entra cuando la boleta tiene una dirección pública.

Ejemplo de llamada
curl -X POST "https://penseatende.com.br/api/integracao/eventos" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -F event=boleto_vence_hoje \
  -F id=BOL-2026-0001-hoje \
  -F phone=5565999998888 \
  -F name="Maria Souza" \
  -F "document=@boleto.pdf;type=application/pdf" \
  -F "document_text=Segue o boleto da mensalidade." \
  -F "variables={\"valor\":\"R$ 150,00\",\"vencimento\":\"23/10/2026\"}"
  • event, id, phone, name, email, document (el CPF o CNPJ), send_at, variables y event_name: los mismos del JSON, cada uno en un campo del formulario. variables, cuando viene, es el objeto JSON en texto.
  • image: archivo JPG o PNG, hasta 5 MB. El tipo vale por los bytes del archivo.
  • image_text: el texto que sale junto a la imagen, hasta 1024 caracteres.
  • document: archivo PDF, hasta 16 MB.
  • document_text: el texto que sale junto al PDF, hasta 1024 caracteres.
  • En el número por código QR, o con la ventana de 24 horas abierta, cada archivo sale en un mensaje, con su propio texto. Sin texto en el archivo, el texto de la automatización entra en el primer mensaje de archivo.
  • En la API oficial, fuera de la ventana de 24 horas, el archivo se vuelve el encabezado de la plantilla aprobada y el texto del mensaje es el de la plantilla, llenado con variables. Para que salgan la imagen y el PDF, ligue dos automatizaciones: una con plantilla de imagen y otra con plantilla de documento.
  • Sin automatización ligada, el estado es sem_automacao y no se envía nada. El archivo queda guardado.
  • El mismo event y el mismo id no repiten el envío ni cambian el archivo. Si el archivo quedó afuera, use otro id.
  • La herramienta del MCP no recibe archivo. El archivo solo va por esta llamada HTTP.
  • Si la instalación todavía no activó el almacenamiento de archivo, la respuesta es 503 con files_unavailable. El aviso en JSON, sin archivo, sigue valiendo.
201 Created
{
  "event": {
    "event": "boleto_vence_hoje",
    "event_name": "Envio do boleto",
    "id": "BOL-2026-0001-hoje",
    "status": "enfileirado",
    "status_name": "Mensagem agendada",
    "message": "Envio recebido. O PDF do boleto e a imagem do Pix foram agendados, cada um com os dizeres.",
    "duplicate": false,
    "created_type": false,
    "new_variables": [],
    "queued": 1,
    "messages": [
      {
        "automation": "envio-do-boleto",
        "automation_name": "Envio do boleto e do Pix",
        "channel": "whatsapp",
        "scheduled_for": "2026-10-23T09:00:00-04:00"
      }
    ],
    "skipped": [],
    "send_at": null,
    "received_at": "2026-10-23T08:12:40-04:00",
    "files": [
      {
        "kind": "imagem",
        "file_name": "qr-pix.png"
      },
      {
        "kind": "documento",
        "file_name": "boleto.pdf"
      }
    ]
  }
}

Aviso solo con texto y enlace

El JSON de abajo no lleva archivo. El dato link_boleto solo existe cuando la boleta tiene una dirección pública. Un sistema de escritorio, sin URL, no manda ese dato: el PDF y la imagen van en el formulario de la sección Imagen y PDF. Un aviso por llamada, un paciente por aviso. La respuesta dice qué pasó y cuándo sale cada mensaje.

Ejemplo de llamada
curl -X POST "https://penseatende.com.br/api/integracao/eventos" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d @aviso.json
aviso.json
{
  "event": "boleto_vence_amanha",
  "event_name": "Boleto vence amanhã",
  "id": "BOL-2026-0001-vespera",
  "contact": {
    "phone": "5565999998888",
    "name": "Maria Souza",
    "email": "maria@exemplo.com.br"
  },
  "variables": {
    "valor": "R$ 150,00",
    "vencimento": "23/10/2026"
  },
  "send_at": "2026-10-22T09:00:00-04:00"
}
201 Created
{
  "event": {
    "event": "boleto_vence_amanha",
    "event_name": "Boleto vence amanhã",
    "id": "BOL-2026-0001-vespera",
    "status": "enfileirado",
    "status_name": "Mensagem agendada",
    "message": "Aviso recebido. A mensagem foi agendada pelas automações ligadas a ele.",
    "duplicate": false,
    "created_type": false,
    "new_variables": [],
    "queued": 1,
    "messages": [
      {
        "automation": "lembrete-de-boleto",
        "automation_name": "Lembrete de boleto na véspera",
        "channel": "whatsapp",
        "scheduled_for": "2026-10-22T09:00:00-04:00"
      }
    ],
    "skipped": [],
    "send_at": "2026-10-22T09:00:00-04:00",
    "received_at": "2026-10-21T18:12:40-04:00"
  }
}

Los campos

  • event: el código del aviso, en minúsculas, números, punto, guion o guion bajo, hasta 60 caracteres. Use siempre el mismo código para el mismo tipo de hecho.
  • id: la clave del aviso en su sistema, hasta 120 caracteres, como el número de la boleta más el tipo de recordatorio (BOL-2026-0001-vespera). El mismo event con el mismo id vale un solo aviso: enviarlo de nuevo no repite el mensaje.
  • contact.phone: el teléfono del paciente con código de país y de área, con o sin máscara: 5565999998888, +55 (65) 99999-8888 y 55 65 99999 8888 valen igual. Obligatorio.
  • contact.name, contact.email y contact.document: el nombre (entra en el mensaje como {{cliente}}, el primer nombre, y {{nome}}, el nombre completo), el correo (para el mensaje por correo) y el CPF o CNPJ, con o sin máscara (queda guardado, no va en el mensaje).
  • variables: los datos del aviso, hasta 30 por aviso, ya con el formato del mensaje: dinero como "R$ 1.234,56", fecha como "23/10/2026". link_boleto solo cuando existe URL. Un sistema de escritorio, sin URL, omite link_boleto y manda el archivo en los campos image y document. El nombre del dato, en minúsculas, números o guion bajo, es el mismo que usa la plantilla, como {{valor}}.
  • send_at: cuándo debe salir el mensaje, en ISO 8601 con el desplazamiento del huso horario: 2026-10-23T09:00:00-03:00 en Brasilia, -04:00 en Cuiabá y Manaos, -05:00 en Acre. Sin él, sale ahora, más la espera de la automatización. Hasta 180 días adelante; en el pasado se rechaza.
  • event_name: el nombre del aviso para la pantalla, usado solo la primera vez que llega el código.

Ejemplos de uso

  • Mensualidad con archivo: el día, boleto_vence_hoje con la imagen en image y el texto en image_text, y el PDF en document y el texto en document_text, más valor y vencimento. La víspera, boleto_vence_amanha; después del vencimiento, boleto_vencido. Quien no envía el archivo usa link_boleto en su lugar. Su sistema decide cuándo sale cada uno, o los envía todos de una vez, cada uno con su send_at.
  • Cumpleaños: aniversario con cupom y desconto, enviado el día, con send_at a las 9 horas.
  • Venta: compra_aprovada con produto y link_acesso, desde la plataforma de cursos o de pagos.

Qué dice la respuesta

  • 201 es aviso nuevo; 200 con duplicate: true es el mismo aviso otra vez, y no se repitió nada.
  • status: enfileirado (el mensaje quedó programado), sem_automacao (guardado, sin automatización ligada), recusado (las automatizaciones no programaron; el motivo de cada una viene en skipped) o desligado (la institución apagó este aviso).
  • messages: cada mensaje programado, con la automatización, el canal y scheduled_for, la hora de salida en el huso de la institución.
  • new_variables: los datos que llegaron por primera vez y se registraron en el aviso.
  • files: la imagen y el PDF guardados en esta llamada. Ausente cuando el aviso llegó solo en JSON.
  • Quien pidió no recibir más mensajes (respondió SAIR) no recibe nada en este teléfono.
  • El mensaje de oferta, como el descuento de cumpleaños, solo sale para quien aceptó recibirlo; el aviso de cobro y de compra sale siempre.
  • Fuera de la ventana de 24 horas de WhatsApp, la automatización usa una plantilla aprobada por Meta, con cada variable apuntando a un dato del aviso.
  • Cada automatización tiene tope diario y espera propios, que define la institución. El aviso nunca pasa por encima de eso.

Consultar un aviso y listar los avisos

GET /api/integracao/eventos?event=...&id=... muestra qué pasó con un aviso enviado. GET /api/integracao/eventos/tipos lista los avisos que la institución ya recibe, con los datos de cada uno y las automatizaciones ligadas: revise allí antes de enviar avisos reales.

Ejemplo de llamada
curl "https://penseatende.com.br/api/integracao/eventos/tipos" \
  -H "Authorization: Bearer SEU_TOKEN"
200 OK
{
  "event_types": [
    {
      "event": "boleto_vence_amanha",
      "name": "Boleto vence amanhã",
      "description": "O sistema de gestão avisa na véspera do vencimento da mensalidade.",
      "is_active": true,
      "variables": [
        {
          "key": "valor",
          "name": "Valor",
          "description": null,
          "example": "R$ 150,00"
        },
        {
          "key": "vencimento",
          "name": "Vencimento",
          "description": null,
          "example": "23/10/2026"
        },
        {
          "key": "link_boleto",
          "name": "Link boleto",
          "description": "Só quando o boleto tem endereço público. Sistema sem URL não manda este dado: manda o PDF no campo document.",
          "example": "https://seusistema.com.br/boletos/BOL-2026-0001.pdf"
        }
      ],
      "automations": [
        {
          "code": "lembrete-de-boleto",
          "name": "Lembrete de boleto na véspera",
          "channel": "whatsapp",
          "is_active": true,
          "delay_minutes": 0
        }
      ]
    }
  ]
}

Dónde usarla

Actualizado el 22/10/2026

La API es HTTP con JSON y un token en el encabezado, así que funciona en cualquier herramienta que haga una llamada HTTP. Abajo, el camino en las más usadas.

Sistema de gestión (ERP)

El flujo habitual: cada cierto tiempo (cada 5 o 10 minutos, por ejemplo), su sistema envía los productos que cambiaron, obtiene las ventas nuevas, las registra de su lado y confirma. Use la colección de Postman para ver cada llamada lista antes de programar.

n8n

  1. Para una automatización común, use el nodo HTTP Request. En Authentication, elija Generic Credential Type y Header Auth, con Name Authorization y Value Bearer SEU_TOKEN.
  2. Method GET y URL https://penseatende.com.br/api/integracao/vendas para obtener las ventas; method POST, URL https://penseatende.com.br/api/integracao/produtos y Body Content Type JSON para enviar productos.
  3. Para un agente de IA en n8n, use el nodo MCP Client Tool, como en la sección de MCP abajo.

Make

  1. Use el módulo HTTP > Make a request.
  2. URL: la dirección de la llamada, como https://penseatende.com.br/api/integracao/vendas. Method: GET o POST.
  3. En Headers, agregue Authorization con el valor Bearer SEU_TOKEN. En el POST, Body type Raw, Content type JSON (application/json).

Zapier

  1. Use la acción Webhooks by Zapier > Custom Request.
  2. Method y URL de la llamada, como GET y https://penseatende.com.br/api/integracao/vendas.
  3. En Headers, Authorization con Bearer SEU_TOKEN y, en el POST, Content-Type con application/json.

Asistentes de IA y LLMs

Para ChatGPT, Claude, agentes de n8n y cualquier cliente MCP, use el servidor MCP: el asistente ve las herramientas que el token permite y las llama solo. Los pasos están en la sección de MCP.

Los agentes que leen OpenAPI, como las acciones de un GPT personalizado, pueden importar la especificación de https://penseatende.com.br/api/integracao/openapi.json y usar autenticación Bearer con el token.

Código propio

Sirve cualquier lenguaje. Los ejemplos de abajo obtienen las ventas en JavaScript y en Python:

JavaScript
const resposta = await fetch("https://penseatende.com.br/api/integracao/vendas", {
  headers: { Authorization: "Bearer SEU_TOKEN" },
});
const { documents } = await resposta.json();
Python
import requests

resposta = requests.get(
    "https://penseatende.com.br/api/integracao/vendas",
    headers={"Authorization": "Bearer SEU_TOKEN"},
    timeout=30,
)
documents = resposta.json()["documents"]

Conectar por MCP

Actualizado el 02/11/2026

MCP es un estándar para conectar sistemas con asistentes de IA. Con él, ChatGPT, Claude, n8n y otros pueden consultar productos, inventario, ventas, atenciones y contactos de la institución con el mismo token de la API y los mismos permisos. Solo aparecen las herramientas que el token alcanza, de los módulos que la institución contrató. Cada herramienta dice si solo lee o si graba, y el asistente debe pedir su confirmación antes de grabar.

Herramientas disponibles:

  • enviar_produtos: Enviar productos, precios e inventario
  • consultar_produtos: Consultar productos, precio e inventario
  • buscar_vendas: Obtener ventas, cancelaciones y devoluciones
  • confirmar_vendas: Confirmar lo que se registró
  • listar_conversas: Listar atenciones
  • ver_conversa: Ver una atención
  • opcoes_de_atendimento: Opciones de la atención, para los filtros
  • atualizar_atendimento: Cambiar una atención
  • encerrar_atendimento: Cerrar una atención
  • consultar_contatos: Consultar contactos
  • salvar_contato: Guardar un contacto
  • enviar_aviso: Mandar aviso de outro sistema
  • consultar_aviso: Consultar aviso
  • tipos_de_aviso: Tipos de aviso

Dos formas de conectar

FormaDirecciónUse en
URL con el tokenhttps://penseatende.com.br/api/integracao/mcp/SEU_TOKENChatGPT, Claude (web y aplicación) y cualquier sistema que solo pide la URL del servidor.
URL + encabezadohttps://penseatende.com.br/api/integracao/mcpn8n y plataformas que aceptan el encabezado Authorization: Bearer SEU_TOKEN.

La URL con el token aparece en el panel de la institución al crear o reemplazar el token. Guárdela como una contraseña. La dirección suele quedar registrada en los registros del servidor, del proxy y en el historial del navegador, y la cabecera no: cuando el sistema acepte las dos formas, use la URL + cabecera.

ChatGPT

  1. En Settings > Apps & Connectors > Advanced settings, active el Developer mode.
  2. En Apps & Connectors, haga clic en Create.
  3. Nombre: Pense Atende. MCP Server URL: https://penseatende.com.br/api/integracao/mcp/SEU_TOKEN. Authentication: No authentication.
  4. Guarde y, en una conversación, active el conector Pense Atende.

Claude (web y aplicación)

  1. En Configuración > Conectores, haga clic en Agregar conector personalizado.
  2. Nombre: Pense Atende. URL del servidor MCP remoto: https://penseatende.com.br/api/integracao/mcp/SEU_TOKEN.

n8n

Nodo MCP Client Tool, conectado a un agente de IA:

  • Endpoint: https://penseatende.com.br/api/integracao/mcp
  • Server Transport: HTTP Streamable
  • Authentication: Header Auth, Name Authorization, Value Bearer SEU_TOKEN

Otros sistemas

Si el sistema acepta un servidor MCP remoto, registre la URL con el token. Si pide el tipo de conexión, elija HTTP. Los sistemas que no usan MCP, como Pipedrive, Conta Azul o Bling, pueden usar esta API directamente o n8n como puente.

Probar sin ninguna herramienta

Ejemplo de llamada
curl -X POST "https://penseatende.com.br/api/integracao/mcp/SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

El token y la URL con el token dan acceso a los datos de la institución. No los comparta. Si se filtran, la institución genera otro en el panel y el anterior deja de funcionar al instante.

Errores

Actualizado el 22/10/2026

Los errores vuelven como { "code": "...", "message": "..." }. El code es fijo, para que su sistema lo trate; el message lo explica en portugués. Cuando conviene esperar e intentar de nuevo (429 y 503), el encabezado Retry-After dice cuántos segundos. En MCP, el rechazo viene con isError y el mismo code en structuredContent, con retry_after_seconds en lugar del encabezado.

HTTPcodeCuándo
400invalid_jsonEl cuerpo no es un JSON válido.
400idempotency_key_requiredEn el envío de mensaje, faltó el encabezado Idempotency-Key (en el MCP, client_reference), o vino fuera del formato.
401unauthorizedToken incorrecto, conexión desactivada por la institución o institución desactivada.
401token_expiredEl token venció. Pida uno nuevo a la institución.
401company_mismatchLa llamada llegó por el dominio propio de una institución con el token de otra. Use la dirección de la institución dueña del token.
403forbiddenEl token no tiene permiso para este recurso. En la lectura y el envío de mensajes, también cuando el token no tiene fecha de vencimiento.
403module_not_contractedLa institución no contrató el módulo que este recurso exige. El mensaje dice cuál (productos y ventas piden Tienda, Inventario o PDV; atenciones piden WhatsApp, Chat o Soporte; contactos, esos o el CRM).
404resource_disabledEste recurso está desactivado en la plataforma.
404not_foundLa atención pedida no existe en la institución del token.
409contact_blockedLa institución bloqueó el contacto.
409window_closedEl paciente no escribió en las últimas 24 horas. Viene con reply_window_ends_at.
409opted_outEl paciente pidió salir de la lista de WhatsApp, respondiendo SAIR.
409idempotency_in_progressUn envío con la misma Idempotency-Key todavía está saliendo. Repita en algunos segundos, con la misma clave.
413too_largeMás de 2000 ítems de variants. Divida el envío.
422validation_failedFormato incorrecto. El mensaje indica el campo.
422consent_grant_not_allowedEl envío pidió whatsapp_consent aceito. Por la API solo se puede registrar el rechazo.
422invalid_optionCódigo de situación, prioridad o sector que la institución no tiene activo. field indica el campo y options, los códigos válidos.
422attendant_not_foundEl correo en assign_to_email no es de nadie del equipo de atención de esta institución.
422conversation_closedPasar a alguien una atención cerrada o archivada sin reabrirla en el mismo envío.
422channel_not_supportedLa atención no es de WhatsApp: por la API solo se puede responder atenciones de WhatsApp.
422group_not_allowedLa atención es de un grupo de WhatsApp.
422idempotency_key_reusedLa misma Idempotency-Key ya se usó en las últimas 24 horas para otro mensaje u otra atención.
429rate_limitedMás de 120 envíos en la última hora, o más de 120 llamadas en el último minuto. Espere el tiempo de Retry-After.
429daily_limit_reachedEl token llegó al tope del día: 2000 lecturas de mensajes, o 500 mensajes enviados. El límite vuelve a la medianoche, en el horario de Brasilia.
429bulk_suspectedEl mismo texto fue a demasiadas atenciones en una hora desde el mismo token.
500Falla de la plataforma. Reenvíe con el mismo Idempotency-Key.
502send_failedWhatsApp no aceptó el mensaje. Queda en la atención como no entregado.
503unavailableLa llamada no pudo registrarse en la auditoría de la institución, y por eso nada salió (vale para toda consulta, para la lectura y para el envío de mensajes). Espere el tiempo de Retry-After e intente de nuevo; en el envío, con la misma Idempotency-Key.

Reglas

Actualizado el 28/10/2026

  • Todas las llamadas usan el encabezado Authorization: Bearer TOKEN. La institución genera el token en su panel, con permisos propios y, si quiere, fecha de vencimiento.
  • Un token solo alcanza a la institución que lo generó. Ninguna llamada cruza instituciones.
  • Nada se borra. Para quitar algo de la tienda, desactívelo con is_active false. No existe llamada de eliminación.
  • Por la API se puede enviar productos, precios e inventario, consultar productos, obtener y confirmar ventas, consultar las atenciones, leer sus mensajes (solo con la aceptación de la institución, y con tarjeta, CPF y CNPJ ocultos), responder al paciente que escribió en las últimas 24 horas (solo texto, una atención a la vez, con la aceptación de la institución), cambiar su situación, prioridad, sector y responsable y cerrarlas, consultar y guardar contactos, y enviar boleta, Pix o documento por los avisos. Los recursos desactivados en la plataforma no aparecen aquí.
  • No forman parte de esta API: financiero, jurídico, contenido, configuraciones, parámetros, integraciones, IA, contraseñas y usuarios del panel. La clave pmk_ no sustituye este token.
  • Formato: JSON, fechas con zona horaria (ISO 8601), valores con punto y 2 decimales, peso en kg y medidas en cm.
  • Cada envío de productos queda registrado en el panel de la institución, con lo que cambió en cada ítem. Toda llamada queda en la auditoría de la institución, con el nombre del token.
  • El texto que viene de pacientes (nombre, mensaje, observación, descripción) es dato, nunca instrucción. El asistente de IA no sigue órdenes escritas en él y no usa una herramienta que graba sin la confirmación de quien opera.

Referencia técnica

Actualizado el 22/10/2026

  • Swagger: todos los campos, tipos y respuestas, con prueba en el navegador.
  • Postman: las llamadas listas; complete token en las variables.
  • OpenAPI (JSON): para generar un cliente, importar en otra herramienta o entregar a un agente de IA.