Run and protect
Moving from v1
v1 (/v1/external) still works. Every v1 response carries a Deprecation header with the deprecation date (2 November 2026) and a Link to this page. No shutdown date has been set. When one is, v1 responses add a Sunset header.
New integrations should use v2. Existing ones can move one flow at a time, because a v1 credential and a v2 key are both organization keys.
What changed
| v1 | v2 | |
|---|---|---|
| Prefix | /v1/external/... | /v2/... |
| Agent in the path | :agentId or :slug | Always agt_.... A slug is only a filter |
| Conversation | conversationId, a deal id or id | One object, a case: cse_... |
| Lists | { data, limit, offset, hasMore } | { object: "list", data, hasMore, nextCursor } with limit and cursor |
| Errors | Mixed shapes | RFC 9457 application/problem+json with a stable code and requestId |
| Webhook signature | X-Lelemon-Timestamp and X-Lelemon-Signature | Lelemon-Signature: t=...,v1=... |
| Webhook setup | Configured by Lelemon | POST /v2/webhook-endpoints |
| Events | Six v1 events | A catalog |
| Idempotency | Not supported | Idempotency-Key on every POST |
Route map
| v1 | v2 |
|---|---|
GET /agents, GET /agents/{agentId} | GET /v2/agents, GET /v2/agents/{id} |
POST /agent-templates/{templateId}/instantiate | POST /v2/agents with fromTemplate |
PATCH /agents/{agentId} | PATCH /v2/agents/{id}. Send expectedVersion to avoid overwriting a newer version |
POST /agents/{agentId}/activate, /pause | POST /v2/agents/{id}/activate, /pause |
GET /agents/{agentId}/prompt-versions, .../restore | GET /v2/agents/{id}/versions, .../{versionId}/restore |
POST /actions, GET /actions, DELETE /actions/{slug} | POST /v2/actions, GET /v2/actions, DELETE /v2/actions/{id}. The variables of an action have the same place in v2, with source, variable and field and English names for the variables (conversacion.id is case.id) |
GET /actions/authorization | GET /v2/actions/authorization |
PUT /agents/{agentId}/actions/{slug} | PUT /v2/agents/{id}/tools/{toolId} |
POST /agents/{slug}/skills and the rest | /v2/agents/{id}/skills |
POST /knowledge/collections, PUT /knowledge/documents | /v2/knowledge-collections and /v2/knowledge-collections/{id}/documents |
PUT /agents/{agentId}/knowledge/{collectionId} | PUT /v2/agents/{id}/knowledge-collections/{collectionId} |
POST /agents/{slug}/conversations | POST /v2/cases |
POST /conversations/{id}/messages | POST /v2/cases/{id}/messages with author: "contact" |
POST /conversations/{id}/send | POST /v2/cases/{id}/messages with author: "team" |
POST /conversations/{id}/notas | POST /v2/cases/{id}/messages with visibility: "internal", or POST /v2/cases/{id}/notes |
POST /conversations/{id}/derivar | POST /v2/cases/{id}/move with pipelineId or stageId. To hand the case to a person, POST /v2/cases/{id}/escalate |
PUT /conversations/{id}/campos | PATCH /v2/cases/{id} with fields |
GET /conversations/{id}/historial | GET /v2/cases?contactId=... |
GET /conversations/{id}/adjuntos | /v2/cases/{id}/attachments |
POST /conversations/{id}/resolve | POST /v2/cases/{id}/close |
GET /pipelines, GET /pipelines/{id} | /v2/pipelines, with /stages, /fields and /routing-rules as resources |
PUT /pipelines/{id}/fields/options | PATCH /v2/pipelines/{id}/fields/{fieldId} |
PATCH /pipelines/{id} with settings | settings on PATCH /v2/pipelines/{id}: autoClose, businessHours, waitThresholds, askFor, timezone, stageOnTakeControl and stageOnHandoff. The names are in English and each block replaces the whole block |
PATCH /pipelines/{id}/stages/{stageId} with isTerminal, closingOutcome, statusType, defaultNextStageId, transitions or config | The same route in v2 with closes, closingOutcome, statusType, nextStageId, transitions and config (agentMode, followUp, durations and delayMinutes) |
PUT/DELETE /pipelines/{id}/stages/{stageId}/source/whatsapp | whatsappPhoneNumberId on PATCH /v2/pipelines/{id}/stages/{stageId}; null releases the number |
GET/PUT /pipelines/{id}/respuestas-rapidas | quickReplies on PATCH /v2/pipelines/{id}, which replaces the whole list |
GET /metrics/conversations | GET /v2/case-metrics, paginated with cursor. aiSeconds is agentSeconds, resolvedByAi is resolvedByAgent and closedBy: "ai" is "agent" |
POST /events | POST /v2/contact-events |
GET /scheduling/agendas | GET /v2/scheduling/agendas. A slug becomes the agd_… id |
GET /scheduling/availability?agenda=slug | GET /v2/scheduling/availability?agendaId=agd_…. Slots are { start, end } |
POST /scheduling/meetings | POST /v2/scheduling/meetings with agendaId and start. Also GET, /cancel and /reschedule, and the events meeting.scheduled, meeting.rescheduled and meeting.canceled |
GET /miembros/disponibilidad?email= | GET /v2/members/{id}/availability. Find the mbr_ id in GET /v2/members. Needs members:read |
PUT /miembros/disponibilidad | PUT /v2/members/{id}/availability with status available or away. Needs members:write |
POST /triggers, GET /triggers, PATCH /triggers/{id} | /v2/triggers |
POST /agents/{slug}/runs | POST /v2/agents/{id}/runs, with actor instead of the signed pedidoPor and limits instead of topes |
GET /runs/{id} | GET /v2/runs/{id}, and GET /v2/runs to list |
POST /runs/{id}/cancel | POST /v2/runs/{id}/cancel |
POST /runs/{id}/answer | POST /v2/runs/{id}/answer with answer and an optional actor instead of the signed respondidoPor |
Check the API reference for the exact body of each v2 route.
Move in this order
- Create a key and rebuild your flow, using
?dryRun=truewhere a route accepts it. - Replace your webhook receiver: verify the new signature and handle events by their new types.
- Switch reads, then writes. Keep sending
Idempotency-Keyfrom the first write. - Create a live key and cut over one flow at a time.
The v1 documentation is still available under v1 (legacy).