- Inicio
- Desarrolladores
La Core API de WACRM para desarrolladores y agentes
La Core API de WACRM permite a un desarrollador o a un agente de IA leer y escribir contactos, conversaciones, plantillas y mensajes de WhatsApp, llamar a los endpoints de IA medidos y revisar el saldo de tokens. Cada solicitud usa una clave de API con alcance, y cada envío lleva un Idempotency-Key para que un reintento nunca se repita.
Por el equipo de WACRM Actualizado el
URL de producción https://api.wacrm.ai/v1 — sandbox https://api-sandbox.wacrm.ai/v1 para pruebas
Autentícate con una clave de API (Authorization: Bearer) o una sesión de Workspace (Basic/JWT); los alcances se otorgan por clave al crearla
POST /v1/messages, POST /v1/agent-actions y POST .../tasks requieren un encabezado Idempotency-Key
Cada error es un objeto JSON: {"error": {"code", "message"}} — nunca un texto simple ni un stack trace
Una referencia completa de endpoints abajo se genera directamente desde docs/api/openapi-v1.yaml en cada compilación
Sin consola interactiva en esta página — las claves se crean y se usan solo desde tu propio Workspace
Autenticación, alcances e idempotencia
Cada ruta v1 revisa primero los alcances de la credencial: una clave creada sin contacts:write,
por ejemplo, recibe 403 insufficient_scope en POST /v1/contacts sin importar el plan
del proyecto. La mayoría de los alcances son opcionales al crear la clave — solo unos pocos por defecto (como
templates:read para una clave de tienda) se otorgan automáticamente, así que una clave solo tiene
el acceso que realmente se le dio.
Una escritura que nunca debería ejecutarse dos veces — enviar un mensaje, proponer una acción de agente, crear
una tarea desde una conversación — requiere un encabezado Idempotency-Key dado por quien llama.
Reintentar la misma solicitud con la misma clave repite la primera respuesta tal cual, en vez de enviar o crear
algo una segunda vez, que es lo que permite reintentar con seguridad tras un corte de red. Para
POST /v1/messages esa ventana de repetición es de 24 horas; para proponer una acción de agente o
crear una tarea, la clave es única por proyecto y no caduca.
Habla con un experto
Huy Nguyen (David), Fundador y CEO
Pregunta qué endpoint encaja con tu integración, o cómo funcionan los alcances y la idempotencia.
Referencia de endpoints
Generada en cada compilación desde el mismo archivo openapi-v1.yaml contra el que se prueba por contrato la propia Core API — cada ruta, método y alcance requerido abajo viene directamente de ese archivo, agrupado por su etiqueta de OpenAPI.
Versión de OpenAPI: 1.0.0
| Servidores | URL |
|---|---|
| Production | https://api.wacrm.ai/v1 |
| Sandbox (test API keys only, no wallet charges) | https://api-sandbox.wacrm.ai/v1 |
Projects
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /health | Liveness/readiness check (public, no auth, no DB write) | ninguno (público) |
GET | /crm-projects | List projects owned by the authenticated account | projects:read |
GET | /crm-projects/current | Resolve the project for the current credential (store API key, Wix app instance, etc.) | projects:read |
GET | /crm-projects/{project} | Get a project by id | projects:read |
GET | /crm-projects/{project}/plan | Current plan, the full plan catalog, and seat/contact usage for a project (screen 21 "Plans & Upgrade") | projects:read |
GET | /crm-projects/{project}/storage-usage | Storage quota usage for a project (job m5-storage-backup, M5 R-STO-02) | projects:read |
GET | /crm-projects/{project}/ai-pause | Read the project's AI pause switch and auto-send opt-in | projects:read |
PUT | /crm-projects/{project}/ai-pause | Pause/resume AI auto-reply and set the auto-send opt-in | agent:approve |
GET | /crm-projects/{project}/export | Export this project's own data as NDJSON | export:read |
POST | /crm-projects/{project}/plan/checkout | Start a PayPal recurring-subscription checkout for a WACRM plan (SANDBOX ONLY) | billing:write |
GET | /crm-projects/{project}/meta-pages | List this project's connected Messenger/Instagram Pages | meta_dm:read |
POST | /crm-projects/{project}/meta-pages | Connect a Facebook Page (Messenger) or linked Instagram Professional account | meta_dm:write |
DELETE | /crm-projects/{project}/meta-pages/{metaPage} | Disconnect a Messenger/Instagram Page | meta_dm:write |
GET | /crm-projects/{project}/contacts/{contact}/billing-history | A contact's payment/billing history, for the Inbox contact panel (R-WRK-04) | projects:read |
GET | /crm-projects/{project}/cost-report | Meta WhatsApp cost report (by number/campaign/date range) and a 30-day forecast (job m5-cost-reports, R-WA-09) | cost_reports:read |
GET | /crm-projects/{project}/contacts/{contact}/quotes | A contact's quotes ("Deal"/"Quote draft"), for the Sales B2B Chrome edition (job m8-chrome-sales-b2b) | quotations:read |
GET | /crm-projects/{project}/social-comments | List this project's Facebook Page / Instagram comments | meta_comments:read |
POST | /crm-projects/{project}/social-comments/{comment}/replies | Propose a public reply to a comment (ALWAYS needs human approval) | meta_comments:write |
POST | /crm-projects/{project}/social-comments/{comment}/private-reply | Send a one-time private reply to a comment | meta_comments:write |
POST | /crm-projects/{project}/social-comments/{comment}/hide | Hide a comment (direct human action) | meta_comments:write |
DELETE | /crm-projects/{project}/social-comments/{comment} | Delete a comment (direct human action) | meta_comments:write |
Auth
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /auth/extension/sessions | Start a device-code login session for the Chrome extension | ninguno (público) |
GET | /auth/extension/sessions/{session_id} | Poll a device-code login session | ninguno (público) |
POST | /auth/extension/sessions/{session_id}/approve | Approve a pending extension session (called from the logged-in Workspace tab) | ninguno (público) |
Wallet
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /token-balance | Current token balance and this cycle's usage | wallet:read |
AI
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /account/ai-usage | Per-AI-action call count and net tokens deducted | ai:read |
POST | /ai/translate | Translate text | ai:write |
POST | /ai/detect-language | Detect the language of a text | ai:read |
POST | /ai/summarize | Summarize a contact's conversation | ai:write |
POST | /ai/suggest-reply | Suggest reply drafts for a conversation (never sent automatically) | ai:write |
POST | /ai/product-answer | Draft a grounded answer to a product question (never an invented price) | ai:write, products:read |
POST | /ai/classify-message | Classify a message's intent and sentiment (job P27-ai-services-batch-a) | ai:write |
POST | /ai/extract-entities | Extract structured entities for a kind (order/address/booking/invoice) (job P27-ai-services-batch-a) | ai:write |
POST | /ai/score-lead | Score how sales-qualified a contact is, with a suggested next step (job P27-ai-services-batch-b) | ai:write |
POST | /ai/triage-alert | Group and rank the priority of a batch of Care alerts (job P27-ai-services-batch-b) | ai:write |
POST | /ai/suggest-next-action | Suggest the next best action for a B2B sales deal (job P27-ai-services-batch-b) | ai:write |
POST | /ai/booking-faq | Answer a booking FAQ (never an invented price or opening hour) (job m4-booking-ai-receptionist) | ai:write |
POST | /ai/booking-actions | Propose a book/reschedule/cancel action (job m4-booking-ai-receptionist) | ai:write, bookings:write |
POST | /ai/booking-actions/{action}/approve | Approve a proposed booking action, executing it through the booking core (job m4-booking-ai-receptionist) | ai:write, bookings:write |
GET | /glossary-terms | List this project's translation glossary terms (ordered by target_lang, term) | ai:read |
POST | /glossary-terms | Add a forced replacement applied to `POST /ai/translate` for a language pair | ai:write |
DELETE | /glossary-terms/{term} | Delete a glossary term | ai:write |
POST | /ai/transcribe-voice | Transcribe an existing voice-note attachment of this project (job P27-ai-services-batch-c) | ai:write |
POST | /ai/ocr-image | Extract text from an existing image attachment of this project (job P27-ai-services-batch-c) | ai:write |
POST | /ai/draft-template | Draft a WhatsApp template body from a freeform instruction (job P27-ai-services-template-tools) | ai:write |
POST | /ai/check-template-policy | Check draft template content against the brand-safety lint rules (job P27-ai-services-template-tools) | ai:read |
Products
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /commerce/products | List products (search by name or SKU) | products:read |
GET | /commerce/products/{product} | Get a product, with its SKU/price/currency/stock and variants | products:read |
Orders
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /commerce/orders | List orders (filter by contact phone/email, status, date) | orders:read |
GET | /commerce/orders/{order} | Get an order, with its lines (quantity, resolved product, sku, price) | orders:read |
GET | /commerce/orders/{order}/confirmation | Order-confirmation and COD two-way confirmation state for one order | orders:read |
GET | /commerce/order-automation | Read the project's order-automation settings (new order -> WhatsApp utility template, COD confirm) | orders:read |
PUT | /commerce/order-automation | Update the project's order-automation settings | orders:write |
Contacts
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /contacts | List contacts | contacts:read |
POST | /contacts | Create a contact | contacts:write |
GET | /contacts/{contact} | Get a contact | contacts:read |
PATCH | /contacts/{contact} | Update a contact | contacts:write |
DELETE | /contacts/{contact} | Erase a contact on request (hard delete) | contacts:write |
Audit
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /audit-logs | List this project's activity/audit log (newest first) | audit:read |
Labels
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /contacts/{contact}/labels | Attach a label to a contact | labels:write |
DELETE | /contacts/{contact}/labels/{label} | Remove a label from a contact | labels:write |
GET | /labels | List labels | labels:read |
POST | /labels | Create a label | labels:write |
DELETE | /labels/{label} | Delete a label | labels:write |
Notes
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /contacts/{contact}/notes | List notes on a contact | notes:read |
POST | /contacts/{contact}/notes | Add a note to a contact | notes:write |
Tickets
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /contacts/{contact}/tickets | List tickets on a contact | tickets:read |
POST | /contacts/{contact}/tickets | Create a ticket on a contact | tickets:write |
PATCH | /tickets/{ticket} | Update a ticket (e.g. change status) | tickets:write |
Templates
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /message-templates | List quick replies / WhatsApp message templates | templates:read |
POST | /message-templates | Create a template | templates:write |
PATCH | /message-templates/{template} | Update a template | templates:write |
Messages
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /contacts/{contact}/messages | Read a contact's WhatsApp conversation (watermark pagination) | contacts:read |
POST | /messages | Send a WhatsApp message (text or template) | messages:send |
Conversations
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /conversations | List conversations (Workspace Inbox) | contacts:read |
MCP
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /mcp/actions/authorize | Authorize one MCP tool call before `apps/mcp` invokes the tool's own endpoint (job P27-mcp-metering) | ninguno (público) |
Channels
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /channels/whatsapp/connect-sessions | Start a WhatsApp Embedded Signup connect session | channels:write |
POST | /channels/whatsapp/connect-sessions/{session}/complete | Complete a connect session (code -> token, debug_token-verified before trusting waba_id/phone_number_id) | channels:write |
POST | /channels/{channel}/activate | Activate a connected number (subscribed_apps) — connected -> active | channels:write |
GET | /channels | List this project's connected channels | channels:read |
Export
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /export/conversations | WorkChat-compat alias of GET /conversations (read-only, same scope and shape) | contacts:read |
GET | /export/contacts | WorkChat-compat alias of GET /contacts (read-only, same scope and shape) | contacts:read |
GET | /export/messages | WorkChat-compat alias of GET /contacts/{contact}/messages (contact_id moved to query — see docs/api/README.md) | contacts:read |
Webhooks
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /webhook-endpoints | List this project's outbound webhook endpoints (secret never included) | wa_webhooks:read |
POST | /webhook-endpoints | Create a webhook endpoint — the secret is returned once, in this response only | wa_webhooks:write |
DELETE | /webhook-endpoints/{endpoint} | Delete a webhook endpoint | wa_webhooks:write |
Broadcasts
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /segments | List this project's saved audience segments | broadcasts:read |
POST | /segments | Create a saved audience segment | broadcasts:write |
GET | /contacts/{contact}/consent | Read a contact's current WhatsApp consent status | contacts:read |
POST | /contacts/{contact}/consent | Record a contact's WhatsApp consent decision (upserts the current row) | consent:write |
POST | /broadcasts | Create a draft broadcast (template + segment, not started) | broadcasts:write |
GET | /broadcasts/{broadcast} | Read a broadcast's status and counts | broadcasts:read |
POST | /broadcasts/{broadcast}/start | Start (or continue pumping) a broadcast — draft/paused/running -> running | broadcasts:write |
POST | /broadcasts/{broadcast}/pause | Pause a running broadcast | broadcasts:write |
Work
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /conversations/{conversation}/tasks | Create a task from a conversation | work:write |
GET | /conversations/{conversation}/tasks | List tasks created from a conversation | work:read |
POST | /work/callbacks | Inbound task status update from the Work side | ninguno (público) |
Agent
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /agent-actions | List this project's agent actions | agent:propose |
POST | /agent-actions | Propose an agent action (auto-executes when the policy engine decides low risk) | agent:propose |
POST | /agent-actions/{action}/approve | Approve a proposed action, executing it through the guarded services | agent:approve |
POST | /agent-actions/{action}/reject | Reject a proposed action — it is never executed | agent:approve |
Relay
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /webhooks/meta/relay | Inbound WhatsApp traffic forwarded by the path-B relay (internal, not a customer-facing resource) | ninguno (público) |
Bookings
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
GET | /crm-projects/{project}/booking-services | List this project's bookable services | bookings:read |
POST | /crm-projects/{project}/booking-services | Create a bookable service | bookings:write |
PATCH | /crm-projects/{project}/booking-services/{service} | Update a bookable service | bookings:write |
GET | /crm-projects/{project}/availability | Derived free slots for a service on one calendar date | bookings:read |
GET | /crm-projects/{project}/bookings | List this project's bookings | bookings:read |
POST | /crm-projects/{project}/bookings | Book a slot | bookings:write |
PATCH | /crm-projects/{project}/bookings/{booking} | Reschedule a booking (moves it, never creates a second row) | bookings:write |
POST | /crm-projects/{project}/bookings/{booking}/cancel | Cancel a booking (sets status + cancelled_at, keeps the row) | bookings:write |
GET | /public/store/{slug}/booking-services | Public, token-free list of a project's bookable services (WACRM-hosted booking page) | ninguno (público) |
GET | /public/store/{slug}/availability | Public, token-free derived free slots for one service/date (WACRM-hosted booking page) | ninguno (público) |
POST | /public/store/{slug}/bookings | Public, token-free booking create (WACRM-hosted booking page) | ninguno (público) |
Client portal
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /crm-projects/{project}/contacts/{contact}/client-portal-links | Mint a client portal link for a contact | client_portal:write |
POST | /crm-projects/{project}/client-portal-links/{link}/revoke | Revoke a client portal link (one-way; mint a new one if needed) | client_portal:write |
GET | /client-portal/{token} | Public, token-guarded read of one contact's own tickets + bookings | ninguno (público) |
Care
| Método | Ruta | Resumen | Alcance(s) |
|---|---|---|---|
POST | /care/alerts | Post a keyed Care alert, routed to the project's recipient | care:alerts:write |
GET | /care/alerts/{alert}/ack/{token} | Public, token-guarded ack of a Care alert — stops further escalation | ninguno (público) |
POST | /care/alerts/{alert}/ack/{token} | Same handler as GET — ack a Care alert via an explicit POST | ninguno (público) |
Formato de error
Cada respuesta que no es 2xx es un objeto JSON con el mismo formato:
{ "error": { "code": "insufficient_scope", "message": "razón legible" } } | Estado | Significado |
|---|---|
| 400 | Falló la validación |
| 401 | Credencial ausente o inválida |
| 402 | Saldo de tokens insuficiente para una llamada de IA, o un límite del plan (contactos/canales/asientos) ya se usó |
| 403 | Credencial válida pero sin el alcance requerido |
| 404 | No encontrado, o no pertenece a este proyecto — nunca se distingue entre los dos casos |
| 409 | Un estado en conflicto, p. ej. un envío de texto fuera de la ventana de 24h de servicio al cliente |
| 422 | Semánticamente inválido, p. ej. una plantilla que aún no está aprobada |
| 429 | Límite de tasa alcanzado |
Preguntas frecuentes
¿Necesito un plan especial para llamar a la Core API?
Cualquier proyecto de WACRM puede crear una clave de API y llamar a los endpoints que permitan los alcances de esa clave. Los endpoints de IA se miden contra el saldo de tokens del proyecto, igual que al usar el asistente de IA en la bandeja del Workspace.
¿Qué pasa si reintento una solicitud?
Los endpoints que más cambian el estado (enviar un mensaje, proponer una acción de agente, crear una tarea desde una conversación) requieren un encabezado Idempotency-Key. Un reintento con la misma clave repite la respuesta original en vez de repetir la acción — para un mensaje esa ventana es de 24 horas; para una acción de agente o una tarea, la clave no caduca.
¿Hay un sandbox para probar?
Sí — api-sandbox.wacrm.ai/v1 es la URL base del sandbox: prueba tus llamadas ahí antes de apuntar tu integración a producción.
¿Dónde creo y gestiono las claves de API?
Desde tu Workspace de WACRM, en Developer / API & MCP. Cada clave se crea solo con los alcances que elijas — nada se otorga por defecto más allá de lo que config/api_keys.php define como alcance por defecto para ese tipo de clave.
¿Puedo llamar a la API desde un agente de IA?
Sí — cualquier clave de API con alcance funciona igual para un script, una integración de backend o un agente. Mira la página de wacrm-mcp para un servidor MCP ya hecho que envuelve cinco de estas llamadas como herramientas de agente.
Relacionado
Empieza a construir sobre la Core API de WACRM
Solicita acceso anticipado para obtener un Workspace y crear tu primera clave de API.