Guía para desarrolladores · Developer guide

API de tareas y funciones Task and function API

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-kinds con 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

  1. 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 responden 403 FEATURE_DISABLED. Algunas áreas necesitan además su propia función (secuencias crm.sequences, guiones crm.playbooks, duplicados crm.merge, conversiones marketing.tracking…): sin ella sus tipos desaparecen del feed y sus rutas responden 403 FEATURE_DISABLED.
  2. 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.
  3. 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).
  4. 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 con GET /api/v1/key y lo que puede hacer con GET /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):

NivelEquivale en la UI aPermite
readlectorLeer tareas y recursos del área, sus historiales e informes
writeagenteCrear registros y borradores, editar (PATCH) y añadir notas
executeagenteAcciones operativas: completar, resolver, responder, reintentar, conciliar…
adminadministradorProgramar, decidir, fusionar, verificar y revisar inciertos; exige actuar como un administrador (§3)
contentlector con contenidoCuerpos de mensajes, notas internas, textos de clientes y transcripciones
ÁreaScopesFunción exigida además de api.tasks
Contactoscontacts:read, contacts:write, subscriptions:inviteInvitaciones (subscriptions:invite): marketing.api
Empresas clientecompanies:read, companies:write—
Oportunidadesdeals:read, deals:write, deals:execute—
Actividades y seguimientosactivities:read, activities:write, activities:execute—
Secuencias comercialessequences:read, sequences:executecrm.sequences
Guiones comercialesplaybooks:read, playbooks:write, playbooks:executecrm.playbooks
Duplicados y fusionesduplicates:read, duplicates:write, duplicates:admincrm.merge
Conversaciones y ticketssupport:read, support:write, support:execute, support:admin, support:content—
Encuestas CSATcsat:read, csat:execute, csat:adminEntregas: support.csat_auto
Vozvoice:read, voice:execute, voice:admin, voice:content—
Calendariocalendar:read, calendar:execute—
Campañascampaigns:read, campaigns:write, campaigns:adminPush: marketing.push; experimentos: marketing.experiments
Recorridosjourneys:read, journeys:admin, automations:enrollDisparo por evento: marketing.api
Segmentossegments:readBloques de comportamiento: marketing.behavior
Formularios y páginasforms:read, forms:adminFormularios alojados: marketing.pages
Sitios websites:read, sites:adminDominios propios: marketing.custom_domains
Conversionesconversions:read, conversions:adminmarketing.tracking
Conocimientoknowledge:read, knowledge:admin—
Canales y conexioneschannels:read, channels:admin—
Informesreports:readLa de cada informe
Equipoteam:read, team:emails—
Webhooks de tareaswebhooks:manage—
Flujos de automatizaciónautomation: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:

