Guía para integradores (ES/EN) de la API de tareas de RouterClip: conecta tu herramienta de tareas (Jira, Asana, ClickUp, Linear, Monday, Trello, Notion…) para leer, modificar y ejecutar el trabajo pendiente de todas las funcionalidades con una clave de servidor. Estado: disponible. Es parte de la API v1: lo común (fuentes, claves, formato de errores, X-Request-ID, eventos y contactos) está en /developers/api-v1.html.
- Contrato OpenAPI (generado de las rutas reales, una etiqueta por área, con ejemplos):
https://www.routerclip.com/developers/api-v1.json. - Catálogo estático de tipos y acciones (lo mismo que
GET /api/v1/task-kindscon todos los permisos, más las rutas de recurso de cada acción y el catálogo de scopes):https://www.routerclip.com/developers/api-v1-task-kinds.json. - Documentación publicada / Published documentation: esta guía, la de la API v1, el contrato y el catálogo están en
https://www.routerclip.com/developers/, enlazados desde el panel de la API de tareas (Integraciones → API y eventos) y desde el pie de la web pública. / This guide, the API v1 guide, the contract and the catalog are published at/developers/, linked from the task API panel and the public site footer.
Español
1. Activación
- El equipo de RouterClip activa para tu empresa la función «API de tareas y funciones» (
api.tasks). Sin ella, todas las rutas de esta guía responden403 FEATURE_DISABLED. Algunas áreas necesitan además su propia función (secuenciascrm.sequences, guionescrm.playbooks, duplicadoscrm.merge, conversionesmarketing.tracking…): sin ella sus tipos desaparecen del feed y sus rutas responden403 FEATURE_DISABLED. - Si vas a usar webhooks, pide también que la plataforma autorice el origen HTTPS de tu herramienta (por ejemplo,
https://hooks.example.com). El envío de webhooks de tareas tiene además un interruptor global; mientras está apagado, las entregas esperan en cola hasta 30 días: si se activa antes, salen; si no, caducan como fallidas (Expired: not sent within 30 days) y, con el envío activado, se pueden reintentar a mano (POST …/deliveries/{id}/retry). Los 30 días cuentan desde que la entrega entró en la cola, desde su último intento o desde el último reintento manual: un reintento empieza una serie nueva de intentos con su propio plazo, aunque el primero vuelva a fallar. - Un administrador crea una fuente por herramienta en Ajustes → Integraciones → API y eventos (por ejemplo, «Jira Soporte»), elige un paquete de scopes (§2) y, en «Actuar como», los usuarios que la herramienta puede representar (§3).
- Emite la clave de la fuente (
aio_<keyId>.<secreto>, se ve una sola vez; dos claves activas para rotar sin cortes) y, si quiere, registra el webhook de tareas (§9). Comprueba la clave conGET /api/v1/keyy lo que puede hacer conGET /api/v1/key/capabilities(áreas y tipos visibles, funciones activas, usuarios delegables y usuario por defecto).
Todas las peticiones llevan Authorization: Bearer aio_<keyId>.<secreto> y Content-Type: application/json. Es una API de servidor a servidor: sin CORS; la clave nunca va en un navegador, en una URL ni en un log. Comprobaciones de cada petición, en orden: clave y fuente, empresa activa (401), acceso al servicio (402), función (403), cuotas (429) y scopes (403).
2. Scopes y paquetes
Los scopes tienen la forma <área>:<nivel>. Los niveles no se heredan (execute no incluye write ni read):
| Nivel | Equivale en la UI a | Permite |
|---|---|---|
read | lector | Leer tareas y recursos del área, sus historiales e informes |
write | agente | Crear registros y borradores, editar (PATCH) y añadir notas |
execute | agente | Acciones operativas: completar, resolver, responder, reintentar, conciliar… |
admin | administrador | Programar, decidir, fusionar, verificar y revisar inciertos; exige actuar como un administrador (§3) |
content | lector con contenido | Cuerpos de mensajes, notas internas, textos de clientes y transcripciones |
| Área | Scopes | Función exigida además de api.tasks |
|---|---|---|
| Contactos | contacts:read, contacts:write, subscriptions:invite | Invitaciones (subscriptions:invite): marketing.api |
| Empresas cliente | companies:read, companies:write | — |
| Oportunidades | deals:read, deals:write, deals:execute | — |
| Actividades y seguimientos | activities:read, activities:write, activities:execute | — |
| Secuencias comerciales | sequences:read, sequences:execute | crm.sequences |
| Guiones comerciales | playbooks:read, playbooks:write, playbooks:execute | crm.playbooks |
| Duplicados y fusiones | duplicates:read, duplicates:write, duplicates:admin | crm.merge |
| Conversaciones y tickets | support:read, support:write, support:execute, support:admin, support:content | — |
| Encuestas CSAT | csat:read, csat:execute, csat:admin | Entregas: support.csat_auto |
| Voz | voice:read, voice:execute, voice:admin, voice:content | — |
| Calendario | calendar:read, calendar:execute | — |
| Campañas | campaigns:read, campaigns:write, campaigns:admin | Push: marketing.push; experimentos: marketing.experiments |
| Recorridos | journeys:read, journeys:admin, automations:enroll | Disparo por evento: marketing.api |
| Segmentos | segments:read | Bloques de comportamiento: marketing.behavior |
| Formularios y páginas | forms:read, forms:admin | Formularios alojados: marketing.pages |
| Sitios web | sites:read, sites:admin | Dominios propios: marketing.custom_domains |
| Conversiones | conversions:read, conversions:admin | marketing.tracking |
| Conocimiento | knowledge:read, knowledge:admin | — |
| Canales y conexiones | channels:read, channels:admin | — |
| Informes | reports:read | La de cada informe |
| Equipo | team:read, team:emails | — |
| Webhooks de tareas | webhooks:manage | — |
| Flujos de automatización | automation:read, automation:enroll (iniciar los flujos con disparador «Por la API»; en ningún paquete) | automation.flows |
| — | act_as (actuar como un usuario de la lista de la fuente) | — |
Paquetes de la pantalla de administración: Lectura de tareas (*:read de las áreas activas y team:read), Gestión de tareas (lo anterior más activities:write/execute, deals:write/execute, support:write/execute, playbooks:write/execute, csat:execute, voice:execute, calendar:execute y act_as), Operación completa (más los *:admin de las áreas activas y webhooks:manage) y Personalizado. Los scopes *:admin, *:content, team:emails y act_as son sensibles y piden confirmación expresa.
Reglas: el feed solo muestra los tipos de las áreas que la clave puede leer (en webhooks, webhooks:manage cuenta como lectura); el PATCH exige <área>:write y, si cambia el estado, también el nivel de la acción equivalente; cada acción exige el scope que declara el catálogo. Ningún scope equivale a un administrador completo.
3. Actor y delegación
Una clave no es un usuario. Cada acción declara qué actor admite:
| Actor | Quién actúa | Dónde |
|---|---|---|
service | La propia fuente, sin usuario (los historiales muestran «Integración») | Acciones que no autorizan por usuario: actividades, oportunidades, estados de ticket, reintentos… Nunca pasa de execute ni habla con clientes |
delegated | Un usuario de la lista de la fuente | Responder, notas con mención, posponer, macros y todas las acciones de nivel admin |
owner | El delegado, que además es el titular del buzón comercial | Secuencias: reanudar, saltar paso, reintentar y responder |
recipient | El delegado, que además es el destinatario de la mención | Marcar una mención como leída |
- La petición elige el usuario con
X-AIO-Act-As: <userId>; sin cabecera actúa el usuario por defecto de la fuente, si lo hay. La clave necesita el scopeact_as. - Errores:
403 DELEGATED_USER_REQUIRED(la acción necesita un delegado),403 DELEGATED_USER_NOT_ALLOWED(usuario fuera de la lista o clave sinact_as),403 DELEGATED_USER_INACTIVE(inactivo o de otra empresa, mismo mensaje),403 ACTOR_ROLE_INSUFFICIENT(su rol no alcanza el de la ruta de la UI),403 MAILBOX_OWNER_REQUIREDy403 MENTION_RECIPIENT_REQUIRED. - El permiso efectivo es la intersección de los scopes de la clave, el rol del delegado y las condiciones de titular o destinatario. La delegación no crea sesión y solo sirve en
/api/v1. - Lista de la fuente: hasta 20 usuarios activos (administradores o agentes) y un usuario por defecto opcional; cada cambio guarda autor y fecha. Para mapear responsables,
GET /api/v1/members(team:read; el email solo conteam:emails).
4. Modelo de tarea
Una tarea es una proyección de su entidad de origen (actividad, ticket, campaña…), no una copia: no hay tabla de tareas, y responsable, fecha, prioridad y notas solo se editan donde la entidad los tiene. El identificador es <kind>:<clave> (hasta 200 caracteres A-Z a-z 0-9 . _ : -, va en la ruta sin codificar), por ejemplo support.ticket:9d2f… o crm.duplicate_review:contact:<idMenor>:<idMayor>.
{ "id": "support.ticket:9d2f4b1c0a7e4e21b3c5d6e7f8091a2b", "kind": "support.ticket", "area": "support", "schemaVersion": 1,
"title": "No llega la factura de septiembre", "status": "waiting", "sourceStatus": "waiting_customer",
"signals": ["sla_resolution_at_risk"], "priority": "high", "assignee": { "type": "user", "id": "3c1f…", "name": "Ana Ruiz" },
"dueAt": "2026-09-30T16:00:00Z", "dueKind": "sla_resolution", "links": [ { "type": "contact", "id": "77aa…", "name": "Lucía Gómez" } ],
"appUrl": "https://www.routerclip.com/app/tickets/9d2f…", "version": 18, "etag": "W/\"h:3fa9c2d17b0e4a55\"",
"editable": ["status", "sourceStatus", "assigneeId", "teamId", "priority", "title", "category"],
"actions": [ { "name": "resolve", "scope": "support:execute", "actor": "service", "available": true, "preview": false } ],
"externalLink": { "externalId": "SUP-431", "url": "https://jira.example.com/browse/SUP-431" } }
statusnormalizado:open,in_progress,waiting,needs_review,doneocancelled;sourceStatusconserva el estado nativo ysignalsañade marcas de un catálogo cerrado (overdue,due_soon,unassigned,sla_resolution_breached,uncertain,reconnect_required…). Ignora los valores que no conozcas.dueAtva condueKind(due,sla_resolution,wake,send_at,undo_until…); fechas en RFC 3339 y UTC.etag:W/"<n>"en las entidades con revisión yW/"h:<16 hex>"(hash del estado escribible, calculado en vivo) en el resto. Es la precondición de escritura (§7).actions: cada acción con su scope, actor,availabley, si no lo está,unavailableReason(STATE,DELEGATED_USER_REQUIRED,MAILBOX_OWNER_REQUIRED,SCOPE_MISSING,FEATURE_DISABLED,SEND_SWITCH_OFF,ACTOR_ROLE_INSUFFICIENT,MENTION_RECIPIENT_REQUIRED), calculada con la clave y el delegado de esta petición.- Contenido y datos personales:
titlenunca es un cuerpo; los textos de clientes y notas exigen<área>:content; un contacto enlazado solo lleva los campos de lectura de la fuente, y mostrar alguno cuenta como una lectura del contacto en el registro de lecturas (una por clave, contacto y petición; /developers/api-v1.html §8), igual en el feed, los tickets, las conversaciones, las llamadas y las reservas. Nada personal viaja en la URL: búsquedas y lookups van porPOST.
Tipos (28; el detalle de estados, campos de PATCH y acciones está en el catálogo estático):
| Área | Tipos | Acción de cierre (completion) |
|---|---|---|
| Actividades | crm.activity | complete |
| Oportunidades | crm.deal_attention | — |
| Duplicados | crm.duplicate_review, crm.merge_review | — |
| Guiones | crm.playbook_session | — |
| Secuencias | sales.enrollment, sales.mailbox, sales.conversation | sales.conversation: mark_read |
| Soporte | support.ticket, support.mention, support.customer_message | resolve, mark_read, mark_done |
| CSAT | support.csat_delivery | — |
| Voz | voice.job, voice.capacity_review | — |
| Calendario | calendar.booking | — |
| Campañas | marketing.campaign, marketing.delivery_review, marketing.experiment_decision | — |
| Recorridos | marketing.journey_attention, marketing.journey_version | — |
| Formularios | marketing.form_publication, marketing.placement | — |
| Sitios | marketing.site_verification, marketing.page_domain | — |
| Conversiones | marketing.conversion_reconciliation | — |
| Conocimiento | knowledge.source_error | — |
| Canales | channel.health | — |
| Webhooks | integration.webhook_failed | — |
Sin acción de cierre, cerrar la tarea exige una decisión: muestra sus acciones en la herramienta en vez de un simple «hecho».
5. Endpoints
| Grupo | Endpoints |
|---|---|
| Tareas | GET y POST /api/v1/tasks; GET y PATCH /api/v1/tasks/{taskId}; POST /api/v1/tasks/{taskId}/actions/{action}; GET y POST …/notes; GET …/history; PUT y DELETE …/external-link; POST /api/v1/tasks/lookup |
| Catálogo y sincronización | GET /api/v1/task-kinds, GET /api/v1/task-changes/cursor, GET /api/v1/task-changes y GET /api/v1/task-summary |
| Recursos | Contactos y empresas, oportunidades y pipelines, actividades, secuencias, guiones, duplicados y fusiones, conversaciones y tickets, recados, CSAT, voz, calendario, campañas y plantillas, recorridos, segmentos, formularios, sitios, conversiones, conocimiento, canales, webhooks de marketing, informes y miembros |
| Webhooks de tareas | GET y POST /api/v1/webhooks; GET, PATCH y DELETE /api/v1/webhooks/{id}; POST …/rotate-secret; POST …/test; GET …/deliveries; POST …/deliveries/{deliveryId}/retry |
| Clave | GET /api/v1/key, GET /api/v1/key/capabilities y GET /api/v1/members |
| Flujos de automatización | GET /api/v1/automation/flows, GET /api/v1/automation/flows/{flowId}, GET …/flows/{flowId}/runs, GET /api/v1/automation/runs/{runId} y POST /api/v1/automation/flows/{flowId}/enroll |
| Feed de eventos | GET /api/v1/events y GET /api/v1/event-types (/developers/api-v1.html, §6 bis): los hechos de las áreas que la clave lee, con events:read |
- Flujos de automatización (
automation:read; funciónautomation.flows): estado, tipo de disparador y versión en uso, nunca la configuración (definición, borrador, condiciones, nombres ni detalles de los pasos). Las ejecuciones (más recientes primero, filtrosstatusysubjectId, cursor firmado de 24 h) dan su estado, paso, códigos, el hecho que las inició (triggerEventId, uniddel feed de eventos) y, en la ficha, cada paso con su tipo, estado,resultCodey el registro que creó (effect). Iniciar (automation:enroll):POST …/flows/{flowId}/enrollcon{"subject": {"type": "contact" | "deal" | "conversation", "id": "…"}}eIdempotency-Keyobligatoria (428); solo flujos publicados con disparador «Por la API» (409 FLOW_NOT_PUBLISHED/FLOW_TRIGGER_NOT_API) y del tipo de sujeto del flujo (422 SUBJECT_TYPE_MISMATCH). Decide en la petición con las comprobaciones de entrada del flujo:201 {"result": "started", "runId"}o200 {"result": "skipped", "reason"}conflowNotActive,subjectUnavailable,conditionsNotMet,activeRunExists,alreadyRan,cooldownoentryLimitReached. La misma clave y cuerpo repiten la respuesta (Idempotent-Replayed: true); otro cuerpo,409 IDEMPOTENCY_CONFLICT.startedno es «hecho»: los pasos los ejecuta el motor con todas sus comprobaciones y un flujo nunca escribe al cliente por su cuenta. Cuenta en la cuota de acciones y queda en «Actividad de la API».automation:enrollno esautomations:enroll(recorridos). - Listado
GET /api/v1/tasks: filtroskindyarea(listas de hasta 10),status(por defecto los abiertos),assigneeId,assignee=me(el delegado),unassigned=true,teamId,dueBefore,dueAfter,overdue=true,signal,priority,contactId,dealId,ticketId,conversationIdyupdatedSince;sort(dueAt,-updatedAt,-priority,createdAt);limitde 1 a 100 (50) ycursoropaco y firmado, ligado a la empresa, la fuente, los filtros y el orden (sort), válido 24 h (400 CURSOR_INVALID); lo acepta cualquier clave de la misma fuente, también la nueva tras una rotación. Responde{items, nextCursor, hasMore, indexedThrough}: los filtros van sobre un índice que va segundos por detrás y cada tarea se hidrata en vivo. - Detalle
GET /api/v1/tasks/{taskId}con la cabeceraETag. Una tarea de otra empresa, inexistente o que ya no es tarea responde igual:404 TASK_NOT_FOUND. - PATCH con
If-Matchobligatorio y cuerpo estricto (title,description,status,sourceStatus,priority,dueAt,assigneeId,teamId,category,activityKind,contactId,dealId,ticketId):422 FIELD_NOT_ALLOWEDsi el campo no existe,422 TASK_FIELD_NOT_SUPPORTED(consupportedFields) si el tipo no lo admite,422 TASK_PATCH_SPLIT_REQUIREDsi exigiría dos llamadas internas y422 TASK_STATUS_REQUIRES_ACTION(conactions) para los estados que solo se alcanzan con una acción. - Alta
POST /api/v1/tasks: solocrm.activity(un seguimiento ligado a contacto, oportunidad o ticket), conIdempotency-Keyobligatoria yexternalLinkopcional. Responde201conLocationyETag. - Notas (
support.ticketysales.conversation): leerlas exige<área>:content; añadirlas,<área>:writey un delegado (text≤ 5.000,mentionUserIds?). Historial sin cuerpos encrm.activity,crm.deal_attention,support.ticketycrm.playbook_session. - Enlace externo
PUT …/external-linkcon{externalId, url}(un enlace por fuente y tarea;urlHTTPS) y lookupPOST /api/v1/tasks/lookupcon{externalId}en el cuerpo: la tarea que tu fuente enlazó. - Recursos: cada uno con listado por cursor, ficha con
ETag,If-Matchen sus PATCH,Idempotency-Keyen sus altas y las mismas acciones que sus tareas enPOST /api/v1/<recurso>/{id}/actions/{action}(la referencia de acciones da la ruta de cada una). SinDELETEde datos: solo se retiran vínculos y webhooks propios.
6. Acciones y dryRun
POST /api/v1/tasks/support.ticket:9d2f…/actions/resolve
Authorization: Bearer aio_<keyId>.<secreto>
Idempotency-Key: jira-SUP-431-transition-51
If-Match: W/"h:3fa9c2d17b0e4a55" (opcional)
X-AIO-Act-As: 3c1f… (si la acción lo exige)
Content-Type: application/json
{ "input": {}, "dryRun": false }
La acción llama a la misma función que la ruta de la UI, con sus validaciones, bloqueos y permisos. Tras las comprobaciones de cada petición (§1), el orden es:
- El tipo de la
taskIdy la acción existen (404 TASK_NOT_FOUND/TASK_ACTION_NOT_FOUND; en la ruta del recurso,RESOURCE_NOT_FOUND/ACTION_NOT_FOUND). - Función y scope (
403 FEATURE_DISABLED/API_SCOPE_REQUIRED). - Formato de
If-Match(422 IF_MATCH_INVALID) y del cuerpo (415sinContent-Type: application/json,422). - Actor (
403). - Sin
dryRun:Idempotency-Key(428 IDEMPOTENCY_KEY_REQUIRED;422si no es válida) y su recibo. Un replay (Idempotent-Replayed: true) o un409 IDEMPOTENCY_*/ACTION_OUTCOME_UNKNOWNresponden antes de mirar la tarea: un reintento con la misma clave recibe la misma respuesta aunque la tarea ya se haya cerrado o ya no exista. - La tarea existe y es de tu empresa (
404 TASK_NOT_FOUND; en el recurso,RESOURCE_NOT_FOUND). If-Matchsi viene (412 REVISION_CONFLICT).- Disponibilidad en el estado actual (
409 TASK_ACTION_NOT_AVAILABLEconreason, o409 SEND_SWITCH_OFF; los motivos de persona, comoMAILBOX_OWNER_REQUIRED, responden403). input(422).- Cuota (
429, también condryRun). - Ejecución.
Por eso una tarea inexistente con una clave sin el scope responde
403, no404.- El tipo de la
inputsigue elinputSchemade la acción en el catálogo. Un error de la función interna conserva su estado y su código (MERGED_RECORD,ACTIVITY_CHANGE_VETOED,OUTBOUND_UNCERTAIN…); uno sin código llega comoACTION_REJECTED.- Respuesta
200conoutcome: "succeeded"si el efecto está aplicado o202conoutcome: "accepted"si la función solo encola (reintentos de envío, refresco de conocimiento, envío de CSAT);resultes mínimo (IDs, recuentos, tokens) ytasktrae el estado y el ETag nuevos. dryRun: trueno escribe nada, no exigeIdempotency-Keyy no consume idempotencia (sí cuenta en la cuota). Si la acción tiene un paso previo nativo, lo ejecuta y devuelve su token enconfirm; la ejecución lo exige:
| Acción | dryRun devuelve | La ejecución exige |
|---|---|---|
marketing.campaign · schedule | Vista previa: recuentos, bloqueos (placeholder_links: enlaces a example.com/.org/.net, listados en placeholderLinks; empty_text_blocks: títulos o botones sin texto, listados en emptyTextBlocks) y audienceFingerprint | audienceFingerprint (409 si cambió la audiencia; 422 CAMPAIGN_PLACEHOLDER_LINKS si quedan enlaces de ejemplo y 422 CAMPAIGN_EMPTY_TEXT_BLOCKS si hay títulos o botones sin texto) |
crm.duplicate_review · merge (o preview_merge) | Diferencias, efectos, bloqueos, planHash y expiresAt | planHash, expiresAt y reason |
crm.merge_review · undo | El plan de deshacer | El mismo plan |
support.ticket · apply_macro y /conversations/bulk | Cambios y previewToken | previewToken |
crm.playbook_session · complete | Efectos y expectedValues | expectedValues y target |
POST /api/v1/sequences/{id}/enrollments | Elegibles y motivos de exclusión | La misma Idempotency-Key |
marketing.journey_version · publish_version | Validación y diferencias | draftRevision |
En el resto, dryRun solo valida todas las precondiciones y responde {dryRun: true, valid: true, effects: […]}: nunca se ejecuta para deshacer después.
- Envíos inciertos: las acciones que podrían duplicar un envío (
review_*conretry,voice.job.retry,review_notification) exigenconfirmPossibleDuplicate: true, como la UI. Si el interruptor global de envío está apagado:409 SEND_SWITCH_OFF.
7. Idempotencia
If-Matches obligatorio en todo PATCH (428 PRECONDITION_REQUIREDsin él;412 REVISION_CONFLICTconcurrentEtagy la cabeceraETagsi no es el actual) y opcional en las acciones (si viene, se comprueba igual). Ante un412: lee la tarea, fusiona y reintenta con el ETag nuevo.Idempotency-Key(1-200 caracteresA-Z a-z 0-9 . _ : ~ -, empezando por letra o dígito) es obligatoria en las altas y en las acciones salvo condryRun(428 IDEMPOTENCY_KEY_REQUIRED). Su ámbito es la fuente y dura 7 días. Usa el ID del evento de tu herramienta (transición, comentario, entrada del changelog).
| Reintento con la misma clave | Respuesta |
|---|---|
| Mismo cuerpo, ejecución terminada (correcta o con error 4xx) | La misma respuesta, con replayed: true y la cabecera Idempotent-Replayed: true |
| Mismo cuerpo, ejecución en curso | 409 IDEMPOTENCY_IN_PROGRESS con Retry-After |
| Mismo cuerpo, ejecución interrumpida sin resultado | 409 ACTION_OUTCOME_UNKNOWN: lee la tarea y decide; RouterClip nunca la repite sola |
| Otro cuerpo | 409 IDEMPOTENCY_CONFLICT |
Repetir una nota (POST …/notes) con la misma clave devuelve la misma nota: se vuelve a leer con su texto y, si ya no se puede leer, llegan su ID, autor, menciones y fecha (las ejecuciones nunca guardan cuerpos).
Todas las escrituras y acciones quedan auditadas 90 días (fuente, clave, delegado, tarea, acción, resultado y X-Request-ID, sin cuerpos); los administradores las ven en Integraciones → API y eventos → API de tareas → Actividad de la API. La misma actividad incluye las altas, vinculaciones y cambios de contactos, las invitaciones de doble opt-in, las inscripciones en recorridos, los inicios de flujos por la API («Inicio de flujo por la API» / «Flujo no iniciado», operación enroll sobre automation_flow) y los cambios en los webhooks de tareas hechos con claves de la fuente, y sus rechazos (403, 404, 409, 412).
8. Feed de cambios
cursor0 = GET /api/v1/task-changes/cursor → {"cursor": "c1.…"} (antes de la carga inicial)
for page in GET /api/v1/tasks?kind=support.ticket,crm.activity:
upsert_in_tool(page.items) (guarda etag y version de cada tarea)
cursor = cursor0
loop (al recibir un webhook o cada 2 minutos):
changes = GET /api/v1/task-changes?cursor=<cursor>&limit=500
for c in changes.items: {taskId, kind, change: upsert|deleted, status, version, changedAt}
if c.version <= known_version(c.taskId): continue
if c.change == "deleted": archive_in_tool(c.taskId)
else: upsert_in_tool(GET /api/v1/tasks/{c.taskId})
cursor = changes.nextCursor (persístelo después de aplicar)
si 410 CURSOR_EXPIRED: vuelve a empezar desde cursor0
- Entrega al menos una vez y sin huecos para un cursor válido; una tarea puede reaparecer si vuelve a cambiar. Las tareas que la clave no puede ver no salen, pero el cursor avanza.
- Las tareas cerradas o desaparecidas se conservan como lápidas 30 días; un cursor más antiguo responde
410 CURSOR_EXPIREDy obliga a resincronizar. GET /api/v1/task-summarydevuelve recuentos por tipo, estado y responsable con los filtros del listado, para cuadros de mando.
9. Webhooks
- Alta con
webhooks:manage:POST /api/v1/webhookscon{name, url, kinds?, events?, skipOwnChanges?, enabled?}.urles HTTPS en el puerto 443 dentro de un origen autorizado por la plataforma;kindsvacío significa todos los que la clave puede leer;eventsentretask.created,task.updated,task.completedytask.deleted. Límites: 5 por fuente y 20 por empresa. La respuesta trae el secretowhsec_…una sola vez (tambiénPOST …/rotate-secret); los listados y fichas nunca lo muestran. - Payload mínimo, sin títulos, nombres ni cuerpos:
{id, type, schemaVersion, occurredAt, data: {taskId, kind, status, previousStatus, version, changedFields, causedBy, cursor, url}}. El webhook solo despierta la lectura: pide el detalle con tu clave o lee el feed desdedata.cursor. - Cabeceras:
X-CRM-Signature: sha256=HMAC(secreto, "<timestamp>.<nonce>.<cuerpo>"),X-CRM-Timestamp,X-CRM-Attempt(el nonce),X-CRM-Delivery-Id(igual en cada intento eIdempotency-Key) yX-CRM-Event-Id. - Reintentos: hasta 8 intentos con espera creciente; un 4xx distinto de 429 es fallo definitivo y un
410desactiva el endpoint.POST …/testenvía unping;GET …/deliveriesyPOST …/deliveries/{id}/retrypermiten revisar y reintentar. - Reparto: cada endpoint recibe una petición a la vez y las empresas se turnan, así que un receptor lento no retrasa a los demás. Tras 5 intentos fallidos seguidos el endpoint espera 5 minutos (el doble cada vez, hasta una hora) sin gastar intentos, tampoco las entregas que ya estaban en el mismo lote, y después se prueba con una sola entrega; una respuesta 2xx, una URL nueva, reactivarlo, un reintento manual o un ping de prueba (
POST …/test, que además adelanta un ping pendiente que esperaba su reintento) lo liberan. El webhook informa de ello enfailureStreak(intentos fallidos seguidos) ydeferredUntil(hasta cuándo espera;nullsi no espera), y la pantalla de administración lo explica. Si el resolutor DNS de la plataforma está ocupado no se envía nada: la entrega recupera su intento, se reintenta a los 30 segundos y no cuenta como fallo del endpoint.
Verificar la firma (Python):
import hashlib
import hmac
import time
def verify(secret: str, headers: dict, raw_body: bytes) -> bool:
timestamp, nonce = headers["X-CRM-Timestamp"], headers["X-CRM-Attempt"]
if abs(time.time() - int(timestamp)) > 300: # ventana anti-replay de 5 minutos
return False
signed = timestamp.encode() + b"." + nonce.encode() + b"." + raw_body
expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, headers["X-CRM-Signature"])
Verifica sobre el cuerpo crudo, deduplica por X-CRM-Delivery-Id, descarta lo que llegue con version menor o igual que la que ya conoces (no hay orden garantizado) y responde 2xx en menos de 10 s.
10. Errores
Formato de la API v1: {"detail": {"code", "message", "requestId", "field?"}}. El código es estable; el mensaje puede cambiar.
| HTTP | Código | Qué hacer |
|---|---|---|
| 400 | CURSOR_INVALID | Cursor alterado, caducado o de otra consulta: empieza sin él |
| 401 / 402 | API_KEY_*, API_SOURCE_DISABLED, COMPANY_INACTIVE / SUBSCRIPTION_PAYMENT_REQUIRED | No reintentar |
| 403 | API_SCOPE_REQUIRED (requiredScopes), FEATURE_DISABLED (feature), DELEGATED_USER_*, ACTOR_ROLE_INSUFFICIENT, MAILBOX_OWNER_REQUIRED, MENTION_RECIPIENT_REQUIRED | Revisar la clave, la fuente o el delegado |
| 404 | TASK_NOT_FOUND, RESOURCE_NOT_FOUND, TASK_ACTION_NOT_FOUND (ruta de la tarea) / ACTION_NOT_FOUND (ruta del recurso) | No existe, es de otra empresa o ya no es tarea |
| 409 | TASK_ACTION_NOT_AVAILABLE (reason), SEND_SWITCH_OFF, IDEMPOTENCY_CONFLICT, IDEMPOTENCY_IN_PROGRESS, ACTION_OUTCOME_UNKNOWN y los códigos de cada función (MERGED_RECORD, MERGE_PREVIEW_STALE, OUTBOUND_UNCERTAIN…) | Leer la tarea antes de decidir |
| 410 | CURSOR_EXPIRED | Resincronizar |
| 412 | REVISION_CONFLICT (currentEtag) | Leer, fusionar y reintentar |
| 413 / 415 | Cuerpo de más de 32 KiB / falta Content-Type: application/json | Corregir |
| 422 | FIELD_NOT_ALLOWED, VALIDATION_ERROR (field), TASK_FIELD_NOT_SUPPORTED, TASK_STATUS_REQUIRES_ACTION, TASK_PATCH_SPLIT_REQUIRED, IF_MATCH_INVALID… | Corregir; no reintentar igual |
| 428 | PRECONDITION_REQUIRED / IDEMPOTENCY_KEY_REQUIRED | Enviar If-Match o Idempotency-Key |
| 429 | RATE_LIMITED (Retry-After, quota) | Esperar lo indicado y reintentar con la misma clave |
| 503 | Servicio no disponible (por ejemplo, CURSOR_KEY_UNAVAILABLE), con Retry-After si lo hay | Esperar y reintentar |
11. Cuotas
| Límite | Valor |
|---|---|
| Peticiones | 120 por minuto y clave, 600 por minuto y empresa (compartidas con el resto de /api/v1) |
| Escrituras y acciones | 60 por minuto y clave; un dryRun también cuenta |
| Cuotas propias | Se mantienen las de cada función: vista previa de fusión, envíos de marketing y CSAT, cupo diario de secuencias… |
| Páginas | 100 tareas por página del listado y 500 cambios por página del feed |
| Cuerpo | 32 KiB; reply y public_reply hasta 10.000 caracteres y notas hasta 5.000 |
| Delegados y webhooks | 20 delegados por fuente; 5 webhooks por fuente y 20 por empresa |
| Retención | Lápidas y eventos task.*: 30 días; ejecuciones: 90 días; recibos de idempotencia: 7 días |
12. Recetas
Patrón común: una fuente y una clave por herramienta; cursor del feed fijado antes de la carga inicial; un webhook de tareas con skipOwnChanges que despierta la sincronización; externalLink en cada tarea creada en la herramienta; y la acción de cierre (completion) del tipo cuando la herramienta marca algo como hecho. Guarda version y etag de cada tarea.
12.1 Jira
- Proyectos: uno por área (Soporte con
kind=support.ticket,support.customer_message; Comercial concrm.activity,crm.deal_attention,sales.enrollment; Marketing; Operación). Crea las incidencias con la carga inicial y guarda elidde RouterClip en una propiedad «RouterClip Task ID»; enlázalas conPUT …/external-link({"externalId": "SUP-431", "url": "https://jira.example.com/browse/SUP-431"}). - Estados:
open→ To Do,in_progress→ In Progress,waiting→ Waiting,needs_review→ Needs review,done→ Done,cancelled→ Won't do. - De Jira a RouterClip: una automatización de Jira (webhook saliente a tu servicio) en la transición a Done llama a la acción
completiondel tipo conIdempotency-Key: jira-<issue>-changelog-<id>; el cambio de assignee o de fecha de vencimiento es un PATCH conIf-Match; un comentario público de un agente esreplyconX-AIO-Act-Asdel agente. - De RouterClip a Jira: el webhook despierta tu servicio, que lee el feed y actualiza la incidencia. Para buscar la tarea de una incidencia:
POST /api/v1/tasks/lookupcon{"externalId": "SUP-431"}.
12.2 Asana
- Proyecto por área con secciones por
status; elidde RouterClip en un campo personalizado yexternal-linka la tarea de Asana. - Completar en Asana (
completed: true) → accióncompletion(completeencrm.activity,resolveensupport.ticket). Las tareas sincompletionse crean con una regla o botón que llama a la acción condryRunprimero. - Los webhooks de Asana llegan a tu servicio; usa su
resource.gid+created_atcomoIdempotency-Key.
12.3 ClickUp
- Lista por área; los estados de ClickUp se mapean 1:1 con los seis normalizados. El
iden un campo personalizado. - Un cambio de estado en ClickUp a «closed» → acción
completion; a «in review» no hace nada en RouterClip (es estado de la herramienta). El cambio de assignee → PATCHassigneeIden los tipos que lo editan (editable). - Las automatizaciones de ClickUp pueden llamar a tu servicio, que añade
Idempotency-Key: clickup-<task>-<history_item_id>.
12.4 Linear
- Equipo o proyecto por área; los estados del flujo se mapean con
status(Backlog/Todo ←open, In Progress ←in_progress, Done ←done, Canceled ←cancelled). - El webhook de Linear (
IssueconupdatedFrom) dispara en tu servicio el PATCH o la acción; usa elwebhookId+updatedAtcomo clave de idempotencia. - Prioridad:
urgent/high/normal/low↔ Urgent/High/Medium/Low.
12.5 Monday
- Tablero por área con una columna de estado (los seis normalizados), una de persona (mapeada con
GET /api/v1/members) y una de fecha (dueAt). - Una automatización «cuando el estado cambie a Hecho» llama a tu servicio, que ejecuta la acción
completion; los botones de Monday pueden lanzar acciones concretas (assign,snooze,schedule) condryRunprimero cuando tienen paso previo.
12.6 Trello
- Tablero por área y una lista por
status(To do, En curso, Esperando, Revisar, Hecho). La tarjeta guarda elidde RouterClip en su descripción o en un campo personalizado yexternal-linkapunta a la tarjeta. - Mover una tarjeta a «Hecho» → acción
completion; a otra lista no cambia nada en RouterClip si el tipo no admite ese estado por PATCH (422 TASK_STATUS_REQUIRES_ACTIONindica qué acciones lo consiguen). - Los webhooks de Trello (
action.id) dan laIdempotency-Key.
12.7 Notion
- Base de datos por área con propiedades
RouterClip ID,Estado(select con los seis valores),Responsable,VenceyEnlace(appUrl). Si tu integración de Notion no recibe eventos de cambios, sondea su API cada pocos minutos; del lado de RouterClip, el webhook de tareas oGET /api/v1/task-changesbastan. - Cambiar
Estadoa «Hecho» en Notion → accióncompletionconIdempotency-Key: notion-<pageId>-<last_edited_time>.
13. Cómo evitar bucles
- Deja
skipOwnChangesactivado (por defecto): un endpoint no recibe los cambios causados solo por su propia fuente (causedBy: {kind: "api", sourceId}). - Envía a RouterClip solo los cambios que hizo una persona en la herramienta, nunca los que escribió tu propia sincronización (marca en la herramienta qué cambios hizo el integrador).
- Usa como
Idempotency-Keyel ID del evento de la herramienta: si el mismo evento llega dos veces, RouterClip devuelve la misma respuesta (replayed: true) sin ejecutar nada. - Compara
versionantes de aplicar y descarta lo antiguo; el webhook solo despierta, el estado se lee del feed o del detalle. - Ante un
412o un409, lee y fusiona: lo que RouterClip gestiona (SLA, envíos, fusiones, recorridos) manda.
14. Qué no se expone
Ningún DELETE de datos (solo se retiran vínculos y webhooks propios); escritura de consentimientos y preferencias; importaciones y exportaciones; borrado o exportación de la empresa; configuración (pipelines, campos, SLA, equipos, reglas, macros, etiquetas, política CSAT, ajustes de voz, calendarios, bases jurídicas, widget); autoría de recorridos, secuencias, guiones, formularios y colocaciones, y envíos de prueba; credenciales y canales (cuentas, conexiones, OAuth, Meta, WAHA, buzones, Stripe); enlaces portadores (portal de tickets, encuestas CSAT, /meet, baja); audio de llamadas y subida de adjuntos; llamadas salientes y funciones de IA; seguridad, invitaciones, contraseñas, facturación, funciones, plataforma y administración de claves; correcciones de resultados comerciales. Ampliar esta lista exige una decisión nueva; la prueba de cobertura comprueba que ninguna de esas rutas existe bajo /api/v1.
English
1. Activation
- The RouterClip team enables the “Task and function API” feature (
api.tasks) for your company; without it every route of this guide answers403 FEATURE_DISABLED. Some areas also need their own feature (sequencescrm.sequences, playbookscrm.playbooks, duplicatescrm.merge, conversionsmarketing.tracking…): without it their kinds leave the feed and their routes answer403 FEATURE_DISABLED. - For webhooks, also ask the platform to authorize your tool's HTTPS origin. Task webhook sending has a global switch; while it is off, deliveries wait in the queue for up to 30 days: they go out if it is switched on in time, otherwise they fail as expired and, once sending is on, can be retried by hand (
POST …/deliveries/{id}/retry). The 30 days count from when the delivery entered the queue, from its last attempt or from its last manual retry: a retry starts a new series of attempts with its own window, even if the first one fails again. - An administrator creates one source per tool in Settings → Integrations → API and events, picks a scope package (§2) and, in “Act as”, the users the tool may represent (§3).
- They issue the source's key (
aio_<keyId>.<secret>, shown once; two active keys for zero-downtime rotation) and, optionally, the task webhook (§9). Check the key withGET /api/v1/keyand what it can do withGET /api/v1/key/capabilities.
Every request sends Authorization: Bearer aio_<keyId>.<secret> and Content-Type: application/json. Server to server only: no CORS, never put the key in a browser, a URL or a log. Checks, in order: key and source, active company (401), service access (402), feature (403), quotas (429) and scopes (403).
2. Scopes and packages
Scopes are <area>:<level>; levels do not inherit. read (viewer), write and execute (agent), admin (administrator: needs acting as an administrator) and content (message bodies, internal notes, customers' texts and transcripts). Areas and scopes: contacts:read, contacts:write, subscriptions:invite (invitations also need marketing.api); companies:read, companies:write; deals:read, deals:write, deals:execute; activities:read, activities:write, activities:execute; sequences:read, sequences:execute (crm.sequences); playbooks:read, playbooks:write, playbooks:execute (crm.playbooks); duplicates:read, duplicates:write, duplicates:admin (crm.merge); support:read, support:write, support:execute, support:admin, support:content; csat:read, csat:execute, csat:admin; voice:read, voice:execute, voice:admin, voice:content; calendar:read, calendar:execute; campaigns:read, campaigns:write, campaigns:admin; journeys:read, journeys:admin, automations:enroll; segments:read; forms:read, forms:admin; sites:read, sites:admin; conversions:read, conversions:admin (marketing.tracking); knowledge:read, knowledge:admin; channels:read, channels:admin; reports:read; team:read, team:emails; webhooks:manage; automation:read, automation:enroll (automation.flows; flows without their configuration, their runs and starting the flows with the “Through the API” trigger; automation:enroll is in no package); and act_as.
Packages: Task reading (every *:read of the active areas and team:read), Task management (plus writing and running activities, deals, support and playbooks, running CSAT, voice and calendar actions and act_as), Full operation (plus the *:admin of the active areas and webhooks:manage) and Custom. *:admin, *:content, team:emails and act_as are sensitive and need an express confirmation. The feed shows only the kinds of the areas the key can read; PATCH needs <area>:write (and the level of the equivalent action to change the status); each action needs the scope the catalog declares. No scope equals a full administrator.
3. Actor and delegation
A key is not a user. Each action declares its actor: service (the source itself, no user; never above execute and never talks to customers), delegated (a user of the source's list: replies, notes with mentions, snoozes, macros and every admin-level action), owner (the delegated user owns the sales mailbox) and recipient (the delegated user is the mention's recipient). The request picks the user with X-AIO-Act-As: <userId> (the key needs act_as); without it the source's default user acts, if any. Errors: 403 DELEGATED_USER_REQUIRED, DELEGATED_USER_NOT_ALLOWED, DELEGATED_USER_INACTIVE, ACTOR_ROLE_INSUFFICIENT, MAILBOX_OWNER_REQUIRED and MENTION_RECIPIENT_REQUIRED. The effective permission is the key's scopes ∩ the delegated user's role ∩ the owner or recipient conditions; delegation never creates a session. Up to 20 active users per source plus an optional default user, each change recorded with author and date. Map assignees with GET /api/v1/members (team:read; email only with team:emails).
4. Task model
A task is a projection of its source entity, never a copy. Its ID is <kind>:<key> (≤200 of A-Z a-z 0-9 . _ : -, unencoded in the path). It carries a normalized status (open, in_progress, waiting, needs_review, done, cancelled), the native sourceStatus, signals of a closed catalog, priority, assignee, team, dueAt with dueKind, links (a linked contact shows only the source's read fields, and showing any of them is a read in the contact read log, as in the feed, tickets, conversations, calls and bookings), appUrl, version, etag (W/"<n>" or W/"h:<16 hex>", computed live), editable (the PATCH fields of its kind and state), actions (with available and unavailableReason for this key and delegated user) and the externalLink of your source. Ignore unknown fields, signals and reasons. The 28 kinds and their completion action are those of the Spanish table above; kinds without completion need a decision: show their actions in the tool.
5. Endpoints
Tasks (GET/POST /api/v1/tasks, GET/PATCH /api/v1/tasks/{taskId}, POST …/actions/{action}, notes, history, external link, POST /api/v1/tasks/lookup), catalog and sync (/api/v1/task-kinds, /api/v1/task-changes/cursor, /api/v1/task-changes, /api/v1/task-summary), resources per functionality (each with cursor lists, ETag details, If-Match on PATCH, Idempotency-Key on creations and the same actions as its tasks at POST /api/v1/<resource>/{id}/actions/{action}), task webhooks (/api/v1/webhooks…), key (/api/v1/key, /api/v1/key/capabilities, /api/v1/members), automation flows (GET /api/v1/automation/flows[/{flowId}[/runs]], GET /api/v1/automation/runs/{runId} without any configuration, and POST /api/v1/automation/flows/{flowId}/enroll with {"subject": {"type", "id"}} and a required Idempotency-Key: 201 started with runId or 200 skipped with the reason, only for published flows with the API trigger) and the event feed (GET /api/v1/events, GET /api/v1/event-types with events:read: see /developers/api-v1.html). The list takes kind, area, status, assigneeId, assignee=me, unassigned, teamId, dueBefore, dueAfter, overdue, signal, priority, contactId, dealId, ticketId, conversationId, updatedSince, sort, limit (≤100) and a signed cursor (24 h), bound to the company, the source, the filters and the sort: any key of the same source accepts it, also the new one after a rotation. PATCH is strict (FIELD_NOT_ALLOWED, TASK_FIELD_NOT_SUPPORTED, TASK_PATCH_SPLIT_REQUIRED, TASK_STATUS_REQUIRES_ACTION). POST /api/v1/tasks creates only crm.activity. Notes exist on support.ticket and sales.conversation; history on crm.activity, crm.deal_attention, support.ticket and crm.playbook_session. There is no data DELETE: only links and your own webhooks are removed.
6. Actions and dryRun
Each action runs the same function as the UI route, with its validations, locks and permissions. After the per-request checks (§1), the order is: the kind of the taskId and the action exist (404 TASK_NOT_FOUND/TASK_ACTION_NOT_FOUND; on the resource route RESOURCE_NOT_FOUND/ACTION_NOT_FOUND), feature and scope (403), the format of If-Match and of the body (422/415), the actor (403), without dryRun the Idempotency-Key (428) and its receipt (a replay or a 409 IDEMPOTENCY_*/ACTION_OUTCOME_UNKNOWN answers before the task is looked at, so a retry with the same key gets the same answer even if the task was closed or is gone), the task exists in your company (404), If-Match if sent (412), availability (409 TASK_ACTION_NOT_AVAILABLE/SEND_SWITCH_OFF), input (422), the quota (429, also for dryRun) and the execution; so a missing task with a key that lacks the scope answers 403, not 404. input follows the action's inputSchema. 200 with outcome: "succeeded" or 202 with outcome: "accepted" when the function only queues; result is minimal and task brings the new status and ETag. dryRun: true writes nothing, needs no Idempotency-Key and consumes no idempotency (it counts in the quota): actions with a native previous step return its token in confirm (audienceFingerprint to schedule a campaign, planHash and expiresAt to merge or undo, previewToken for macros, expectedValues and target to complete a playbook, draftRevision to publish a journey version) and the execution requires it; the rest only validate and return the declared effects. Actions that could duplicate a send require confirmPossibleDuplicate: true; a global send switch off answers 409 SEND_SWITCH_OFF.
7. Idempotency
If-Match is required on every PATCH (428 PRECONDITION_REQUIRED; stale: 412 REVISION_CONFLICT with currentEtag) and optional on actions. Idempotency-Key (1-200 of A-Z a-z 0-9 . _ : ~ -, starting with a letter or digit) is required on creations and on actions unless dryRun (428 IDEMPOTENCY_KEY_REQUIRED), per source, for 7 days. Same key and body: the same answer with replayed: true and Idempotent-Replayed: true; still running: 409 IDEMPOTENCY_IN_PROGRESS with Retry-After; interrupted with an unknown outcome: 409 ACTION_OUTCOME_UNKNOWN (read the task and decide: RouterClip never repeats it); another body: 409 IDEMPOTENCY_CONFLICT. A note retried with the same key answers the same note (read again with its text or, when it can no longer be read, its ID, author, mentions and date). Writes and actions are audited for 90 days without bodies, together with the contact writes, double opt-in invitations, journey enrollments and task webhook changes made with the source's keys and their rejections (403, 404, 409, 412).
8. Change feed
Read GET /api/v1/task-changes/cursor before the initial load, load with GET /api/v1/tasks, then follow GET /api/v1/task-changes?cursor=…&limit=500 ({items: [{taskId, kind, change: upsert|deleted, status, version, changedAt}], nextCursor, hasMore}), skip versions you already know, fetch the detail of each upsert, archive deletions and persist nextCursor after applying. At-least-once delivery without gaps for a valid cursor; tasks the key cannot see are left out but the cursor advances. Tombstones last 30 days: an older cursor answers 410 CURSOR_EXPIRED and you resynchronize. GET /api/v1/task-summary counts by kind, status and assignee.
9. Webhooks
Create with webhooks:manage: POST /api/v1/webhooks with {name, url, kinds?, events?, skipOwnChanges?, enabled?} (HTTPS on port 443 within an origin the platform authorized; 5 per source and 20 per company). The whsec_… secret comes once, at creation and on rotate-secret. The payload is minimal ({id, type, schemaVersion, occurredAt, data: {taskId, kind, status, previousStatus, version, changedFields, causedBy, cursor, url}}) and only wakes your reader. Headers: X-CRM-Signature: sha256=HMAC(secret, "<timestamp>.<nonce>.<body>"), X-CRM-Timestamp, X-CRM-Attempt (the nonce), X-CRM-Delivery-Id (also Idempotency-Key) and X-CRM-Event-Id. Up to 8 attempts with backoff; a 4xx other than 429 is final and 410 disables the endpoint. Verify the signature on the raw body with the Python function of the Spanish section (5-minute replay window, hmac.compare_digest), deduplicate by X-CRM-Delivery-Id, drop version ≤ the known one and answer 2xx within 10 s.
10. Errors
{"detail": {"code", "message", "requestId", "field?"}}. 400 CURSOR_INVALID; 401/402 key, source, company or subscription (do not retry); 403 API_SCOPE_REQUIRED, FEATURE_DISABLED, DELEGATED_USER_*, ACTOR_ROLE_INSUFFICIENT, MAILBOX_OWNER_REQUIRED, MENTION_RECIPIENT_REQUIRED; 404 TASK_NOT_FOUND/RESOURCE_NOT_FOUND/TASK_ACTION_NOT_FOUND/ACTION_NOT_FOUND; 409 TASK_ACTION_NOT_AVAILABLE, SEND_SWITCH_OFF, IDEMPOTENCY_*, ACTION_OUTCOME_UNKNOWN and the codes of each function; 410 CURSOR_EXPIRED; 412 REVISION_CONFLICT; 413 above 32 KiB; 415 without JSON content type; 422 invalid or unsupported body; 428 PRECONDITION_REQUIRED/IDEMPOTENCY_KEY_REQUIRED; 429 RATE_LIMITED (Retry-After); 503 when a service is unavailable (for example CURSOR_KEY_UNAVAILABLE): wait and retry.
11. Quotas
120 requests per minute per key and 600 per company (shared with the rest of /api/v1); 60 writes and actions per minute per key (dryRun included); each function keeps its own quotas; pages of 100 tasks and 500 changes; 32 KiB bodies (replies up to 10,000 characters, notes up to 5,000); 20 delegated users per source; 5 webhooks per source and 20 per company; tombstones and task.* events 30 days, runs 90 days, idempotency receipts 7 days.
12. Recipes
Common pattern: one source and key per tool; the feed cursor read before the initial load; a task webhook with skipOwnChanges that wakes the sync; an externalLink on every task created in the tool; and the kind's completion action when the tool marks something done. Keep version and etag per task.
12.1 Jira
One project per area filtered by kind; the RouterClip ID in an issue property and PUT …/external-link. open/in_progress/waiting/needs_review/done/cancelled ↔ To Do/In Progress/Waiting/Needs review/Done/Won't do. A Jira automation on the transition to Done calls the kind's completion action with Idempotency-Key: jira-<issue>-changelog-<id>; assignee or due date changes are a PATCH with If-Match; an agent's public comment is reply with X-AIO-Act-As. Find the task of an issue with POST /api/v1/tasks/lookup.
12.2 Asana
One project per area with sections by status; the RouterClip ID in a custom field. Completing in Asana calls the completion action; tasks without one get a rule or button that calls the action with dryRun first. Use the webhook's resource.gid + created_at as Idempotency-Key.
12.3 ClickUp
One list per area with the six normalized statuses. Closing calls the completion action; assignee changes are a PATCH of assigneeId where the kind lists it in editable. Use clickup-<task>-<history_item_id> as Idempotency-Key.
12.4 Linear
One team or project per area; workflow states map to status and priorities urgent/high/normal/low to Urgent/High/Medium/Low. The Linear Issue webhook (with updatedFrom) drives the PATCH or the action; webhookId + updatedAt is the idempotency key.
12.5 Monday
One board per area with status, person (mapped with GET /api/v1/members) and date columns. An automation “when status changes to Done” calls the completion action; buttons can run specific actions (assign, snooze, schedule) with dryRun first when they have a previous step.
12.6 Trello
One board per area and one list per status. Moving a card to Done calls the completion action; other moves change nothing when the kind does not admit that status by PATCH (422 TASK_STATUS_REQUIRES_ACTION lists the actions that do). Trello's action.id is the Idempotency-Key.
12.7 Notion
One database per area with RouterClip ID, Status (the six values), Assignee, Due and Link (appUrl) properties. If your Notion integration receives no change events, poll its API every few minutes; on the RouterClip side, the task webhook or GET /api/v1/task-changes is enough. Setting Status to Done calls the completion action with Idempotency-Key: notion-<pageId>-<last_edited_time>.
13. Avoiding loops
Keep skipOwnChanges on (the default: an endpoint never receives the changes caused only by its own source); send RouterClip only the changes a person made in the tool, never those your sync wrote; use the tool's event ID as Idempotency-Key; compare version before applying; and on 412 or 409 read and merge: what RouterClip manages (SLA, sends, merges, journeys) wins.
14. Not exposed
No data DELETE; no consents, preferences, imports, exports or company deletion; no configuration (pipelines, fields, SLA, teams, rules, macros, labels, CSAT policy, voice settings, calendars, legal bases, widget); no authoring of journeys, sequences, playbooks, forms or placements, nor test sends; no credentials or channel setup (accounts, connections, OAuth, Meta, WAHA, mailboxes, Stripe); no bearer links (ticket portal, CSAT surveys, /meet, unsubscribe); no call audio or attachment uploads; no outgoing calls or AI features; no security, invitations, passwords, billing, features, platform or key administration; no corrections of sales results. Extending this list needs a new decision; the coverage test checks that none of those routes exists under /api/v1.
Referencia de acciones · Action reference
Cada acción del registro con su scope, su actor y un ejemplo: la ruta de la tarea (/api/v1/tasks/<kind>:<clave>/actions/<acción>) o, si no tiene tipo, la de su recurso. Las de una tarea se ejecutan igual por su recurso (la columna «paths» del catálogo estático da todas las rutas). (admin): exige un delegado administrador; dryRun → …: el token que devuelve el paso previo y que la ejecución exige; 202: solo encola. Every action of the registry with its scope, actor and an example: the task route or, without a kind, the resource route; actions of a task also run through their resource (the paths of the static catalog list every route).
Oportunidades · Deals
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
crm.deal_attention | archive | deals:execute · service | POST /api/v1/tasks/crm.deal_attention:{id}/actions/archive {"input":{}} |
crm.deal_attention | lose | deals:execute · service | POST /api/v1/tasks/crm.deal_attention:{id}/actions/lose {"input":{"lostReason":"Price"}} |
crm.deal_attention | reopen | deals:execute · service | POST /api/v1/tasks/crm.deal_attention:{id}/actions/reopen {"input":{}} |
crm.deal_attention | restore | deals:execute · service | POST /api/v1/tasks/crm.deal_attention:{id}/actions/restore {"input":{}} |
crm.deal_attention | schedule_next_activity | deals:write + activities:write · service | POST /api/v1/tasks/crm.deal_attention:{id}/actions/schedule_next_activity {"input":{"title":"Llamar para renovar","dueAt":"2026-10-01T09:00:00Z"}} |
crm.deal_attention | update_deal | deals:write · service | POST /api/v1/tasks/crm.deal_attention:{id}/actions/update_deal {"input":{"amount":"12000.00","currency":"EUR","expectedClose":"2026-11-30"}} |
crm.deal_attention | win | deals:execute · service | POST /api/v1/tasks/crm.deal_attention:{id}/actions/win {"input":{}} |
Actividades y seguimientos · Activities and follow-ups
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
crm.activity | cancel | activities:execute · service | POST /api/v1/tasks/crm.activity:{id}/actions/cancel {"input":{}} |
crm.activity | complete | activities:execute · service | POST /api/v1/tasks/crm.activity:{id}/actions/complete {"input":{}} |
crm.activity | reassign | activities:execute · service | POST /api/v1/tasks/crm.activity:{id}/actions/reassign {"input":{"assigneeId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
crm.activity | reopen | activities:execute · service | POST /api/v1/tasks/crm.activity:{id}/actions/reopen {"input":{}} |
crm.activity | reschedule | activities:execute · service | POST /api/v1/tasks/crm.activity:{id}/actions/reschedule {"input":{"dueAt":"2026-10-01T09:00:00Z"}} |
crm_activity (recurso · resource) | start_playbook | activities:read + playbooks:execute · delegated | POST /api/v1/activities/{id}/actions/start_playbook {"input":{"playbookId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
Secuencias comerciales · Sales sequences
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
sales.conversation | mark_read | sequences:execute · service | POST /api/v1/tasks/sales.conversation:{id}/actions/mark_read {"input":{}} |
sales.conversation | reply | sequences:execute · owner | POST /api/v1/tasks/sales.conversation:{id}/actions/reply {"input":{"text":"Hola Lucía, ya hemos reenviado la factura de septiembre.","expectedLastMessageId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
sales.enrollment | cancel | sequences:execute · delegated | POST /api/v1/tasks/sales.enrollment:{id}/actions/cancel {"input":{"reason":"The customer already bought"}} |
sales.enrollment | pause | sequences:execute · delegated | POST /api/v1/tasks/sales.enrollment:{id}/actions/pause {"input":{"reason":"The customer is on holiday"}} |
sales.enrollment | reconcile_execution | sequences:execute · delegated | POST /api/v1/tasks/sales.enrollment:{id}/actions/reconcile_execution {"input":{}} |
sales.enrollment | resume | sequences:execute · owner | POST /api/v1/tasks/sales.enrollment:{id}/actions/resume {"input":{}} |
sales.enrollment | review_execution | sequences:execute · delegated | POST /api/v1/tasks/sales.enrollment:{id}/actions/review_execution {"input":{"decision":"confirm_accepted","evidence":"Seen in the sent folder of the mailbox at 09:02"}} |
sales.enrollment | skip_step | sequences:execute · owner | POST /api/v1/tasks/sales.enrollment:{id}/actions/skip_step {"input":{"reason":"Confirmed with the customer by phone"}} |
sales_sequence (recurso · resource) | pause | sequences:execute · delegated | POST /api/v1/sequences/{id}/actions/pause {"input":{}} |
sales_sequence (recurso · resource) | resume | sequences:execute · delegated | POST /api/v1/sequences/{id}/actions/resume {"input":{}} |
Guiones comerciales · Sales playbooks
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
crm.playbook_session | abandon | playbooks:execute · delegated | POST /api/v1/tasks/crm.playbook_session:{id}/actions/abandon {"input":{}} |
crm.playbook_session | complete | playbooks:execute · delegated · dryRun → expectedValues, target | POST /api/v1/tasks/crm.playbook_session:{id}/actions/complete {"input":{"expectedValues":[{"entity":"contact","fieldId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}],"target":{"contactId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}} |
crm.playbook_session | save | playbooks:write · delegated | POST /api/v1/tasks/crm.playbook_session:{id}/actions/save {"input":{}} |
Duplicados y fusiones · Duplicates and merges
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
crm.duplicate_review | dismiss | duplicates:write · delegated | POST /api/v1/tasks/crm.duplicate_review:contact:{idA}:{idB}/actions/dismiss {"input":{}} |
crm.duplicate_review | merge | duplicates:admin · delegated (admin) · dryRun → planHash, expiresAt | POST /api/v1/tasks/crm.duplicate_review:contact:{idA}:{idB}/actions/merge {"input":{"survivorId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","reason":"Same customer: same email and phone","planHash":"9ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d79ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d7","expiresAt":"2026-10-01T09:00:00Z"}} |
crm.duplicate_review | preview_merge | duplicates:admin · delegated (admin) · dryRun | POST /api/v1/tasks/crm.duplicate_review:contact:{idA}:{idB}/actions/preview_merge {"input":{"survivorId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
crm.duplicate_review | restore | duplicates:write · delegated | POST /api/v1/tasks/crm.duplicate_review:contact:{idA}:{idB}/actions/restore {"input":{}} |
crm.merge_review | review | duplicates:admin · delegated (admin) | POST /api/v1/tasks/crm.merge_review:{id}/actions/review {"input":{}} |
crm.merge_review | undo | duplicates:admin · delegated (admin) · dryRun → planHash, expiresAt | POST /api/v1/tasks/crm.merge_review:{id}/actions/undo {"input":{"planHash":"9ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d79ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d7","expiresAt":"2026-10-01T09:00:00Z"}} |
Conversaciones y tickets · Conversations and tickets
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
notification_job (recurso · resource) | review | support:admin · delegated (admin) | POST /api/v1/notification-jobs/{id}/actions/review {"input":{"action":"confirm_delivered"}} |
support.customer_message | mark_done | support:execute · service | POST /api/v1/tasks/support.customer_message:{id}/actions/mark_done {"input":{}} |
support.customer_message | reopen | support:execute · service | POST /api/v1/tasks/support.customer_message:{id}/actions/reopen {"input":{}} |
support.customer_message | retry_notifications | support:execute · service · 202 | POST /api/v1/tasks/support.customer_message:{id}/actions/retry_notifications {"input":{}} |
support.customer_message | review_notification | support:admin · delegated (admin) | POST /api/v1/tasks/support.customer_message:{id}/actions/review_notification {"input":{"jobId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","action":"retry","confirmPossibleDuplicate":true}} |
support.mention | mark_read | support:execute · recipient | POST /api/v1/tasks/support.mention:{id}/actions/mark_read {"input":{}} |
support.ticket | add_note | support:write · delegated | POST /api/v1/tasks/support.ticket:{id}/actions/add_note {"input":{"text":"Lo revisa Facturación esta tarde.","mentionUserIds":["3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"]}} |
support.ticket | apply_macro | support:execute · delegated · dryRun → previewToken | POST /api/v1/tasks/support.ticket:{id}/actions/apply_macro {"input":{"macroId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","previewToken":"9ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d79ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d7"}} |
support.ticket | assign | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/assign {"input":{"assigneeId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
support.ticket | hand_off | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/hand_off {"input":{}} |
support.ticket | mark_read | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/mark_read {"input":{}} |
support.ticket | merge_into | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/merge_into {"input":{"targetTicketId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
support.ticket | public_reply | support:execute · delegated | POST /api/v1/tasks/support.ticket:{id}/actions/public_reply {"input":{"text":"Hola Lucía, ya hemos reenviado la factura de septiembre."}} |
support.ticket | reopen | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/reopen {"input":{}} |
support.ticket | reply | support:execute · delegated | POST /api/v1/tasks/support.ticket:{id}/actions/reply {"input":{"text":"Hola Lucía, ya hemos reenviado la factura de septiembre.","expectedLastMessageId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
support.ticket | resolve | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/resolve {"input":{}} |
support.ticket | return_to_ai | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/return_to_ai {"input":{}} |
support.ticket | set_labels | support:write · service | POST /api/v1/tasks/support.ticket:{id}/actions/set_labels {"input":{"labelIds":["3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"]}} |
support.ticket | set_stage | support:write · service | POST /api/v1/tasks/support.ticket:{id}/actions/set_stage {"input":{"stageId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
support.ticket | set_status | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/set_status {"input":{"sourceStatus":"waiting_customer"}} |
support.ticket | set_team | support:write · service | POST /api/v1/tasks/support.ticket:{id}/actions/set_team {"input":{"teamId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
support.ticket | snooze | support:execute · delegated | POST /api/v1/tasks/support.ticket:{id}/actions/snooze {"input":{"until":"2026-10-01T09:00:00Z"}} |
support.ticket | split | support:execute · service | POST /api/v1/tasks/support.ticket:{id}/actions/split {"input":{"title":"Segunda factura duplicada"}} |
support.ticket | unsnooze | support:execute · delegated | POST /api/v1/tasks/support.ticket:{id}/actions/unsnooze {"input":{}} |
Encuestas de satisfacción · Satisfaction surveys
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
support.csat_delivery | cancel | csat:execute · service | POST /api/v1/tasks/support.csat_delivery:{id}/actions/cancel {"input":{}} |
support.csat_delivery | retry | csat:execute · service · 202 | POST /api/v1/tasks/support.csat_delivery:{id}/actions/retry {"input":{}} |
support.csat_delivery | review | csat:admin · delegated (admin) | POST /api/v1/tasks/support.csat_delivery:{id}/actions/review {"input":{"decision":"confirm_accepted","reason":"Confirmed with the customer by phone"}} |
support.csat_delivery | send_now | csat:execute · service · 202 | POST /api/v1/tasks/support.csat_delivery:{id}/actions/send_now {"input":{}} |
Voz · Voice
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
voice.capacity_review | review | voice:admin · delegated (admin) | POST /api/v1/tasks/voice.capacity_review:{id}/actions/review {"input":{}} |
voice.job | retry | voice:execute · service · 202 | POST /api/v1/tasks/voice.job:{id}/actions/retry {"input":{"confirmPossibleDuplicate":true}} |
voice_call (recurso · resource) | email_summary | voice:execute · delegated · 202 | POST /api/v1/voice/calls/{call_id}/actions/email_summary {"input":{"emailAccountId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","recipient":"[email protected]"}} |
Calendario y reuniones · Calendar and meetings
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
calendar.booking | reconcile | calendar:execute · service | POST /api/v1/tasks/calendar.booking:{id}/actions/reconcile {"input":{}} |
Campañas · Campaigns
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
campaign_recipient (recurso · resource) | review | campaigns:admin · delegated (admin) | POST /api/v1/campaign-recipients/{id}/actions/review {"input":{"decision":"retry","confirmPossibleDuplicate":true}} |
marketing.campaign | cancel | campaigns:admin · delegated (admin) | POST /api/v1/tasks/marketing.campaign:{id}/actions/cancel {"input":{}} |
marketing.campaign | clone | campaigns:write · delegated | POST /api/v1/tasks/marketing.campaign:{id}/actions/clone {"input":{}} |
marketing.campaign | pause | campaigns:admin · delegated (admin) | POST /api/v1/tasks/marketing.campaign:{id}/actions/pause {"input":{}} |
marketing.campaign | preview | campaigns:write · service · dryRun | POST /api/v1/tasks/marketing.campaign:{id}/actions/preview {"input":{}} |
marketing.campaign | resume | campaigns:admin · delegated (admin) | POST /api/v1/tasks/marketing.campaign:{id}/actions/resume {"input":{}} |
marketing.campaign | schedule | campaigns:admin · delegated (admin) · dryRun → audienceFingerprint | POST /api/v1/tasks/marketing.campaign:{id}/actions/schedule {"input":{"sendAt":"2026-10-01T08:00:00Z","audienceFingerprint":"9ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d79ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d7"}} |
marketing.delivery_review | review_recipient | campaigns:admin · delegated (admin) | POST /api/v1/tasks/marketing.delivery_review:{id}/actions/review_recipient {"input":{"recipientId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","decision":"retry","confirmPossibleDuplicate":true}} |
marketing.experiment_decision | decide | campaigns:admin · delegated (admin) | POST /api/v1/tasks/marketing.experiment_decision:{id}/actions/decide {"input":{"decision":"release"}} |
Recorridos · Journeys
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
journey_enrollment (recurso · resource) | cancel | journeys:admin · delegated (admin) | POST /api/v1/journey-enrollments/{id}/actions/cancel {"input":{}} |
journey_enrollment (recurso · resource) | pause | journeys:admin · delegated (admin) | POST /api/v1/journey-enrollments/{id}/actions/pause {"input":{}} |
journey_enrollment (recurso · resource) | resume | journeys:admin · delegated (admin) | POST /api/v1/journey-enrollments/{id}/actions/resume {"input":{}} |
journey (recurso · resource) | activate | journeys:admin · delegated (admin) | POST /api/v1/automations/{automation_id}/actions/activate {"input":{}} |
journey (recurso · resource) | cancel | journeys:admin · delegated (admin) | POST /api/v1/automations/{automation_id}/actions/cancel {"input":{}} |
journey (recurso · resource) | pause | journeys:admin · delegated (admin) | POST /api/v1/automations/{automation_id}/actions/pause {"input":{}} |
journey (recurso · resource) | resume | journeys:admin · delegated (admin) | POST /api/v1/automations/{automation_id}/actions/resume {"input":{}} |
journey (recurso · resource) | retry_sends | journeys:admin · delegated (admin) | POST /api/v1/automations/{automation_id}/actions/retry_sends {"input":{}} |
marketing.journey_attention | cancel_enrollment | journeys:admin · delegated (admin) | POST /api/v1/tasks/marketing.journey_attention:{id}/actions/cancel_enrollment {"input":{"enrollmentId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
marketing.journey_attention | resume_automation | journeys:admin · delegated (admin) | POST /api/v1/tasks/marketing.journey_attention:{id}/actions/resume_automation {"input":{}} |
marketing.journey_attention | resume_enrollment | journeys:admin · delegated (admin) | POST /api/v1/tasks/marketing.journey_attention:{id}/actions/resume_enrollment {"input":{"enrollmentId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}} |
marketing.journey_attention | retry_sends | journeys:admin · delegated (admin) | POST /api/v1/tasks/marketing.journey_attention:{id}/actions/retry_sends {"input":{}} |
marketing.journey_version | publish_version | journeys:admin · delegated (admin) · dryRun → draftRevision | POST /api/v1/tasks/marketing.journey_version:{id}/actions/publish_version {"input":{"draftRevision":3}} |
Formularios y páginas · Forms and pages
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
marketing.form_publication | archive | forms:admin · delegated (admin) | POST /api/v1/tasks/marketing.form_publication:{id}/actions/archive {"input":{}} |
marketing.form_publication | pause | forms:admin · delegated (admin) | POST /api/v1/tasks/marketing.form_publication:{id}/actions/pause {"input":{}} |
marketing.form_publication | publish | forms:admin · delegated (admin) | POST /api/v1/tasks/marketing.form_publication:{id}/actions/publish {"input":{"expectedRevision":2}} |
marketing.form_publication | resume | forms:admin · delegated (admin) | POST /api/v1/tasks/marketing.form_publication:{id}/actions/resume {"input":{}} |
marketing.placement | activate | forms:admin · delegated (admin) | POST /api/v1/tasks/marketing.placement:{id}/actions/activate {"input":{}} |
marketing.placement | pause | forms:admin · delegated (admin) | POST /api/v1/tasks/marketing.placement:{id}/actions/pause {"input":{}} |
Sitios web · Websites
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
marketing.page_domain | verify | sites:admin · delegated (admin) | POST /api/v1/tasks/marketing.page_domain:{id}/actions/verify {"input":{}} |
marketing.site_verification | verify | sites:admin · delegated (admin) | POST /api/v1/tasks/marketing.site_verification:{id}/actions/verify {"input":{}} |
marketing_site (recurso · resource) | pause | sites:admin · delegated (admin) | POST /api/v1/sites/{id}/actions/pause {"input":{}} |
marketing_site (recurso · resource) | resume | sites:admin · delegated (admin) | POST /api/v1/sites/{id}/actions/resume {"input":{}} |
Conversiones y atribución · Conversions and attribution
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
marketing.conversion_reconciliation | link | conversions:admin · delegated (admin) | POST /api/v1/tasks/marketing.conversion_reconciliation:{id}/actions/link {"input":{"target":{"type":"deal","id":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"},"reason":"Confirmed with the customer by phone"}} |
marketing.conversion_reconciliation | revoke_link | conversions:admin · delegated (admin) | POST /api/v1/tasks/marketing.conversion_reconciliation:{id}/actions/revoke_link {"input":{"linkId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","reason":"Confirmed with the customer by phone"}} |
Conocimiento · Knowledge
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
knowledge.source_error | refresh | knowledge:admin · delegated (admin) · 202 | POST /api/v1/tasks/knowledge.source_error:{id}/actions/refresh {"input":{}} |
Canales y conexiones · Channels and connections
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
channel.health | verify | channels:admin · delegated (admin) | POST /api/v1/tasks/channel.health:account:{id}/actions/verify {"input":{}} |
channel_account (recurso · resource) | verify | channels:admin · delegated (admin) | POST /api/v1/channels/{id}/actions/verify {"input":{}} |
mail_domain (recurso · resource) | verify | channels:admin · delegated (admin) | POST /api/v1/mail-domains/{id}/actions/verify {"input":{}} |
marketing_connection (recurso · resource) | verify | channels:admin · delegated (admin) | POST /api/v1/marketing-connections/{id}/actions/verify {"input":{}} |
Webhooks de tareas · Task webhooks
| Tipo o entidad · Kind or entity | Acción · Action | Scope · actor | Ejemplo · Example |
|---|---|---|---|
integration.webhook_failed | retry | webhooks:manage · service · 202 | POST /api/v1/tasks/integration.webhook_failed:task:{endpointId}/actions/retry {"input":{}} |
marketing_webhook_delivery (recurso · resource) | retry | webhooks:manage · delegated (admin) · 202 | POST /api/v1/marketing-webhooks/{webhook_id}/deliveries/{delivery_id}/actions/retry {"input":{}} |