API and webhooks

Connect your system to your assistant, without asking anyone for anything

A REST API to read and write your business data, and signed webhooks that notify your system when a contact comes in, an appointment is booked or the assistant hands off to a person. Keys and webhooks are managed from your dashboard, under Integrations.

/api/v1Base URL
6Webhook events
120/minRequests per key
1. Authentication

One key per system

Go to your dashboard, menu Integrations, and create a key with a name (for example, the system that will use it). The full key is shown only once: store it in your system. If you lose it, revoke it and create a new one.

Every request carries the key in the header Authorization:

curl -H "Authorization: Bearer ap_k7f3m2x9q1_a1b2c3..." https://asistentepro.cl/api/v1/cuenta
  • Read only: reads contacts, conversations, appointments and the catalog.
  • Read and write: also changes statuses, creates appointments, replaces the catalog and sends messages.
  • A key only sees its own business's data. IDs from another account return 404.
2. Format

Always JSON, always the same shape

Successful responses include ok: true and the data in data; lists add paginacion. Errors include ok: false, a stable code in error and an explanation in message.

{
  "ok": true,
  "data": [
    {
      "id": "clx1...",
      "nombre": "Ana Pérez",
      "contacto": "56912345678",
      "correo": "[email protected]",
      "canal": "whatsapp",
      "estado": "calificado",
      "etapa": "seguimiento",
      "notas": "Quiere cotizar 3 servicios para noviembre.",
      "conversacionId": "clx9...",
      "creadoEl": "2026-10-20T14:03:11.000Z",
      "actualizadoEl": "2026-10-20T14:09:40.000Z"
    }
  ],
  "paginacion": { "pagina": 1, "porPagina": 50, "total": 1 }
}

Dates are in ISO 8601 (UTC). Phone numbers include the country code, with no symbols: 56912345678.

3. Endpoints

What an external system actually needs

Base URL: https://asistentepro.cl/api/v1

GET/v1/cuentaread

Returns the business and the key you signed in with. Useful for testing the connection.

curl -H "Authorization: Bearer TU_LLAVE" https://asistentepro.cl/api/v1/cuenta
GET/v1/leadsread

Lists the business's contacts (leads), newest first. Filters: desde, hasta (creation date, ISO 8601), estado (nuevo, calificado, contacto_comercial, ganado, perdido), canal (whatsapp, instagram, facebook, web). Paginated with pagina and porPagina (maximum 100).

curl -H "Authorization: Bearer TU_LLAVE" "https://asistentepro.cl/api/v1/leads?estado=nuevo&desde=2026-10-01&porPagina=50"
GET/v1/leads/:idread

A contact with its full record and the ID of its latest conversation.

curl -H "Authorization: Bearer TU_LLAVE" https://asistentepro.cl/api/v1/leads/ID_DEL_LEAD
PATCH/v1/leads/:idwrite

Changes a contact's status and/or notes (its record). Fires the lead.actualizado event.

curl -X PATCH -H "Authorization: Bearer TU_LLAVE" -H "Content-Type: application/json" \
  -d '{"estado":"ganado","notas":"Cerró plan anual, factura 1234"}' https://asistentepro.cl/api/v1/leads/ID_DEL_LEAD
GET/v1/conversaciones/:id/mensajesread

The messages of a conversation in chronological order. Each message says whether it was written by the customer, the assistant or a team member. Paginated (porPagina up to 200).

curl -H "Authorization: Bearer TU_LLAVE" https://asistentepro.cl/api/v1/conversaciones/ID_CONVERSACION/mensajes
GET/v1/citasread

Appointments in a date range (desde, hasta; the next 30 days by default; maximum 92 days). Status filter (estado): agendada, hecha, cancelada.

curl -H "Authorization: Bearer TU_LLAVE" "https://asistentepro.cl/api/v1/citas?desde=2026-10-20&hasta=2026-11-20"
POST/v1/citaswrite

Creates an appointment for the business with the same validation as the dashboard: titulo and inicio are required, correo must be valid if present, and it returns 409 horario_ocupado if it overlaps another appointment. Sends the calendar invite (if there's an email) and schedules the WhatsApp reminders (if there's a contact). Fires cita.creada.

curl -X POST -H "Authorization: Bearer TU_LLAVE" -H "Content-Type: application/json" \
  -d '{"titulo":"Visita técnica","inicio":"2026-10-22T15:00:00-03:00","duracionMin":45,"contacto":"56912345678","nombre":"Ana Pérez","correo":"[email protected]","notas":"Revisión anual"}' \
  https://asistentepro.cl/api/v1/citas
GET/v1/catalogoread

All the products or services in the catalog, with price, stock and category. The internal cost is never exposed.

curl -H "Authorization: Bearer TU_LLAVE" https://asistentepro.cl/api/v1/catalogo
PUT/v1/catalogowrite