ActorQuién actúaDónde
serviceLa 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
delegatedUn usuario de la lista de la fuenteResponder, notas con mención, posponer, macros y todas las acciones de nivel admin
ownerEl delegado, que además es el titular del buzón comercialSecuencias: reanudar, saltar paso, reintentar y responder
recipientEl delegado, que además es el destinatario de la menciónMarcar 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 scope act_as.
  • Errores: 403 DELEGATED_USER_REQUIRED (la acción necesita un delegado), 403 DELEGATED_USER_NOT_ALLOWED (usuario fuera de la lista o clave sin act_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_REQUIRED y 403 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 con team: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" } }
  • status normalizado: open, in_progress, waiting, needs_review, done o cancelled; sourceStatus conserva el estado nativo y signals añade marcas de un catálogo cerrado (overdue, due_soon, unassigned, sla_resolution_breached, uncertain, reconnect_required…). Ignora los valores que no conozcas.
  • dueAt va con dueKind (due, sla_resolution, wake, send_at, undo_until…); fechas en RFC 3339 y UTC.
  • etag: W/"<n>" en las entidades con revisión y W/"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, available y, 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: title nunca 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 por POST.

Tipos (28; el detalle de estados, campos de PATCH y acciones está en el catálogo estático):

ÁreaTiposAcción de cierre (completion)
Actividadescrm.activitycomplete
Oportunidadescrm.deal_attention—
Duplicadoscrm.duplicate_review, crm.merge_review—
Guionescrm.playbook_session—
Secuenciassales.enrollment, sales.mailbox, sales.conversationsales.conversation: mark_read
Soportesupport.ticket, support.mention, support.customer_messageresolve, mark_read, mark_done
CSATsupport.csat_delivery—
Vozvoice.job, voice.capacity_review—
Calendariocalendar.booking—
Campañasmarketing.campaign, marketing.delivery_review, marketing.experiment_decision—
Recorridosmarketing.journey_attention, marketing.journey_version—
Formulariosmarketing.form_publication, marketing.placement—
Sitiosmarketing.site_verification, marketing.page_domain—
Conversionesmarketing.conversion_reconciliation—
Conocimientoknowledge.source_error—
Canaleschannel.health—
Webhooksintegration.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

GrupoEndpoints
TareasGET 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ónGET /api/v1/task-kinds, GET /api/v1/task-changes/cursor, GET /api/v1/task-changes y GET /api/v1/task-summary
RecursosContactos 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 tareasGET y POST /api/v1/webhooks; GET, PATCH y DELETE /api/v1/webhooks/{id}; POST …/rotate-secret; POST …/test; GET …/deliveries; POST …/deliveries/{deliveryId}/retry
ClaveGET /api/v1/key, GET /api/v1/key/capabilities y GET /api/v1/members
Flujos de automatizaciónGET /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 eventosGET /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ón automation.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, filtros status y subjectId, cursor firmado de 24 h) dan su estado, paso, códigos, el hecho que las inició (triggerEventId, un id del feed de eventos) y, en la ficha, cada paso con su tipo, estado, resultCode y el registro que creó (effect). Iniciar (automation:enroll): POST …/flows/{flowId}/enroll con {"subject": {"type": "contact" | "deal" | "conversation", "id": "…"}} e Idempotency-Key obligatoria (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"} o 200 {"result": "skipped", "reason"} con flowNotActive, subjectUnavailable, conditionsNotMet, activeRunExists, alreadyRan, cooldown o entryLimitReached. La misma clave y cuerpo repiten la respuesta (Idempotent-Replayed: true); otro cuerpo, 409 IDEMPOTENCY_CONFLICT. started no 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:enroll no es automations:enroll (recorridos).
  • Listado GET /api/v1/tasks: filtros kind y area (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, conversationId y updatedSince; sort (dueAt, -updatedAt, -priority, createdAt); limit de 1 a 100 (50) y cursor opaco 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 cabecera ETag. Una tarea de otra empresa, inexistente o que ya no es tarea responde igual: 404 TASK_NOT_FOUND.
  • PATCH con If-Match obligatorio y cuerpo estricto (title, description, status, sourceStatus, priority, dueAt, assigneeId, teamId, category, activityKind, contactId, dealId, ticketId): 422 FIELD_NOT_ALLOWED si el campo no existe, 422 TASK_FIELD_NOT_SUPPORTED (con supportedFields) si el tipo no lo admite, 422 TASK_PATCH_SPLIT_REQUIRED si exigiría dos llamadas internas y 422 TASK_STATUS_REQUIRES_ACTION (con actions) para los estados que solo se alcanzan con una acción.
  • Alta POST /api/v1/tasks: solo crm.activity (un seguimiento ligado a contacto, oportunidad o ticket), con Idempotency-Key obligatoria y externalLink opcional. Responde 201 con Location y ETag.
  • Notas (support.ticket y sales.conversation): leerlas exige <área>:content; añadirlas, <área>:write y un delegado (text ≤ 5.000, mentionUserIds?). Historial sin cuerpos en crm.activity, crm.deal_attention, support.ticket y crm.playbook_session.
  • Enlace externo PUT …/external-link con {externalId, url} (un enlace por fuente y tarea; url HTTPS) y lookup POST /api/v1/tasks/lookup con {externalId} en el cuerpo: la tarea que tu fuente enlazó.
  • Recursos: cada uno con listado por cursor, ficha con ETag, If-Match en sus PATCH, Idempotency-Key en sus altas y las mismas acciones que sus tareas en POST /api/v1/<recurso>/{id}/actions/{action} (la referencia de acciones da la ruta de cada una). Sin DELETE de 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:

    1. El tipo de la taskId y la acción existen (404 TASK_NOT_FOUND / TASK_ACTION_NOT_FOUND; en la ruta del recurso, RESOURCE_NOT_FOUND / ACTION_NOT_FOUND).
    2. Función y scope (403 FEATURE_DISABLED / API_SCOPE_REQUIRED).
    3. Formato de If-Match (422 IF_MATCH_INVALID) y del cuerpo (415 sin Content-Type: application/json, 422).
    4. Actor (403).
    5. Sin dryRun: Idempotency-Key (428 IDEMPOTENCY_KEY_REQUIRED; 422 si no es válida) y su recibo. Un replay (Idempotent-Replayed: true) o un 409 IDEMPOTENCY_* / ACTION_OUTCOME_UNKNOWN responden 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.
    6. La tarea existe y es de tu empresa (404 TASK_NOT_FOUND; en el recurso, RESOURCE_NOT_FOUND).
    7. If-Match si viene (412 REVISION_CONFLICT).
    8. Disponibilidad en el estado actual (409 TASK_ACTION_NOT_AVAILABLE con reason, o 409 SEND_SWITCH_OFF; los motivos de persona, como MAILBOX_OWNER_REQUIRED, responden 403).
    9. input (422).
    10. Cuota (429, también con dryRun).
    11. Ejecución.

    Por eso una tarea inexistente con una clave sin el scope responde 403, no 404.

  • input sigue el inputSchema de 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 como ACTION_REJECTED.
  • Respuesta 200 con outcome: "succeeded" si el efecto está aplicado o 202 con outcome: "accepted" si la función solo encola (reintentos de envío, refresco de conocimiento, envío de CSAT); result es mínimo (IDs, recuentos, tokens) y task trae el estado y el ETag nuevos.
  • dryRun: true no escribe nada, no exige Idempotency-Key y no consume idempotencia (sí cuenta en la cuota). Si la acción tiene un paso previo nativo, lo ejecuta y devuelve su token en confirm; la ejecución lo exige:
AccióndryRun devuelveLa ejecución exige
marketing.campaign · scheduleVista 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 audienceFingerprintaudienceFingerprint (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 expiresAtplanHash, expiresAt y reason
crm.merge_review · undoEl plan de deshacerEl mismo plan
support.ticket · apply_macro y /conversations/bulkCambios y previewTokenpreviewToken
crm.playbook_session · completeEfectos y expectedValuesexpectedValues y target
POST /api/v1/sequences/{id}/enrollmentsElegibles y motivos de exclusiónLa misma Idempotency-Key
marketing.journey_version · publish_versionValidación y diferenciasdraftRevision

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_* con retry, voice.job.retry, review_notification) exigen confirmPossibleDuplicate: true, como la UI. Si el interruptor global de envío está apagado: 409 SEND_SWITCH_OFF.

7. Idempotencia

  • If-Match es obligatorio en todo PATCH (428 PRECONDITION_REQUIRED sin él; 412 REVISION_CONFLICT con currentEtag y la cabecera ETag si no es el actual) y opcional en las acciones (si viene, se comprueba igual). Ante un 412: lee la tarea, fusiona y reintenta con el ETag nuevo.
  • Idempotency-Key (1-200 caracteres A-Z a-z 0-9 . _ : ~ -, empezando por letra o dígito) es obligatoria en las altas y en las acciones salvo con dryRun (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 claveRespuesta
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 curso409 IDEMPOTENCY_IN_PROGRESS con Retry-After
Mismo cuerpo, ejecución interrumpida sin resultado409 ACTION_OUTCOME_UNKNOWN: lee la tarea y decide; RouterClip nunca la repite sola
Otro cuerpo409 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_EXPIRED y obliga a resincronizar.
  • GET /api/v1/task-summary devuelve recuentos por tipo, estado y responsable con los filtros del listado, para cuadros de mando.

9. Webhooks

  • Alta con webhooks:manage: POST /api/v1/webhooks con {name, url, kinds?, events?, skipOwnChanges?, enabled?}. url es HTTPS en el puerto 443 dentro de un origen autorizado por la plataforma; kinds vacío significa todos los que la clave puede leer; events entre task.created, task.updated, task.completed y task.deleted. Límites: 5 por fuente y 20 por empresa. La respuesta trae el secreto whsec_… una sola vez (también POST …/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 desde data.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 e Idempotency-Key) y X-CRM-Event-Id.
  • Reintentos: hasta 8 intentos con espera creciente; un 4xx distinto de 429 es fallo definitivo y un 410 desactiva el endpoint. POST …/test envía un ping; GET …/deliveries y POST …/deliveries/{id}/retry permiten 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 en failureStreak (intentos fallidos seguidos) y deferredUntil (hasta cuándo espera; null si 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.

HTTPCódigoQué hacer
400CURSOR_INVALIDCursor alterado, caducado o de otra consulta: empieza sin él
401 / 402API_KEY_*, API_SOURCE_DISABLED, COMPANY_INACTIVE / SUBSCRIPTION_PAYMENT_REQUIREDNo reintentar
403API_SCOPE_REQUIRED (requiredScopes), FEATURE_DISABLED (feature), DELEGATED_USER_*, ACTOR_ROLE_INSUFFICIENT, MAILBOX_OWNER_REQUIRED, MENTION_RECIPIENT_REQUIREDRevisar la clave, la fuente o el delegado
404TASK_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
409TASK_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
410CURSOR_EXPIREDResincronizar
412REVISION_CONFLICT (currentEtag)Leer, fusionar y reintentar
413 / 415Cuerpo de más de 32 KiB / falta Content-Type: application/jsonCorregir
422FIELD_NOT_ALLOWED, VALIDATION_ERROR (field), TASK_FIELD_NOT_SUPPORTED, TASK_STATUS_REQUIRES_ACTION, TASK_PATCH_SPLIT_REQUIRED, IF_MATCH_INVALID…Corregir; no reintentar igual
428PRECONDITION_REQUIRED / IDEMPOTENCY_KEY_REQUIREDEnviar If-Match o Idempotency-Key
429RATE_LIMITED (Retry-After, quota)Esperar lo indicado y reintentar con la misma clave
503Servicio no disponible (por ejemplo, CURSOR_KEY_UNAVAILABLE), con Retry-After si lo hayEsperar y reintentar

11. Cuotas

LímiteValor
Peticiones120 por minuto y clave, 600 por minuto y empresa (compartidas con el resto de /api/v1)
Escrituras y acciones60 por minuto y clave; un dryRun también cuenta
Cuotas propiasSe mantienen las de cada función: vista previa de fusión, envíos de marketing y CSAT, cupo diario de secuencias…
Páginas100 tareas por página del listado y 500 cambios por página del feed
Cuerpo32 KiB; reply y public_reply hasta 10.000 caracteres y notas hasta 5.000
Delegados y webhooks20 delegados por fuente; 5 webhooks por fuente y 20 por empresa
RetenciónLá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 con crm.activity,crm.deal_attention,sales.enrollment; Marketing; Operación). Crea las incidencias con la carga inicial y guarda el id de RouterClip en una propiedad «RouterClip Task ID»; enlázalas con PUT …/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 completion del tipo con Idempotency-Key: jira-<issue>-changelog-<id>; el cambio de assignee o de fecha de vencimiento es un PATCH con If-Match; un comentario público de un agente es reply con X-AIO-Act-As del 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/lookup con {"externalId": "SUP-431"}.

12.2 Asana

  • Proyecto por área con secciones por status; el id de RouterClip en un campo personalizado y external-link a la tarea de Asana.
  • Completar en Asana (completed: true) → acción completion (complete en crm.activity, resolve en support.ticket). Las tareas sin completion se crean con una regla o botón que llama a la acción con dryRun primero.
  • Los webhooks de Asana llegan a tu servicio; usa su resource.gid + created_at como Idempotency-Key.

12.3 ClickUp

  • Lista por área; los estados de ClickUp se mapean 1:1 con los seis normalizados. El id en 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 → PATCH assigneeId en 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 (Issue con updatedFrom) dispara en tu servicio el PATCH o la acción; usa el webhookId + updatedAt como 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) con dryRun primero 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 el id de RouterClip en su descripción o en un campo personalizado y external-link apunta 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_ACTION indica qué acciones lo consiguen).
  • Los webhooks de Trello (action.id) dan la Idempotency-Key.

12.7 Notion

  • Base de datos por área con propiedades RouterClip ID, Estado (select con los seis valores), Responsable, Vence y Enlace (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 o GET /api/v1/task-changes bastan.
  • Cambiar Estado a «Hecho» en Notion → acción completion con Idempotency-Key: notion-<pageId>-<last_edited_time>.

13. Cómo evitar bucles

  • Deja skipOwnChanges activado (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-Key el ID del evento de la herramienta: si el mismo evento llega dos veces, RouterClip devuelve la misma respuesta (replayed: true) sin ejecutar nada.
  • Compara version antes de aplicar y descarta lo antiguo; el webhook solo despierta, el estado se lee del feed o del detalle.
  • Ante un 412 o un 409, 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

  1. The RouterClip team enables the “Task and function API” feature (api.tasks) for your company; without it every route of this guide answers 403 FEATURE_DISABLED. Some areas also need their own feature (sequences crm.sequences, playbooks crm.playbooks, duplicates crm.merge, conversions marketing.tracking…): without it their kinds leave the feed and their routes answer 403 FEATURE_DISABLED.
  2. 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.
  3. 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).
  4. 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 with GET /api/v1/key and what it can do with GET /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 entityAcción · ActionScope · actorEjemplo · Example
crm.deal_attentionarchivedeals:execute · servicePOST /api/v1/tasks/crm.deal_attention:{id}/actions/archive {"input":{}}
crm.deal_attentionlosedeals:execute · servicePOST /api/v1/tasks/crm.deal_attention:{id}/actions/lose {"input":{"lostReason":"Price"}}
crm.deal_attentionreopendeals:execute · servicePOST /api/v1/tasks/crm.deal_attention:{id}/actions/reopen {"input":{}}
crm.deal_attentionrestoredeals:execute · servicePOST /api/v1/tasks/crm.deal_attention:{id}/actions/restore {"input":{}}
crm.deal_attentionschedule_next_activitydeals:write + activities:write · servicePOST /api/v1/tasks/crm.deal_attention:{id}/actions/schedule_next_activity {"input":{"title":"Llamar para renovar","dueAt":"2026-10-01T09:00:00Z"}}
crm.deal_attentionupdate_dealdeals:write · servicePOST /api/v1/tasks/crm.deal_attention:{id}/actions/update_deal {"input":{"amount":"12000.00","currency":"EUR","expectedClose":"2026-11-30"}}
crm.deal_attentionwindeals:execute · servicePOST /api/v1/tasks/crm.deal_attention:{id}/actions/win {"input":{}}

Actividades y seguimientos · Activities and follow-ups

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
crm.activitycancelactivities:execute · servicePOST /api/v1/tasks/crm.activity:{id}/actions/cancel {"input":{}}
crm.activitycompleteactivities:execute · servicePOST /api/v1/tasks/crm.activity:{id}/actions/complete {"input":{}}
crm.activityreassignactivities:execute · servicePOST /api/v1/tasks/crm.activity:{id}/actions/reassign {"input":{"assigneeId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
crm.activityreopenactivities:execute · servicePOST /api/v1/tasks/crm.activity:{id}/actions/reopen {"input":{}}
crm.activityrescheduleactivities:execute · servicePOST /api/v1/tasks/crm.activity:{id}/actions/reschedule {"input":{"dueAt":"2026-10-01T09:00:00Z"}}
crm_activity (recurso · resource)start_playbookactivities:read + playbooks:execute · delegatedPOST /api/v1/activities/{id}/actions/start_playbook {"input":{"playbookId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}

Secuencias comerciales · Sales sequences

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
sales.conversationmark_readsequences:execute · servicePOST /api/v1/tasks/sales.conversation:{id}/actions/mark_read {"input":{}}
sales.conversationreplysequences:execute · ownerPOST /api/v1/tasks/sales.conversation:{id}/actions/reply {"input":{"text":"Hola Lucía, ya hemos reenviado la factura de septiembre.","expectedLastMessageId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
sales.enrollmentcancelsequences:execute · delegatedPOST /api/v1/tasks/sales.enrollment:{id}/actions/cancel {"input":{"reason":"The customer already bought"}}
sales.enrollmentpausesequences:execute · delegatedPOST /api/v1/tasks/sales.enrollment:{id}/actions/pause {"input":{"reason":"The customer is on holiday"}}
sales.enrollmentreconcile_executionsequences:execute · delegatedPOST /api/v1/tasks/sales.enrollment:{id}/actions/reconcile_execution {"input":{}}
sales.enrollmentresumesequences:execute · ownerPOST /api/v1/tasks/sales.enrollment:{id}/actions/resume {"input":{}}
sales.enrollmentreview_executionsequences:execute · delegatedPOST /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.enrollmentskip_stepsequences:execute · ownerPOST /api/v1/tasks/sales.enrollment:{id}/actions/skip_step {"input":{"reason":"Confirmed with the customer by phone"}}
sales_sequence (recurso · resource)pausesequences:execute · delegatedPOST /api/v1/sequences/{id}/actions/pause {"input":{}}
sales_sequence (recurso · resource)resumesequences:execute · delegatedPOST /api/v1/sequences/{id}/actions/resume {"input":{}}

Guiones comerciales · Sales playbooks

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
crm.playbook_sessionabandonplaybooks:execute · delegatedPOST /api/v1/tasks/crm.playbook_session:{id}/actions/abandon {"input":{}}
crm.playbook_sessioncompleteplaybooks:execute · delegated · dryRun → expectedValues, targetPOST /api/v1/tasks/crm.playbook_session:{id}/actions/complete {"input":{"expectedValues":[{"entity":"contact","fieldId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}],"target":{"contactId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}}
crm.playbook_sessionsaveplaybooks:write · delegatedPOST /api/v1/tasks/crm.playbook_session:{id}/actions/save {"input":{}}

Duplicados y fusiones · Duplicates and merges

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
crm.duplicate_reviewdismissduplicates:write · delegatedPOST /api/v1/tasks/crm.duplicate_review:contact:{idA}:{idB}/actions/dismiss {"input":{}}
crm.duplicate_reviewmergeduplicates:admin · delegated (admin) · dryRun → planHash, expiresAtPOST /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_reviewpreview_mergeduplicates:admin · delegated (admin) · dryRunPOST /api/v1/tasks/crm.duplicate_review:contact:{idA}:{idB}/actions/preview_merge {"input":{"survivorId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
crm.duplicate_reviewrestoreduplicates:write · delegatedPOST /api/v1/tasks/crm.duplicate_review:contact:{idA}:{idB}/actions/restore {"input":{}}
crm.merge_reviewreviewduplicates:admin · delegated (admin)POST /api/v1/tasks/crm.merge_review:{id}/actions/review {"input":{}}
crm.merge_reviewundoduplicates:admin · delegated (admin) · dryRun → planHash, expiresAtPOST /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 entityAcción · ActionScope · actorEjemplo · Example
notification_job (recurso · resource)reviewsupport:admin · delegated (admin)POST /api/v1/notification-jobs/{id}/actions/review {"input":{"action":"confirm_delivered"}}
support.customer_messagemark_donesupport:execute · servicePOST /api/v1/tasks/support.customer_message:{id}/actions/mark_done {"input":{}}
support.customer_messagereopensupport:execute · servicePOST /api/v1/tasks/support.customer_message:{id}/actions/reopen {"input":{}}
support.customer_messageretry_notificationssupport:execute · service · 202POST /api/v1/tasks/support.customer_message:{id}/actions/retry_notifications {"input":{}}
support.customer_messagereview_notificationsupport:admin · delegated (admin)POST /api/v1/tasks/support.customer_message:{id}/actions/review_notification {"input":{"jobId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","action":"retry","confirmPossibleDuplicate":true}}
support.mentionmark_readsupport:execute · recipientPOST /api/v1/tasks/support.mention:{id}/actions/mark_read {"input":{}}
support.ticketadd_notesupport:write · delegatedPOST /api/v1/tasks/support.ticket:{id}/actions/add_note {"input":{"text":"Lo revisa Facturación esta tarde.","mentionUserIds":["3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"]}}
support.ticketapply_macrosupport:execute · delegated · dryRun → previewTokenPOST /api/v1/tasks/support.ticket:{id}/actions/apply_macro {"input":{"macroId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","previewToken":"9ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d79ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d7"}}
support.ticketassignsupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/assign {"input":{"assigneeId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
support.tickethand_offsupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/hand_off {"input":{}}
support.ticketmark_readsupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/mark_read {"input":{}}
support.ticketmerge_intosupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/merge_into {"input":{"targetTicketId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
support.ticketpublic_replysupport:execute · delegatedPOST /api/v1/tasks/support.ticket:{id}/actions/public_reply {"input":{"text":"Hola Lucía, ya hemos reenviado la factura de septiembre."}}
support.ticketreopensupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/reopen {"input":{}}
support.ticketreplysupport:execute · delegatedPOST /api/v1/tasks/support.ticket:{id}/actions/reply {"input":{"text":"Hola Lucía, ya hemos reenviado la factura de septiembre.","expectedLastMessageId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
support.ticketresolvesupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/resolve {"input":{}}
support.ticketreturn_to_aisupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/return_to_ai {"input":{}}
support.ticketset_labelssupport:write · servicePOST /api/v1/tasks/support.ticket:{id}/actions/set_labels {"input":{"labelIds":["3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"]}}
support.ticketset_stagesupport:write · servicePOST /api/v1/tasks/support.ticket:{id}/actions/set_stage {"input":{"stageId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
support.ticketset_statussupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/set_status {"input":{"sourceStatus":"waiting_customer"}}
support.ticketset_teamsupport:write · servicePOST /api/v1/tasks/support.ticket:{id}/actions/set_team {"input":{"teamId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
support.ticketsnoozesupport:execute · delegatedPOST /api/v1/tasks/support.ticket:{id}/actions/snooze {"input":{"until":"2026-10-01T09:00:00Z"}}
support.ticketsplitsupport:execute · servicePOST /api/v1/tasks/support.ticket:{id}/actions/split {"input":{"title":"Segunda factura duplicada"}}
support.ticketunsnoozesupport:execute · delegatedPOST /api/v1/tasks/support.ticket:{id}/actions/unsnooze {"input":{}}

Encuestas de satisfacción · Satisfaction surveys

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
support.csat_deliverycancelcsat:execute · servicePOST /api/v1/tasks/support.csat_delivery:{id}/actions/cancel {"input":{}}
support.csat_deliveryretrycsat:execute · service · 202POST /api/v1/tasks/support.csat_delivery:{id}/actions/retry {"input":{}}
support.csat_deliveryreviewcsat: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_deliverysend_nowcsat:execute · service · 202POST /api/v1/tasks/support.csat_delivery:{id}/actions/send_now {"input":{}}

Voz · Voice

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
voice.capacity_reviewreviewvoice:admin · delegated (admin)POST /api/v1/tasks/voice.capacity_review:{id}/actions/review {"input":{}}
voice.jobretryvoice:execute · service · 202POST /api/v1/tasks/voice.job:{id}/actions/retry {"input":{"confirmPossibleDuplicate":true}}
voice_call (recurso · resource)email_summaryvoice:execute · delegated · 202POST /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 entityAcción · ActionScope · actorEjemplo · Example
calendar.bookingreconcilecalendar:execute · servicePOST /api/v1/tasks/calendar.booking:{id}/actions/reconcile {"input":{}}

Campañas · Campaigns

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
campaign_recipient (recurso · resource)reviewcampaigns:admin · delegated (admin)POST /api/v1/campaign-recipients/{id}/actions/review {"input":{"decision":"retry","confirmPossibleDuplicate":true}}
marketing.campaigncancelcampaigns:admin · delegated (admin)POST /api/v1/tasks/marketing.campaign:{id}/actions/cancel {"input":{}}
marketing.campaignclonecampaigns:write · delegatedPOST /api/v1/tasks/marketing.campaign:{id}/actions/clone {"input":{}}
marketing.campaignpausecampaigns:admin · delegated (admin)POST /api/v1/tasks/marketing.campaign:{id}/actions/pause {"input":{}}
marketing.campaignpreviewcampaigns:write · service · dryRunPOST /api/v1/tasks/marketing.campaign:{id}/actions/preview {"input":{}}
marketing.campaignresumecampaigns:admin · delegated (admin)POST /api/v1/tasks/marketing.campaign:{id}/actions/resume {"input":{}}
marketing.campaignschedulecampaigns:admin · delegated (admin) · dryRun → audienceFingerprintPOST /api/v1/tasks/marketing.campaign:{id}/actions/schedule {"input":{"sendAt":"2026-10-01T08:00:00Z","audienceFingerprint":"9ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d79ab3c4d5e6f7a8b9c0d1e2f3a4b5c6d7"}}
marketing.delivery_reviewreview_recipientcampaigns:admin · delegated (admin)POST /api/v1/tasks/marketing.delivery_review:{id}/actions/review_recipient {"input":{"recipientId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40","decision":"retry","confirmPossibleDuplicate":true}}
marketing.experiment_decisiondecidecampaigns:admin · delegated (admin)POST /api/v1/tasks/marketing.experiment_decision:{id}/actions/decide {"input":{"decision":"release"}}

Recorridos · Journeys

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
journey_enrollment (recurso · resource)canceljourneys:admin · delegated (admin)POST /api/v1/journey-enrollments/{id}/actions/cancel {"input":{}}
journey_enrollment (recurso · resource)pausejourneys:admin · delegated (admin)POST /api/v1/journey-enrollments/{id}/actions/pause {"input":{}}
journey_enrollment (recurso · resource)resumejourneys:admin · delegated (admin)POST /api/v1/journey-enrollments/{id}/actions/resume {"input":{}}
journey (recurso · resource)activatejourneys:admin · delegated (admin)POST /api/v1/automations/{automation_id}/actions/activate {"input":{}}
journey (recurso · resource)canceljourneys:admin · delegated (admin)POST /api/v1/automations/{automation_id}/actions/cancel {"input":{}}
journey (recurso · resource)pausejourneys:admin · delegated (admin)POST /api/v1/automations/{automation_id}/actions/pause {"input":{}}
journey (recurso · resource)resumejourneys:admin · delegated (admin)POST /api/v1/automations/{automation_id}/actions/resume {"input":{}}
journey (recurso · resource)retry_sendsjourneys:admin · delegated (admin)POST /api/v1/automations/{automation_id}/actions/retry_sends {"input":{}}
marketing.journey_attentioncancel_enrollmentjourneys:admin · delegated (admin)POST /api/v1/tasks/marketing.journey_attention:{id}/actions/cancel_enrollment {"input":{"enrollmentId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
marketing.journey_attentionresume_automationjourneys:admin · delegated (admin)POST /api/v1/tasks/marketing.journey_attention:{id}/actions/resume_automation {"input":{}}
marketing.journey_attentionresume_enrollmentjourneys:admin · delegated (admin)POST /api/v1/tasks/marketing.journey_attention:{id}/actions/resume_enrollment {"input":{"enrollmentId":"3c1f2a9e0b7d4c1e9f3a5b7c9d1e2f40"}}
marketing.journey_attentionretry_sendsjourneys:admin · delegated (admin)POST /api/v1/tasks/marketing.journey_attention:{id}/actions/retry_sends {"input":{}}
marketing.journey_versionpublish_versionjourneys:admin · delegated (admin) · dryRun → draftRevisionPOST /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 entityAcción · ActionScope · actorEjemplo · Example
marketing.form_publicationarchiveforms:admin · delegated (admin)POST /api/v1/tasks/marketing.form_publication:{id}/actions/archive {"input":{}}
marketing.form_publicationpauseforms:admin · delegated (admin)POST /api/v1/tasks/marketing.form_publication:{id}/actions/pause {"input":{}}
marketing.form_publicationpublishforms:admin · delegated (admin)POST /api/v1/tasks/marketing.form_publication:{id}/actions/publish {"input":{"expectedRevision":2}}
marketing.form_publicationresumeforms:admin · delegated (admin)POST /api/v1/tasks/marketing.form_publication:{id}/actions/resume {"input":{}}
marketing.placementactivateforms:admin · delegated (admin)POST /api/v1/tasks/marketing.placement:{id}/actions/activate {"input":{}}
marketing.placementpauseforms:admin · delegated (admin)POST /api/v1/tasks/marketing.placement:{id}/actions/pause {"input":{}}

Sitios web · Websites

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
marketing.page_domainverifysites:admin · delegated (admin)POST /api/v1/tasks/marketing.page_domain:{id}/actions/verify {"input":{}}
marketing.site_verificationverifysites:admin · delegated (admin)POST /api/v1/tasks/marketing.site_verification:{id}/actions/verify {"input":{}}
marketing_site (recurso · resource)pausesites:admin · delegated (admin)POST /api/v1/sites/{id}/actions/pause {"input":{}}
marketing_site (recurso · resource)resumesites:admin · delegated (admin)POST /api/v1/sites/{id}/actions/resume {"input":{}}

Conversiones y atribución · Conversions and attribution

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
marketing.conversion_reconciliationlinkconversions: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_reconciliationrevoke_linkconversions: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 entityAcción · ActionScope · actorEjemplo · Example
knowledge.source_errorrefreshknowledge:admin · delegated (admin) · 202POST /api/v1/tasks/knowledge.source_error:{id}/actions/refresh {"input":{}}

Canales y conexiones · Channels and connections

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
channel.healthverifychannels:admin · delegated (admin)POST /api/v1/tasks/channel.health:account:{id}/actions/verify {"input":{}}
channel_account (recurso · resource)verifychannels:admin · delegated (admin)POST /api/v1/channels/{id}/actions/verify {"input":{}}
mail_domain (recurso · resource)verifychannels:admin · delegated (admin)POST /api/v1/mail-domains/{id}/actions/verify {"input":{}}
marketing_connection (recurso · resource)verifychannels:admin · delegated (admin)POST /api/v1/marketing-connections/{id}/actions/verify {"input":{}}

Webhooks de tareas · Task webhooks

Tipo o entidad · Kind or entityAcción · ActionScope · actorEjemplo · Example
integration.webhook_failedretrywebhooks:manage · service · 202POST /api/v1/tasks/integration.webhook_failed:task:{endpointId}/actions/retry {"input":{}}
marketing_webhook_delivery (recurso · resource)retrywebhooks:manage · delegated (admin) · 202POST /api/v1/marketing-webhooks/{webhook_id}/deliveries/{delivery_id}/actions/retry {"input":{}}