Changelog
6 November 2026: The attention queue of a member
- Case queue:
GET /v2/case-queue?memberId=(caseQueue.retrieve, scopecases:read) returns what a member has to look at, in three lists:waitingForPerson(the agent handed the case to a person and nobody took it, assigned to the member or without an owner, withwaitColorgreen, yellow or red by the wait thresholds of the pipeline),waitingForReply(cases the member escalated, in a stage withattentionRoleescalation) andanswered(cases back in a stage withattentionRoleanswerthat still need a reply to the customer).waitMinutescounts only the business hours of the pipeline, and each case appears once. - Stages:
config.attentionRole(escalation,answerornull) onPOSTandPATCH /v2/pipelines/{id}/stages. When a case enters ananswerstage, its owner gets a notification.
6 November 2026: The API and the MCP do what the dashboard lets the role do
- Breaking, scopes: what the dashboard keeps for admins and the owner no longer hangs from
cases:write,contacts:writeandcontacts:presence. It has scopes of its own, and a key acts with at most the role of whoever issued it:cases:delete:DELETE /v2/cases/{id},POST /v2/cases/{id}/archive,POST /v2/cases/{id}/unarchiveandPOST /v2/cases/{id}/messages/{messageId}/redact.cases:reorganize:POST /v2/cases/move-batch, andPOST /v2/cases/{id}/movewhen it changes the pipeline (apipelineId, or astageIdof another pipeline). Moving between stages of the same pipeline stays incases:write.contacts:erase:DELETE /v2/contacts/{id}.opt-outs:write:PUTandDELETE /v2/contacts/{contactId}/opt-outs/{channel}.contact-fields:write:POST /v2/contact-fieldsandPATCH,DELETE /v2/contact-fields/{id}.presence:configure:GETandPUT /v2/presence/settings.contacts:presencekeeps onlyPOST /v2/presence/signals.
- Existing keys and connections: the ones issued by an admin or the owner that had the old scope got the new ones, so their integrations keep working. The ones issued by a member did not: a member cannot hold them, as in the dashboard.
- Assigning:
POST /v2/cases/{id}/assignrecords who assigned (the person who issued the key, or the person who connected through the MCP) and applies the rule of the dashboard: a member only assigns to people of their own team, and403 forbiddenotherwise. The MCP toolcreate_leadwithassign_tofollows the same rule. - Scopes:
conversations:route(POST /v1/external/conversations/{id}/derivar) now needs a key issued by an admin or the owner, likecases:reorganize. - MCP:
move_deal_to_pipelinealso needs thecases:reorganizepermission on the connection. The tools of the CRM check the role of the person on every call:move_deal_to_pipelineis for admins and the owner. A tool the role cannot use is not listed.
5 November 2026: Escalate a case to your technical team in Linear
- Linear:
PUT,GET,PATCHandDELETE /v2/integrations/linear(linear.connect,linear.retrieve,linear.update,linear.disconnect) connect the Linear of the organization with its own API key, choose the team and project that receive the issues and save the signing secret of the Linear webhook. New scopeslinear:readandlinear:write, both for admins. - Cases:
POST /v2/cases/{id}/escalate-to-team(cases.escalateToTeam) creates an issue in Linear with the contact, the pipeline, the last messages and the link to the case, and never a second one while the first is open.GET /v2/cases/{id}/team-escalationslists the escalations with their issue, status and answer. - Stages: a case that enters a stage with
config.attentionRoleescalationis escalated by itself when Linear is connected. When the team completes the issue, the case moves to theanswerstage of the pipeline, the answer is left as an internal note and the owner of the case is notified (once). If Linear does not answer, the escalation stays pending and Lelemon retries. See Escalate a case to your technical team.
5 November 2026: Which cases a member sees, by API
- Members:
PATCH /v2/members/{id}/case-scope(members.updateCaseScope) sets what a member sees:caseScopeisall,unassigned_and_own,assigned, ornullto follow the default of the organization. Same rule as the Team screen, capped by the role of whoever issued the key: it never touches someone with a higher role, and the owner and admins always see all. It needsmembers:manageand it is recorded in the audit log of members (member.scope_changed, withscopeBeforeandscopeAfter). - Members:
members.listreturnscaseScopeandeffectiveCaseScopefor each member. The MCP connector of Lelemon only works for people who see all cases; when it cannot connect someone, the consent screen and the token endpoint now say why (access_denied).
5 November 2026: A stage creates a task when a case does not move
- Stages:
config.noProgressonPOSTandPATCH /v2/pipelines/{id}/stages. When a case stays in the stage forminutes(counted inside the business hours of the pipeline, when it has them), Lelemon creates a reminder of typecallfor the assignee of the case, or forfallbackAssigneeIdwhen the case has no assignee, with yourtitleanddescription, and can add atagto the contact. One task per pass of the case through the stage. If the case leaves the stage or closes, the task closes by itself. See Settings of a stage.
5 November 2026: Triggers without a message
- Triggers:
templateIdis optional. A trigger with onlyonEventopens or moves the case of the contact when the event arrives and sends nothing.POST /v2/contact-eventsanswers202withsentempty,caseActionsandreasonset tonull. A trigger with neithertemplateIdnoronEventis rejected with400, andvariablesis now optional when there is no template. See Message on events.
4 November 2026: Organization settings and company profile
- Organization:
GET,PATCH /v2/organization,GET,PATCH /v2/organization/settingsandGET,PATCH /v2/organization/company-profile. They read and change the business hours, the inactivity closing, presence, branding, the company profile and the name, with the same validation as the dashboard. - Scopes:
organization:read,settings:writeandorganization:write. A key acts with at most the role of whoever issued it, so only a key issued by an owner can useorganization:write.
4 November 2026: Teams by API
- New, teams:
teams.list,teams.retrieve,teams.create,teams.update,teams.deleteandteams.merge, plusteams.members.set,teams.members.removeandteams.pipelines.setto assign members and pipelines. They need the newteams:readandteams:writescopes.teams:writeneeds a key issued by an admin or the owner.
3 November 2026: Keys are managed only from the dashboard
- Breaking, keys:
GET,POST /v2/api-keysandPATCH,DELETE /v2/api-keys/{id}andPOST /v2/api-keys/{id}/rotateare removed, withapiKeys.*in the SDK and the MCP. They answer404. Create, rotate and revoke keys from the dashboard. - Breaking, scopes:
api-keys:writeno longer exists. Keys that carried it lose it.
3 November 2026: Case closed event
- Events:
case.closedfires once when a case changes from open to closed. Its data hascase,reason,status,closedByandclosedAt.closedByissystem,stage,agent,apioruser. It covers the inactivity sweeps, closing stages,end_conversation,POST /v2/cases/{id}/closeand the closes of the dashboard. See React when a case closes.
3 November 2026: Scheduled tasks for agents
- Scheduled tasks:
POST /v2/agents/{id}/schedules,GET /v2/schedules,GET,PATCHandDELETE /v2/schedules/{id}. On each date of a cron, in the timezone you send, the agent gets the goal as an unattended run and writes first by email to a contact, with a file from one of its granted actions if it needs one. Ids aresch_…. They need the new scopesschedules:readandschedules:write. See Scheduled tasks. email_contact: a new tool you grant to the agent. It writes to the contact of the task and takes up to three attachments from HTTP actions already granted to that agent:.csv,.pdf,.xlsxor.txt, up to 5 MB each.- Runs:
Runhasschedule, the id of the task that started it, ornull.GET /v2/runstakesscheduleId. - Events:
schedule.fired,schedule.skippedandschedule.paused. - Errors:
invalid_cron,invalid_timezoneandschedule_limit_reached. - Fire now:
POST /v2/schedules/{id}/firestarts one run right now to try a task. It does not movenextRunAt, it needsschedules:writeand anIdempotency-Key, and it sends a real email. - Email: a first email that names an agent in
onReply.agentIdreuses an open case of the contact only if that case is attended by the same agent. Before, it reused the contact's open case whoever attended it, so the answer went to the other agent.
2 November 2026: Runs no longer show cost
- Breaking,
Run:costUsdandlimits.maxCostUsdare removed from the run object and from therun.*event payloads. Token cost is internal;rounds,limits.maxRoundsandlimits.maxMinutesremain. - Breaking,
POST /v2/agents/{id}/runs:limits.maxCostUsdis no longer accepted. Sending it answers400 unknown_field. To cap a run, uselimits.maxRoundsandlimits.maxMinutes.
2 November 2026: Claude as your team's assistant
- Knowledge search:
POST /v2/knowledge-collections/search(knowledgeCollections.search) returns the passages of your documents that answer a question, with the collection and document of each one. It is the search the agents use. It needsknowledge:readand changes nothing. - Context of a team question:
GET /v2/team-questions/{id}/context(teamQuestions.context) returns the question with the last lines of the conversation and the data of the case. Every sensitive value comes covered. It needsteam-questions:read,conversations:readandcases:read. - Sensitive values covered:
GET /v2/team-questionsandGET /v2/team-questions/{id}(and the answer route's response) now cover every sensitive value of the case inquestion,contextandanswer, as the dashboard does. The value is replaced by[dato oculto]. - MCP: both routes are tools of the MCP server, marked read only. See Use Claude as your team's assistant.
2 November 2026: Usage and budgets count conversations
Usage and budgets now measure conversations, the unit Lelemon bills: a window per case of up to 10 agent turns or 24 hours, whichever comes first. The next turn opens another conversation. The model does not change the count. Token cost is internal and no response shows it.
- Breaking, budgets:
monthlyLimitUsdis nowmonthlyLimitConversations(an integer from 1) inPOST /v2/budgetsandPATCH /v2/budgets/{id}, and in theBudgetobject.spentUsdis nowusedConversations. No budget created before this change is kept: the dollar limits have no equivalent in conversations. Create them again in conversations. - Breaking,
402 budget_exceeded:budget.limitUsdandbudget.spentUsdare nowbudget.limitConversationsandbudget.usedConversations. The error answers only when the message would open a new conversation. A case whose conversation is already open keeps answering. - Breaking, events:
budget.threshold_reachedandbudget.exceededcarrymonthlyLimitConversationsandusedConversationsinstead ofmonthlyLimitUsdandspentUsd. - Usage:
GET /v2/usageaddsconversationstototalsand to the groups by day, agent and subaccount. It counts from 2 November 2026 on; earlier days show zero. The groups by model do not carry it.
1 November 2026: Test mode removed
- Keys: only
lel_live_keys exist.lel_test_keys stop working, andPOST /v2/api-keysno longer takeslivemode. livemode: removed from every object, event and webhook payload.- Test helpers:
POST /v2/test-helpers/whatsapp/inboundand the other/v2/test-helpersroutes are gone. Use a number you connected. - Errors:
test_mode_limitandtest_mode_onlyno longer exist.
1 November 2026: Erasure reaches stored responses and opt-outs hold
- Idempotency: the response stored for an
Idempotency-Keyis erased when the person in it is suppressed. A retry with that key answers409 idempotency_key_reused. - Queues: the WhatsApp history and pipeline job queues are purged when a contact is erased.
- Opt-outs survive erasure: an opt-out keeps a keyed hash of the phone and the email, so a new contact with the same number or address is still opted out.
- One rule for WhatsApp: an opt-out blocks every send to the number, including replies from the team and the test send of a template (
422 contact_opted_out). The dashboard disables the send button and says why.
1 November 2026: Safer inputs
- Nesting limit: a body or a query string with objects or arrays nested more than 32 levels deep answers
400 invalid_requestwithparamset tobodyorquery. It used to answer500 internal_error. - Test send and opt-outs:
POST /v2/whatsapp/templates/{id}/testchecks opt-outs by phone number. A number that belongs to a contact who opted out ofwhatsappanswers422 contact_opted_outand nothing is sent.dryRun=trueanswers the same. - Case attachments:
POST /v2/cases/{id}/attachmentsreads the type from the whole content and compares it with the declaredContent-Type, as/v2/filesdoes. A file that is not of its declared type, or that carries HTML or SVG with scripts, answers400 invalid_requestwithparam: "file".
1 November 2026: Limits that hold under load
- Webhook endpoints: an organization can have up to 16. The next
POST /v2/webhook-endpointsanswers422 webhook_endpoint_limit. See Receive events. - Limits per organization:
POST /v2/actions/{id}/test(10 per minute),POST /v2/data-connectors/{id}/check(20) andPOST /v2/mcp-servers/{id}/discover(20) are counted for the whole organization across all servers, and answer429 rate_limitedwithRetry-After. See Rate limits. - Pipelines and stages: deleting a pipeline or a stage while cases are being opened or moved into it can no longer leave a case in a deleted stage or pipeline, and a stage can no longer point to a stage that was just deleted.
1 November 2026: One MCP server, at api.lelemon.cl/mcp
- Remote MCP with OAuth:
https://api.lelemon.cl/mcpexposes the tools of the v2 API. Paste the URL in Claude, Cursor or ChatGPT, sign in and choose the organization, the permissions and real or test data. There is no API key to copy. See MCP server. - Permissions you grant: a connection lists only the tools its scopes cover, and each call goes through the same rules as a call with an API key. Creating API keys, new actions, approvals, revealing values, webhooks, connectors and the recipient allowlist are never granted through the MCP.
- Connections in the dashboard: Developers lists each connection with its client, permissions and last use, and removes its access at once.
- Security: PKCE
S256, tokens bound to the server withresource(RFC 8707), refresh tokens that rotate, and no token forwarded to another service. Client registration is rate limited, the consent screen shows the host the client returns to, and permissions that change data are confirmed apart. A member can only grant the reads the dashboard lets a member see. - The CRM tools stay:
find_contact,send_messageand the rest keep their names and work on deals. @lelemon-ai/mcp: it stays for environments without a browser (CI, scripts, servers) and only needsLELEMON_API_KEY.
1 November 2026: Pipeline settings and stage configuration
- Pipeline settings:
POST /v2/pipelinesandPATCH /v2/pipelines/{id}takesettings:autoClose,businessHours,waitThresholds,askFor,timezone,stageOnTakeControlandstageOnHandoff. Every pipeline returns them,nullwhen not set. The dashboard shows and changes the same settings. See Pipeline settings. - Stages that close: a stage takes
closes,closingOutcomeandstatusType. A case that arrives at a stage that closes ends and gets the outcome of the stage. - Next stage and transitions:
nextStageIdandtransitionson a stage, with targets in the same pipeline. - Stage config:
configtakesagentMode,followUp,maxDurationSeconds,minDurationSecondsanddelayMinutes. Webhooks, sources and the other keys of the panel are not part of it, and a key that is not documented answers400 unknown_field. - WhatsApp number by stage:
whatsappPhoneNumberIdonPATCH /v2/pipelines/{id}/stages/{stageId}starts the cases of a number in that stage. A number feeds one pipeline only (409 conflict).
1 November 2026: Operate cases from the API
- Tags and fields:
PATCH /v2/cases/{id}takestags(replaces the list of the contact) and writesfieldsof any source, not onlysystem.Caseaddstags,archivedAtandmuted. - Reveal:
POST /v2/cases/{id}/fields/{key}/revealreturns a sensitive field. It needs the new scopecases:reveal, audits the key that revealed it in the same trail the dashboard writes to, never stores the value and answers422 field_not_sensitivefor any other field. In the MCP it is in the hiddenkeysgroup. - Archive:
POST /v2/cases/{id}/archiveand/unarchive, andGET /v2/cases?archived=. - Move:
POST /v2/cases/move-batchmoves up to 100 cases and says why each of the others did not move.POST /v2/cases/{id}/movetakespipelineIdas an alternative tostageId. - Mute and escalate:
POST /v2/cases/{id}/mute,/unmuteand/escalate. Escalating firescase.control_changedwithescalated: true. - Reminders:
/v2/cases/{id}/remindersand/v2/reminders/{id}, withcompleteanddismiss. Ids arerem_…. - Notes:
Noteaddspinned, andPATCH /v2/cases/{id}/notes/{noteId}takespinned. - History of a person: the cases are
GET /v2/cases?contactId=…and the messages of each oneGET /v2/cases/{id}/messages. New:GET /v2/contacts/{id}/eventslists the events reported for the contact. It needstriggers:read, likeGET /v2/contact-events/{id}.
1 November 2026: Contact fields, contact search and companies
- Contact fields:
/v2/contact-fieldsdefines the data every contact can hold (text,textarea,email,phone,url,number,date,booleanorselect).POST,PATCHandPUT /v2/contacts/by-external-ref/{externalRef}takefields, every value is checked against its type, and contacts answerfields. The contact page of the dashboard shows and edits them and the Contacts list filters by them. - Search contacts:
GET /v2/contactstakesq(name, email, phone,externalRefand contact fields, withmatchsaying what matched),pipelineId,hasOpenCases=true,order(activityorname), andfieldKeywithfieldValue. It is the search of the Contacts screen, and addscaseCount,openCaseCountandlastActivityAtto each contact. - Companies:
GET /v2/companiesandGET /v2/companies/{id}withcontacts:read.POST /v2/companies,PATCH /v2/companies/{id}andDELETE /v2/companies/{id}need the new scopecompanies:write, which asks for the same role as the dashboard (owner or admin). Arutalready used by a live company answers409 conflictwithparam: "rut". Deleting a company keeps its contacts and clears theircompanyId. - Company of a contact:
ContactaddscompanyId.POST /v2/contacts,PATCH /v2/contacts/{id},PUT /v2/contacts/by-external-ref/{externalRef}, thecontactofPOST /v2/casesand thecontactofPOST /v2/contact-eventstake it (nullunlinks, except in cases and events) withcontacts:write, and a company that does not exist is a400withparam: "companyId". - Account in the contact page: a contact with an
externalRefshows its account in your active data connector, live, with the connector's permissions and masking.
1 November 2026: Scheduling tools for the agent, delete a budget
- System tools:
check_availability,schedule_meetingandcancel_meetingcan be granted withPUT /v2/agents/{id}/tools/{toolId}. They book on the default agenda, so an agent no longer needs actions of your own to schedule. - Action names:
POST /v2/actionsanswers409when the name is the name of a Lelemon tool (cancel_meeting,send_email...). The agent ran the Lelemon tool instead of your action. If an action with such a name already exists, the agent is offered and runs the Lelemon tool. - Data connector tools: a connector you create, check or delete shows up in the tools of an agent right away. A copilot could answer
Unknown toolfor up to five minutes after a turn had loaded the tools of the organization. The change reaches every API and worker process. - Budgets:
DELETE /v2/budgets/{id}answers204. The dashboard has the same action. - Subaccounts:
fromTemplates.agentstakes ids fromGET /v2/agent-templates.
31 October 2026: Examples in every request body, how a run ends and a typed MCP
- Unknown fields: a body field the route does not document answers
400 unknown_field, andparamnames the first one. It wasinvalid_request. - Idempotency: once a request starts running, its final response is stored whether it is
2xx,4xxor5xx, and a retry with the sameIdempotency-Keygets the same response without repeating the effect. A request rejected before it runs, such as a body that fails validation, leaves the key free. A replayed create does not repeat the secret. See Idempotency. - MCP servers shared with subaccounts: a platform connects a server with
sharedWithSubaccounts: true, or turns it on withPATCH /v2/mcp-servers/{id}. A subaccount lists it withsharedByPlatform: trueand grants its tools, but cannot change it. See Platforms. - Usage:
GET /v2/usageaddscasestototals, and to the groups by day, agent and subaccount: the cases where the agent wrote at least one reply. - Connector in the contract: the
webhookssection ofopenapi.jsondeclares the four requests your connector serves, with the schemas of the format as components (ConnectorManifest,ConnectorAccountSearch,ConnectorAccount,ConnectorView). - Runs: the
completedstatus is gone from the contract. Nothing produced it; a run that finishes iscompleted_unverified. - Contract:
AgentModeland itsfallbackin agent answers now describe the v2 model (model,thinking,effort...). The published contract carried a v1 schema under that name. - Cancel:
POST /v2/runs/{id}/cancelon a run that iswaiting_for_answeranswered500 internal_error. It now endscanceled, withquestionback tonull, and firesrun.canceled. The same applies to the v1 routes. - Runs: the runs guide says how a run ends. The agent ends it by calling its finish action after using at least one tool. An agent that only answers in text ends
stoppedwithstopReason: "no_conclusion"and its answer inresult.partial.rounds,costandtimeare limits;no_conclusionandloopare not. EverystopReasonis now described in the contract and in therun.*events. - Examples: every JSON request body in the contract has a valid
example. Bodies that accept several shapes (agents.create,cases.create,caseMessages.create,whatsapp.messages.create,email.messages.createand others) have one named example per shape inexamples, and each branch of aoneOforanyOfhas its ownexample. Postman and Insomnia import them instead of"<string>". - MCP: each tool whose success answer has a body declares an
outputSchemaand returns the answer asstructuredContent. Calls now wait 50 seconds, under the 60 seconds an MCP client waits by default, so the client receives thetimeouterror with theidempotencyKeyto retry. New error codeinvalid_response.
31 October 2026: Case metrics and action variables in v2
GET /v2/case-metrics: one row per case that changed in a range of up to 31 days, with when it came in, was handed off, was taken and was closed, who closed it (agent,humanorsystem), whether the agent resolved it alone and the seconds with the agent and with a person. It needscases:read, paginates withcursorand reads one subaccount withLelemon-Subaccount. It replacesGET /v1/external/metrics/conversations, and the dashboard shows the same numbers on the home page, to owners and admins.variableson actions:POST /v2/actionsandPATCH /v2/actions/{id}takevariables, the fields Lelemon fills when it calls your endpoint (case.id,contact.phoneor a field of the case), and every read of an action returns them. A variable that cannot be saved answers400 invalid_requestwith theparamthat failed,400 action_variable_in_querywhen it would go in aGETaction, and400 action_variable_needs_authorizationwhencontact.phoneorcontact.whatsapp_idlack the authorization of the destination.authorization.dataSentnames the data in English.- Moving from v1: the conversation metrics are no longer listed as missing in v2.
31 October 2026: Agendas, meetings and team availability
- Scheduling:
GET /v2/scheduling/agendasandGET /v2/scheduling/agendas/{id},GET /v2/scheduling/availability?agendaId=…and the meetings:POST /v2/scheduling/meetings(idempotent, withdryRun),GET /v2/scheduling/meetings,GET /v2/scheduling/meetings/{id},POST …/cancelandPOST …/reschedule. Ids areagd_…andmtg_…. They needscheduling:readandscheduling:write, andscheduling:readnow also reads the meetings, which carry the attendee. Meetings booked by an agent or in the dashboard show up too, and the dashboard lists the ones booked by API in Mi Negocio. See Schedule meetings. - Events:
meeting.scheduled,meeting.rescheduledandmeeting.canceled, for every meeting whoever creates it. - Team availability:
GETandPUT /v2/members/{id}/availability, withstatusavailableorawayandavailableForAssignment. Reading needsmembers:read; setting needs the new scopemembers:write, which only sets availability. The v1 scopesmiembros:readandmiembros:writekeep working on the v1 routes only. - Errors: new codes
slot_not_availableandmeeting_not_active. - Moving from v1: scheduling and team availability leave the list of what v2 does not have yet.
31 October 2026: Runs, jobs an agent does on its own
- Runs:
POST /v2/agents/{id}/runsgives an agent agoalthat it works on outside your request, withlimitsfor rounds, spending and minutes.GET /v2/runs,GET /v2/runs/{id},POST /v2/runs/{id}/cancelandPOST /v2/runs/{id}/answerlist, read, cancel and answer it. Scopesruns:writeandruns:read.POSTtakesIdempotency-KeyanddryRun. - No signature: the run works for the
actoryour key declares, recorded as declared by the key and sent signed by Lelemon to every action and MCP server. Withoutactorit works as the key. There is no shared secret and nopedidoPor. A role above the key answers403 actor_role_above_key. - Statuses:
running,waiting_for_answer,completed_unverified(the agent says it finished and nobody checked),stopped(withstopReason),failedandcanceled. - Events:
run.started,run.waiting_for_answer,run.completed,run.stopped,run.failedandrun.canceled. - Errors: new codes
run_finishedandrun_not_waiting. - Dashboard: the runs of an agent show under it, in Activity, and a run that asks something is answered there.
- Migration: runs leave the list of what v2 does not have yet.
30 October 2026: Talk to a copilot, ordered stages and truthful statuses
- Copilot cases:
POST /v2/casesaccepts theagentIdof a copilot (audience: "internal") with apipelineIdorstageIdfor the case to live in. The copilot answers the messages written withauthor: "contact"and the case showsagentIdof the copilot, fires the same events and shows in the dashboard. A copilot cannot open email cases or work a stage, and activating it does not ask for a stage:readinessonly checks theapichannel. - Stages:
GET /v2/pipelines/{id}/stageslists the stages in funnel order, fromposition0 up, and its pages follow that order. - MCP servers: a successful discovery, including the one
PATCH /v2/mcp-servers/{id}runs after new credentials, puts the server back toconnected. - Data connectors:
422 data_connector_invalid_responsenames the failing paths and the rule each one breaks in itsdetail. The check endpoint reads the manifest only. - Docs: the key can be created in the dashboard or by API, and
GET /v2/actions/authorizationis listed as available in v2.
30 October 2026: One naming, a stricter contract and SDKs for external developers
- Names: every single-object read is
retrieve(budgets.retrieve,usage.retrieve,recipientAllowlist.retrieve,email.domains.retrieve). WhatsApp routes arewhatsapp.connections.*andwhatsapp.phoneNumbers.*(withcommerceSettings.retrieveandupdate), email domains areemail.domains.*,knowledgeCollections.documents.deleteandsubaccounts.apiKeys.create. The paths did not change. - Fields: the key of
POST /v2/subaccounts/{id}/api-keysis insecret, like every other secret the API returns once. The id of an agent tool isid, nottoolId. - Contract: every operation declares the scopes it needs (
x-required-scopes, also as the scopes of its security requirement), theIdempotency-Keyon everyPOSTthat uses it and theLelemon-Subaccountheader.dryRunanswers declaredryRun. Recipients, case messages, interactive messages, agent bodies and approval conditions areoneOforanyOfunions, and a body with required content is required. - Errors in the headers: a
Lelemon-Subaccountthat is not asub_…id answers400withparam: Lelemon-Subaccount, and404only when the id is well formed and is not one of your subaccounts. A missing requiredIdempotency-Keyanswers400before the subaccount is looked up, and a method that a fixed route does not have (for examplePATCH /v2/actions/authorization) answers405. Every operation documents the400,404and409its headers can cause. - Webhooks:
Lelemon-Delivery-Idis thewhd_id of the attempt. agents.activateacceptsdryRun.- Errors: every code has a concrete cause, and the generic ones have a
fix. - TypeScript SDK and MCP server: the SDK ships ESM and CommonJS, runs on Web Crypto, throws one class per error family and takes one
optionsobject (query,idempotencyKey,subaccount,signal). The MCP server filters its tools by the scopes of the key and returns the idempotency key it used. Neither is on npm yet.
30 October 2026: Rules for approvals, and automated decisions with any mode
- Rules:
approval.modeacceptsrules, an ordered list. The first rule whosewhenapplies decides, with the effectallow,require_approval(its own approvers and deadlines) orreject(a hard cap that never asks). Policies saved before keep working unchanged. A platform floor still applies on top of the rules. - Roles include the roles above them: an approval assigned to
role: adminis seen and decided by owners too. - Automated decisions (Ley 21.719, art. 8 bis):
automatedDecisionno longer requiresmode: always. Calls that nobody approved, or that a rule rejected, are recorded and read withGET /v2/automated-decisionsandGET /v2/automated-decisions/{id}.POST /v2/automated-decisions/{id}/request-reviewandPOST /v2/approvals/{id}/request-reviewstore what the person said (reviewReason). New eventautomated_decision.review_requested, andreasonCodecan bepolicy_rule(withruleIndex) orpolicy_not_required. approvewithdryRunanswersstatus: "preview"and the decision it would record, instead ofstatus: "executed"with no decision.- Erasing a contact cancels its pending approvals (event
approval.canceled) and discards its open team questions, which before stayedpendingwith their arguments emptied. actions.teston anoPersistaction no longer leaves the input or the answer in the request log or in the idempotency store.- What the agent is told: a call that waits says
pending_approval,approved_runningorrejected_by_policy, and the action did not run. The state shows in theoutputof the step inGET /v2/cases/{id}/turns. - Errors:
agent_not_readyandunprocessablecarry afix; new codereview_not_available.
30 October 2026: Files for messages, campaigns and templates
POST /v2/files: upload a file once (multipart, withpurposemessage_media,campaign_mediaortemplate_header) and get afil_…id.GET /v2/files,GET /v2/files/{id}andDELETE /v2/files/{id}list, read and delete. New scopesfiles:readandfiles:write.?dryRun=truevalidates the file and stores nothing.- Use it as
fileId: indocument,components.headerImage,components.headerVideoand the cards of a media carousel, in messages and campaigns, and asexampleFileIdin theheaderand the carousel cards of a template. Lelemon uploads the file to WhatsApp by media id (messages) or resumable upload (template samples). A URL keeps working. - Limits per purpose are the ones in Meta's media table, and the type is read from the content. A wrong type or content is
400 invalid_requestwithparam: "file", a file too big is413 payload_too_large, and a file used in the wrong place names the field. Deleting a file that a campaign that has not finished uses answers409 resource_in_use. - Person data: a
message_mediafile uploaded withcontactIdcan only be sent to that contact and is erased with them. The files of a case (/v2/cases/{id}/attachments) are a different thing and stay as they were.
30 October 2026: Approvals and team questions
- Approvals:
PUT /v2/agents/{id}/tools/{toolId}accepts anapprovalpolicy. A call that meets it becomes an approval that waits; onlyPOST /v2/approvals/{id}/approveruns it.GET /v2/approvals,rejectandrequest-reviewcomplete the resource, with the scopesapprovals:readandapprovals:write. - Who decides: a member, or an API key that the policy names. The key that proposed the action never decides it. Every decision needs a reason.
- Limits: a condition on the arguments, an accumulated limit per contact and period, an expiry and an escalation. Events
approval.requested,approval.decided,approval.expired,approval.escalatedandapproval.review_requested. - Team questions: the
ask_teamsystem tool,GET /v2/team-questionsandPOST /v2/team-questions/{id}/answer, with the scopesteam-questions:readandteam-questions:write. Eventsteam_question.createdandteam_question.answered. The dashboard shows both queues and edits the policy of each tool. A platform can set an approval floor on a shared action withPUT /v2/actions/{id}/approval-floor. See Approve agent actions.
30 October 2026: Every WhatsApp format available in Chile
- New interactive types:
cta_url,flow,location_request,contact_request,callandcarouselininteractiveofPOST /v2/cases/{id}/messages.buttonsandcta_urltakeheaderMedia. Limits and fields are in the WhatsApp guide. - What the person sends back: a shared location, the answer of a Flow and a phone shared for a
contact_requestarrive as a message of the case (location,flowResponse,contact) and asmessage.receivedwithtypelocation,flow_responseorcontact. The event carries no personal data. - Failures: a message with
status: "failed"haserror: { code, message }. - Catalog and commerce:
catalogIdon phone numbers, andGETandPATCH /v2/whatsapp/phone-numbers/{id}/commerce-settings(isCartEnabled,isCatalogVisible). A message that uses a catalog answers422 catalog_not_connectedwhen the number has no catalog or the id differs. - Templates: image and video headers (
components.headerImage,components.headerVideo), a variable at the end of a link button,catalog,mpmandflowbuttons, andcarousel(media and product cards). The sends takecomponents; campaigns andPOST /v2/whatsapp/templates/{id}/testtoo. - System tools:
send_carousel,send_cta_url,send_flowandrequest_locationcan be granted withPUT /v2/agents/{id}/tools/{toolId}. - Not available in Chile:
order_details,order_statusand payment inside WhatsApp (Kapso Pix is only for Brazil), and the address message (India only). Payment stays an external link: usecta_url.
30 October 2026: A contract with nothing pending
- Nothing deprecated: the
providerfield and the AWS model ids are gone, strict bodies apply to every key. An unknown field answers400 unknown_field, a model that is not inGET /v2/modelsanswers422 model_not_supported. dryRunon everything that sends, charges or configures:whatsapp.messages.create,email.messages.create,caseMessages.create,contactEvents.create,whatsapp.templates.test,apiKeys.rotate,campaigns.createandupdate,actions.createandupdate,triggers.createandupdate. It runs the same checks as the real call and answers200withdryRun: true, the object as it would be created and an id that is not saved. A route that sends messages or costs money must accept it: the contract tests fail otherwise.estimatedCostof a campaign is nevernull: it is the list price from the WhatsApp Business Platform rate card published by Meta (https://developers.facebook.com/docs/whatsapp/pricing), by the category of the template and the country of each phone, witheffectiveFrom. Utility and authentication volume tiers are not applied, so the real charge can be lower.- Errors that say what to do:
agent_not_readynames what the agent lacks,thinking_not_supportedreplacesmodel_not_supportedwhen a model cannot turn thinking off and points atthinking, and a trigger or campaign variable written as{{contact.name}}is a400that shows the right form,contact.name. - Data connectors:
http://localhostis accepted while developing, under the same rule as webhook endpoints. - OpenAPI 3.1 with
webhooks:GET /v2/openapi.jsonis OpenAPI 3.1. Each of the 27 event types is a webhook with its payload (theEventenvelope plus thedataof that type) and thewebhook-signaturescheme (Lelemon-Signature).nullableis now a JSON Schema type list (["string", "null"]), so the TypeScript SDK types of fields that can benullincludenull.
30 October 2026: Copilots and MCP from the API
- Run identity of an MCP server:
GET,POSTandDELETE /v2/mcp-servers/{id}/run-identityturn on, rotate and read the signed context. The secret comes once.?dryRun=truechecks it. Theorgandsrvclaims of the JWT are public ids (org_…,mcp_…), not UUIDs. The TypeScript SDK addsverifyMcpAssertion. - Copilots:
POST /v2/agentstakesaudience: "internal"with the new scopeagents:internal. You manage and use it like any agent, andGET /v2/agents/{id}/toolslists thedct_tools of your data connector. A turn that read data of the connector gets no tool that writes or calls another system. The assistant of the owner stays out of the API. - Connector documents:
POST /v2/data-connectors/format/validatechecks a manifest, card, search answer or view page and names the failing paths. - MCP server status:
GET /v2/mcp-servers/{id}showserrorandlastErrorwhen the last tool call failed, not only the last discovery. A 401 or 403 is told apart by its status, andmcp_server.failedfires on every move to rejected credentials. - Effects: revealing a value and getting the link of an account action are
write, notread, because they return personal data and write an audit row. - Budget:
402 budget_exceededcarriesbudget(id,scope,subjectId,limitUsd,spentUsd,resetsAt) andRetry-After. Limits under one cent no longer readUS$0.00. - Presence:
GETandPUT /v2/presence/settingsturnpresenceEnabledon or off. - Actions:
Actionreturns theauthorizationthat is in force, ornull. - Errors: a problem in a nested body names the whole path in
param, a missing field says it is missing, afixwithsetnames the field, and a subaccount key with bad scopes namesscopesorauthorName. - Cases and campaigns:
POST /v2/casestakescontactto find or create the person byexternalRefor phone.schedule.ataccepts"now". dryRun: also on rotating the signing secret of webhook endpoints, actions and connectors, and on launching and resuming a campaign.- Usage:
groupBy=subaccountcounts the platform itself as the group withsubaccountId: null. - Scopes:
miembros:readandmiembros:writeare the availability of one person;members:readlists the team. Their descriptions say so. - Docs: the SDK page no longer says that the MCP server does not exist.
30 October 2026: Retries, events and tools
- Idempotency of tool calls: the
Idempotency-Keythat Lelemon sends to an action or an MCP server is now one per operation (turn, tool and arguments). If the model retries the same call, your service receives the same key and can answer once. Before, each retry came with another key. - Agents created through the API: a contact who writes to the WhatsApp number of an agent that you put in a pipeline stage with
agentIdgets an answer. Before, the turn failed withAgent not found. A stage now names its agent only throughagentId. - Events of a subaccount: every event of a subaccount (
message.*,case.*,budget.*and the rest) reaches the endpoints withscope: customersof its platform, withcustomerId. Before, only some did. - System tools:
send_buttons,send_listandsend_productscan be granted withPUT /v2/agents/{id}/tools/{toolId}. POST /v2/actions/{id}/test: signs the request like a turn.GET /v2/cases/{id}/turns: system tools show their public name, such assave_case_data.case.escalated:contact.externalRefis included.budget.exceeded: fires when a budget with enforcementstopruns out, not only when the next message is refused.
30 October 2026: Public model ids
llmConfig.model: takes a public id fromGET /v2/models, such asanthropic/claude-sonnet-4.6,deepseek/deepseek-v3.2oramazon/nova-2-lite. It is the same inllmConfig.fallback.provideris no longer needed: it comes from the id.GET /v2/models: returnsid,name,capabilities(thinkingCanBeOffandcontextWindow) anddeprecated. Theproviderfield is gone andidis no longer an AWS id.- Responses: agents,
GET /v2/usage,GET /v2/cases/{id}/turnsand thecase.turn_completedevent return the public id.llmConfigno longer hasprovider. - Only public ids: the
providerfield and the AWS ids (us.anthropic.claude-sonnet-4-6,global.anthropic.claude-sonnet-5-5) are not accepted. See Versioning.
30 October 2026: docs
- New guides: Track usage and cap spending, Show who is online and Keep tool data out of storage.
- Objects you can open: the guides show the fields of Case, Contact, Budget and more, read from the contract.
- Diagrams: the main flows are drawn step by step. Each page says what you will do and what you need.
- Errors: every error page has the cause and how to fix it.
30 October 2026: Tools inside subaccounts
- Platform key with
Lelemon-Subaccount:POST /v2/actionsandPOST /v2/mcp-serverscreate the tool inside the subaccount, checked against the sites of your key. Before, they answered403 action_origin_not_allowed. - Subaccount keys: accept
actions:writeandallowedActionOrigins, a subset of the sites of the platform key. A rejected request names the parameter. - Shared tools:
sharedWithSubaccountson an action lets the agents of your subaccounts use it. Calls carryLelemon-Subaccount-Id. See Run Lelemon for your customers.
30 October 2026: Hand off to a person
- System tools:
PUT /v2/agents/{id}/tools/transfer_to_humanand.../save_case_datalet an agent hand a case to a person and write case fields.GET /v2/agents/{id}/toolslists them withkind: systemand theirconfig. - Handoff: the stage, the business hours and the farewell are set on the grant. The farewell is written by the tool. A reply that promises a handoff on a case that was not handed over is corrected once and, if it persists, the case is handed over. See Actions and MCP in v2.
29 October 2026: API v2
Version 2 of the API is available at https://api.lelemon.cl/v2. Its API version for webhooks is 2026-10-29.
- New resources: subaccounts, agents and agent versions, actions, MCP servers, skills, knowledge collections, pipelines with stages, fields and handoff rules, contacts, cases with messages, notes and attachments, WhatsApp connections, numbers, templates and messages, email domains and messages, contact events, triggers, campaigns, opt-outs, the recipient allowlist, webhook endpoints, events and API keys.
- Conventions: prefixed ids, cursor lists, RFC 9457 errors with stable codes,
Idempotency-Keyon everyPOST, and aRequest-Idon every response. - Platforms: subaccounts with the
Lelemon-Subaccountheader, and webhook endpoints withscope: customers. - Email: cases can run over email, with verified sender domains and threaded replies.
- Webhooks: signed deliveries with
Lelemon-Signature, retries for up to 72 hours and a catalog of events. - Contract:
GET /v2/openapi.jsonis public and generated from the code. - TypeScript SDK: generated from the contract. Not published yet.
- Docs: this site, with
llms.txt,llms-full.txtand a Markdown version of every page.
29 October 2026: Built for agents
fixon errors: when a code has a known remedy, the error carriesfixwith anaction(set,remove,retry,callorstop). See Errors.?dryRun=true: validates and answers what would happen without saving or sending anything, and does not use theIdempotency-Key.PUT /v2/recipient-allowlistaccepts it first. A route that does not accept it answers400.x-lelemon-effect: every operation in the contract declaresread,write,destructiveormoney.- MCP server for the API: generated from the contract, with annotations taken from the effect. It does not offer approvals, API keys or erasure by default. See Actions and MCP in v2.
- Strict bodies: unknown body fields are rejected with
400 unknown_field, andparamnames the field.metadatais not affected, and neither are responses or events. See Versioning. - Request size: a body over 1 MB answers
413 payload_too_large. - Docs: v1 guides moved from
/guias/to/legacy/guides/; the old addresses redirect.
30 October 2026: the context of the turn in actions and MCP servers
- Actions: every call carries
Lelemon-Case-Id,Lelemon-Contact-Id,Lelemon-Contact-External-Ref,Lelemon-Subaccount-Id, the actor and anIdempotency-Key, signed inLelemon-Signature. Verify it withverifyRequestof the SDK. TheLelemon-prefix is now reserved. See Actions and MCP in v2. - Secret:
GET /v2/actions/{id}/signing-secretandPOST /v2/actions/signing-secret/rotate. - Actor:
POST /v2/cases/{id}/messagesacceptsactorwithauthor: contact. - MCP: the context travels in the claims of the run identity and in
_meta, also outside runs and when an approval resumes a call.
30 October 2026: events that open cases, and cadences
- Triggers:
onEventopens or moves the case when the event arrives, andcadencerepeats the template up to 5 times until the contact replies, opts out, or the case changes stage or closes. See Message on events. - Contact events: the response carries
caseActions, and two new reasons:cadence_activeandoutside_window. - Webhooks: new event
trigger.attempted.
30 October 2026: erasure
- Erase a contact:
DELETE /v2/contacts/{id}now erases the contact, its cases, messages, files and logs, and answers202with a suppression. Before, it only hid the contact. UsedryRun=trueto preview,closeOpenCases=trueto include open cases andlegalHold=trueto record a request you must keep. - Follow the job:
GET /v2/suppressions/{id}. - Redact a message:
POST /v2/cases/{id}/messages/{messageId}/redact. - Events:
contact.suppressedandmessage.redacted, with ids only.
30 October 2026: interactive WhatsApp
- Buttons, lists and products:
POST /v2/cases/{id}/messagestakesinteractivewithtypebuttons,list,product,product_listorcatalog. See Send buttons, lists and products. - Template buttons:
POST /v2/whatsapp/templatestakesbuttonsof typequick_replyandurl. They were ignored before; now a template that cannot be built with them answers400 invalid_requestwithparam: buttons. - What the person sends back: a tap on a button or a list row arrives as a message with
reply: { id, title }, and a cart from the WhatsApp catalog as a message withorder.message.receivedcarriestype,replyandorder. - New error:
422 interactive_unsupported_channel, when the case is not on WhatsApp. - Agents: the tools
send_buttons,send_listandsend_products.
2 November 2026: v1 deprecated
v1 (/v1/external) keeps working. Its responses carry Deprecation and a Link to Moving from v1. A Sunset header will appear when a shutdown date is set.