Replaces the catalog with the list you send (up to 500 products). Matches by name: existing ones are updated, new ones are created and those not included become inactive (they aren't deleted: they keep their photo, order and featured flag). Fields: nombre (required), precio, stock, categoria, descripcion, precioTexto, activo.

curl -X PUT -H "Authorization: Bearer TU_LLAVE" -H "Content-Type: application/json" \
  -d '{"productos":[{"nombre":"Queso mantecoso 1 kg","precio":8990,"stock":24,"categoria":"Quesos"},{"nombre":"Jamón serrano 250 g","precio":6490,"stock":0,"categoria":"Cecinas"}]}' \
  https://asistentepro.cl/api/v1/catalogo
POST/v1/mensajeswrite

Sends a text on WhatsApp to a contact, ONLY if the 24-hour window is open (the customer wrote less than 24 hours ago). If it's closed, it returns 409 ventana_cerrada and sends nothing: WhatsApp only accepts template messages outside that window. With pausarAsistente: true the assistant stops replying in that thread until someone releases it from the dashboard.

curl -X POST -H "Authorization: Bearer TU_LLAVE" -H "Content-Type: application/json" \
  -d '{"contacto":"56912345678","texto":"Tu pedido #482 ya está listo para retiro."}' https://asistentepro.cl/api/v1/mensajes
4. Webhooks

We notify you when something happens

In Integrations add your system's https URL and choose the events. Every time one happens, we send a POST with JSON to that URL. Your server must respond with a 2xx code in under 8 seconds; do the heavy work after responding.

EventWhen it's sent
lead.creadoA new contact wrote for the first time, or was created from the dashboard or the API.
lead.actualizadoA contact's status or record changed (by the assistant, the dashboard or the API).
cita.creadaAn appointment was booked (by the assistant, the dashboard or the API).
cita.canceladaAn appointment was canceled or deleted.
derivacion.creadaThe assistant handed a conversation off to a person: the customer asked to talk to someone, a complaint, a question it couldn't resolve, or the AI service couldn't respond.
mensaje.recibidoA message from a customer arrived on WhatsApp or Instagram.

The body includes id (unique per notification and repeated on retries: use it to avoid processing twice), evento, fecha, negocioId and datos with the same shape the API returns.

POST https://misistema.cl/webhooks/asistentepro
Content-Type: application/json
X-AsistentePro-Evento: cita.creada
X-AsistentePro-Entrega: wh_8f2c...
X-AsistentePro-Timestamp: 1760990000
X-AsistentePro-Firma: 3b1f9c...   (HMAC-SHA256 en hexadecimal)

{
  "id": "wh_8f2c...",
  "evento": "cita.creada",
  "fecha": "2026-10-20T18:00:00.000Z",
  "negocioId": "clorg...",
  "datos": {
    "id": "clx5...",
    "titulo": "Visita técnica",
    "contacto": "56912345678",
    "inicio": "2026-10-22T18:00:00.000Z",
    "duracionMin": 45,
    "estado": "agendada"
  }
}
  • Retries: if your server doesn't respond with 2xx, we try up to 3 times in total (immediately, 1 minute later and 5 minutes later). A redirect (3xx) counts as a failure.
  • URLs: public https only. Local or private network addresses are rejected when saved and when sending.
  • Test: the "Test" button in the dashboard sends a prueba event and shows you what your server responded. The last 20 deliveries and their status stay visible.
5. Signature

Check that the notification comes from AsistentePro

When you create the webhook we give you a secret (only once). Every notification includes X-AsistentePro-Timestamp (unix seconds) and X-AsistentePro-Firma: the HMAC-SHA256, using your secret, of the text <timestamp>.<cuerpo>, in hexadecimal. Compute the same over the raw body you received and compare. Discard notifications older than 5 minutes.

import crypto from 'node:crypto'

// cuerpoCrudo: el cuerpo EXACTO que llegó (string o Buffer), no el JSON ya parseado y vuelto a serializar.
function firmaValida(secreto, cabeceras, cuerpoCrudo) {
  const ts = Number(cabeceras['x-asistentepro-timestamp'])
  const firma = String(cabeceras['x-asistentepro-firma'] || '')
  if (!ts || Math.abs(Date.now() / 1000 - ts) > 300) return false // más de 5 minutos: se descarta
  const esperada = crypto.createHmac('sha256', secreto).update(`${ts}.${cuerpoCrudo}`).digest('hex')
  const a = Buffer.from(esperada, 'hex'); const b = Buffer.from(firma, 'hex')
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}
6. Errors and limits

Codes you'll see

AnswerWhat it means
401 llave_invalidaThe key doesn't exist, is mistyped or was revoked.
403 permiso_insuficienteThe key is read-only and the endpoint modifies data.
403 cuenta_pausadaThe business account is paused.
404 no_encontradoThe ID doesn't exist in this account (IDs from other businesses always return 404).
400 fecha_invalida / estado_invalido / faltan_datos / correo_invalidoCheck the body or the filters; the message field explains what's missing.
409 horario_ocupadoThere's already an appointment at that time (citaId is included).
409 ventana_cerradaNon-template text can't be sent to that contact until they write again.
429 rate_limitedMore than 120 requests per minute with the same key. Wait as long as Retry-After says.

Limit: 120 requests per minute per key (headers X-RateLimit-Limit and X-RateLimit-Remaining). Up to 10 active keys and 10 webhooks per business.

Need an endpoint that isn't here? Write to us from your dashboard: this first version covers what an external system actually uses and grows with what businesses ask for.