Lelemon
  • Get started
  • Use cases
  • Guides
  • API basics
  • Webhooks
  • SDK, CLI and MCP
  • API reference
  • Changelog
  • v1 (legacy)
Configure your account
    AgentsPipelinesKnowledgeContactsActions and MCP in v2Approve agent actionsUse Claude as your team's assistantConnect your back officeAPI keys
Talk to people
Run and protect
powered by Zudoku
Configure your account

Pipelines

You will

Model the path a conversation follows: stages, the data it carries, where it goes next and how it ends.

You need

  • A key with pipelines:write (pipelines:read to read)
  • cases:write to move and close cases

A pipeline is the path a conversation, called a case, follows. It has stages in order, fields that hold the data of the case, routing rules that send a case to another pipeline, settings such as business hours and automatic close, and quick replies your team sends from the inbox. A case lives in one stage at a time, and the agent linked to that stage works it.

The examples use this client:

Code
import { Lelemon } from '@lelemon-ai/sdk'; const lelemon = new Lelemon({ apiKey: process.env.LELEMON_API_KEY });

Create a pipeline

Send stages to create them in the same call, in order. The entry stage is the one marked entry, or the first. Link an agent to a stage with agentId. The pipeline is created active.

Expected: 201 with status: "active" and stages holding the stage ids in order. The pipeline is this object:

Pipelineobject, 10 fields
  • objectenumrequired

    pipeline

  • idstringrequired

    Example ppl_02y0e5MANqacVbmtn1YyeJ

  • namestringrequired

    Example Orders

  • descriptionstring or nullrequired
  • statusenumrequired

    draftactivepausedarchived

  • stagesstring[]required

    The ids of its stages, in order.

    Example ["stg_N3wX2mRw0TqS9mYp3LkQ8d"]

  • quickRepliesQuickReply[]required
    QuickReply2 fields
    • shortcutstringrequired

      1 to 30 lowercase letters, numbers, hyphens or underscores. Unique in the pipeline.

      Example hours

    • textstringrequired

      Up to 4096 characters.

      Example We are open from 12:00 to 24:00.

  • settingsPipelineSettingsResponserequired
    PipelineSettingsResponse7 fields
    • timezonestring or nullrequired
    • askForenumrequired

      one_at_a_timein_order

    • autoCloseAutoClose or nullrequired
      AutoClose6 fields
      • enabledbooleanrequired

        Turns the automatic close on or off.

      • inactivityMinutesintegerrequired

        Minutes of silence before the case closes, from 5 to 525600. Counted inside the business hours when the pipeline has them.

        Example 120

      • messagestring or nulloptional

        Farewell sent when the case closes, up to 1000 characters. It needs inactivityMinutes under 1440, because after 24 hours the WhatsApp window is closed.

      • closeStageIdstring or nulloptional

        The stage where the case is left when it closes. A stage of this pipeline.

        Example stg_02y0e5MANqacVbmtn1YyeJ

      • includeTakenbooleanoptional

        Also close the chats a person has taken over.

      • reopenWindowHoursintegeroptional

        Hours after the close when a new message reopens the case, from 0 to 720. 24 when omitted.

    • businessHoursPipelineBusinessHours or nullrequired
      PipelineBusinessHours3 fields
      • timezonestringoptional

        IANA time zone. Santiago when omitted.

        Example America/Santiago

      • daysPipelineBusinessDaysoptional

        Ranges per weekday. A day that is not here is closed. Without days the pipeline attends 24/7.

        PipelineBusinessDays7 fields
        • monTimeRange[]optional

          Ranges on Monday. An empty list closes the day.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

        • tueTimeRange[]optional

          Ranges on Tuesday.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

        • wedTimeRange[]optional

          Ranges on Wednesday.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

        • thuTimeRange[]optional

          Ranges on Thursday.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

        • friTimeRange[]optional

          Ranges on Friday.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

        • satTimeRange[]optional

          Ranges on Saturday.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

        • sunTimeRange[]optional

          Ranges on Sunday.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

      • holidaysHoliday[]optional
        Holiday2 fields
        • datestringrequired

          YYYY-MM-DD.

          Example 2026-12-25

        • rangesTimeRange[]optional

          Ranges that replace the ones of that weekday. Without ranges the day is closed.

          TimeRange2 fields
          • fromstringrequired

            HH:MM, 00:00 to 23:59.

            Example 09:00

          • tostringrequired

            HH:MM, after from. 24:00 is the end of the day.

            Example 18:00

    • waitThresholdsWaitThresholds or nullrequired
      WaitThresholds2 fields
      • yellowMinutesnumberoptional

        Minutes without an answer before the wait turns yellow.

        Example 10

      • redMinutesnumberoptional

        Minutes without an answer before the wait turns red. Greater than yellowMinutes.

        Example 30

    • stageOnTakeControlstring or nullrequired
    • stageOnHandoffstring or nullrequired
  • createdAtstring (date-time)required
  • updatedAtstring (date-time)required

Stages

A stage is a step of the path. It has a name, a position, an optional agentId and the requiredFields a case needs before it can enter, and it can close the conversation, name the stage that follows and carry its own settings. List them in funnel order with GET /v2/pipelines/{id}/stages.

The entry stage

Cases enter a pipeline through its entry stage, so the agent that answers new conversations belongs there. Exactly one stage is the entry. Mark another one with entry: true and the previous one stops being the entry. You cannot unmark the entry stage, and you cannot delete it: make another stage the entry first.

Add, order and change stages

position is the place in the funnel, starting at 0. Creating or moving a stage to a position shifts the others.

DELETE /v2/pipelines/{id}/stages/{stageId} answers 409 resource_in_use while cases are in the stage (move or close them first) and 409 conflict for the entry stage.

Stage kinds

A stage has no kind in the API. Its role comes from how you use it:

RoleHow you make it
Entryentry: true
Worked by an agentagentId set
Worked by a personNo agentId. Your team answers the cases here
HandoffThe stage you name in config.stageId when you grant transfer_to_human to an agent
GaterequiredFields set: a case cannot enter without those fields
Closingcloses: true: a case that arrives there ends. See Stages that close

Stages that close

Mark a stage with closes: true and a case that arrives there ends: it is closed, and the next message from the person starts a new case. Give the stage a closingOutcome of up to 50 characters, such as Resolved, and that text is written in the case as its outcome. A stage with statusType: "done" closes too. statusType says what the stage means on the board: todo, in_progress or done; null leaves it without one.

You can also close a case yourself, wherever it is, with POST /v2/cases/{id}/close. See Move and close cases.

The next stage and transitions

nextStageId is the stage that follows when no transition holds, and transitions lists where a case goes from this stage. Each transition has a targetStageId, a priority (lower numbers are tried first) and conditions that must all hold. A condition compares a field path with a value using operator: eq, neq, gt, gte, lt, lte, contains, exists or in. Every target must be a stage of the same pipeline, or the call answers 400 invalid_request with param naming it. transitions replaces the whole list; nextStageId: null removes the next stage.

Code
await lelemon.pipelines.stages.update(pipeline.id, quoteSent!, { nextStageId: visitBooked!, transitions: [ { targetStageId: lost!, priority: 0, conditions: [{ field: 'data.budget', operator: 'lt', value: 100 }], }, ], });

Settings of a stage

config holds the settings of a stage. Only the keys you send change, and null removes a key.

KeyUse
agentModeWhen the agent answers: always, paused (never) or outside_business_hours (only outside the business hours of the organization)
followUpMessages for a person who went silent: enabled, delays (minutes of silence before each one), maxAttempts, templateSequence (reengagement, reminder, last_chance, breakup, demo_reminder or no_show, in order), and optionally allowTemplates and maxTemplates (1 to 5). Templates sent after the 24-hour window cost money, so allowTemplates is false unless you turn it on. It replaces the whole block
maxDurationSeconds, minDurationSecondsThe longest and the shortest duration of the stage, in seconds
delayMinutesMinutes a case waits in the stage before it moves on
noProgressA task for your team when a case stays too long in the stage: minutes (counted inside the business hours of the pipeline, when it has them), title, and optionally description, fallbackAssigneeId (the member who gets the task when the case has no assignee) and tag (added to the contact). It creates a reminder of type call, one per pass of the case through the stage, and closes it by itself when the case leaves the stage or closes. A case with no assignee and no fallbackAssigneeId gets no task. It replaces the whole block
attentionRoleThe part the stage plays in the attention queue: escalation (cases here wait for the technical team and show as waiting for a reply to whoever escalated them) or answer (cases here came back with an answer and the customer still needs a reply; the owner of the case gets a notification when one enters). null removes it. Read the queue of a member with GET /v2/case-queue
Code
await lelemon.pipelines.stages.update(pipeline.id, quoteSent!, { config: { agentMode: 'outside_business_hours', followUp: { enabled: true, delays: [240, 1440], maxAttempts: 2, templateSequence: ['reengagement', 'breakup'], }, }, });

A key that is not in the table answers 400 unknown_field.

Escalate a case to your technical team

A case that your agents cannot solve can become an issue in your Linear, and the answer of the team comes back to the case. Connect Linear once per organization, mark the stage where those cases wait, and say which stage receives the answer.

  1. Connect Linear. PUT /v2/integrations/linear (linear.connect) with a Linear personal API key and the key or id of the team that receives the issues (and optionally a project). Lelemon checks them with Linear, keeps the key encrypted and never returns it. It needs the linear:write scope, which belongs to admins. The answer carries webhook.url.
  2. Register the webhook in Linear. In Linear, Settings, API, Webhooks, create a webhook with that URL, the Issues resource and the team. Copy the signing secret Linear shows and send it with PATCH /v2/integrations/linear as webhookSecret. Until you do, Lelemon rejects every notification (webhook.secretConfigured says whether it is saved).
  3. Mark the stages. Set config.attentionRole to escalation on the stage where those cases wait and to answer on the stage that receives the answer. They are the same marks the attention queue uses, so there is nothing else to configure.

When a case enters the escalation stage, Lelemon creates one issue with the contact, the pipeline, the last messages (sensitive values covered) and the link to the case, and saves the link in the case. A case that already has an open issue never gets a second one. If Linear does not answer, the escalation stays pending and Lelemon keeps trying every minute with growing waits. When the team completes the issue, Lelemon reads the last comment of the team, moves the case to the answer stage of the pipeline if it is still in the stage where it waited, and leaves the answer as an internal note. Entering the answer stage notifies the owner of the case as always; when the case ends elsewhere or has no owner, Lelemon notifies the owner or the admins itself. If the team cancels the issue, the case stays where it was with a note.

To escalate a case that is not in an escalation stage, call POST /v2/cases/{id}/escalate-to-team (cases.escalateToTeam) with an optional answerStageId (the answer stage of the pipeline by default). GET /v2/cases/{id}/team-escalations lists the escalations of a case with their issue, status and answer. DELETE /v2/integrations/linear disconnects.

Code
await lelemon.linear.connect({ apiKey: process.env.LINEAR_API_KEY!, team: 'SUP' }); await lelemon.pipelines.stages.update(pipeline.id, quoteSent!, { config: { attentionRole: 'escalation' }, });

Start the cases of a WhatsApp number in a stage

whatsappPhoneNumberId is the id of a WhatsApp number of the organization, from GET /v2/whatsapp/phone-numbers. A message that arrives at that number opens its case in this stage and the pipeline of the stage works it. Linking an agent to a number with PATCH /v2/whatsapp/phone-numbers/{id} does not let you choose: Lelemon uses the entry stage of your oldest pipeline that has no number yet, or creates a pipeline. Use whatsappPhoneNumberId to choose the stage yourself. A number feeds one pipeline only: linking it to a stage of another pipeline answers 409 conflict, and moving it to another stage of the same pipeline is fine. Send null to release it. Disconnecting the number releases it too.

Link an agent to a stage

An agent works the cases of the stages it is linked to. Send agentId to link one and null to unlink.

The agent must be linked to the entry stage to be reachable; activation reports no_stage or not_entry_stage otherwise.

Require fields before a stage

requiredFields lists the keys of fields a case needs before it can enter the stage. Moving a case there without them answers 422 required_fields_missing, with param naming the missing field. The list replaces the previous one on every update.

Code
await lelemon.pipelines.stages.update(pipeline.id, visitBooked!, { requiredFields: ['address', 'visit_date'], });

Fields

A field holds a piece of data of the case. Create the fields before the agents that fill them.

PropertyUse
keyRequired. Letters, numbers and underscores, starting with a letter, up to 64. Fixed once created
typeRequired. text, email, phone, url, textarea, file or select. Fixed once created
labelWhat people see. Defaults to the key
requiredWhether the field must be filled
sourceWho fills it: team, channel, system or agent. Default team
instructionWhat the agent should ask or look for. Up to 1,000 characters
sensitiveHides the value from the agent and from webhooks
optionsFor select: a list of { value, label }. The label defaults to the value. Up to 80 characters each
dependsOnThe key of another select. The options of this field then depend on the value of that one

A select can depend on another select. Give each option whenParent: the values of the parent for which the option is offered.

Expected: 201 with the field. A key that breaks the format answers 400 invalid_request with param: "key".

  • Who fills it. The agent fills fields with source: "agent" through its save_case_data tool, which refuses sensitive fields. Your team or your system fills the others, with PATCH /v2/cases/{id} and { "fields": { ... } }.
  • Update. PATCH /v2/pipelines/{id}/fields/{fieldId} changes the label, required, source, instruction, sensitive and dependsOn. options replaces the list and cases keep the values they already have.
  • Delete. DELETE /v2/pipelines/{id}/fields/{fieldId} answers 409 resource_in_use while another field depends on it. The field stops being required in the stages that asked for it.
Code
const fields = await lelemon.pipelines.fields.list(pipeline.id); await lelemon.pipelines.fields.update(pipeline.id, service.id, { label: 'Installation' }); await lelemon.cases.update('cse_...', { fields: { service: 'solar', system_size: '5kw' } });

Routing rules

A routing rule sends a case to another pipeline when it reaches a stage. With mode: "create" a new case opens in the other pipeline and the first one stays. With mode: "move" the case itself moves. toStageId is the stage of the destination; leave it out for its entry stage.

GET /v2/pipelines/{id}/routing-rules lists the rules in the order they are evaluated. PATCH changes toStageId, mode and enabled; it answers 422 when the values do not form a valid rule. DELETE removes a rule: cases already routed stay where they are, and new cases stop matching it.

Pipeline settings

settings goes in POST /v2/pipelines and PATCH /v2/pipelines/{id}, and every read of a pipeline returns it with all its keys, null when a setting is not set. Only the settings you send change. autoClose, businessHours and waitThresholds replace their whole block, and null removes a setting.

SettingUse
timezoneIANA time zone of the scheduled work of the pipeline, such as America/Santiago
askForHow the agent asks for the fields it fills: one_at_a_time as the conversation goes (the default) or in_order following the order of the fields
autoCloseCloses the cases that go silent: enabled, inactivityMinutes (5 to 525,600), an optional farewell message, closeStageId, includeTaken to close also the chats a person took over, and reopenWindowHours (0 to 720, 24 by default)
businessHoursWhen the pipeline attends: an optional timezone, days with mon to sun (each a list of { from, to } as HH:MM, where 24:00 ends the day) and holidays, each a date with optional ranges that replace the ones of that weekday
waitThresholdsThe minutes without an answer after which the wait of a case turns yellow (yellowMinutes, 10 by default) and red (redMinutes, 30 by default)
stageOnTakeControlThe stage a case moves to when a person takes control
stageOnHandoffThe stage a case moves to when the agent hands it to a person

Without businessHours the pipeline attends all day and the minutes are counted by the clock. With them, the wait colors, autoClose and the warning before it count only the minutes inside the hours. A day that is not in days is closed; without days the pipeline attends 24/7. The ranges of a day cannot overlap.

A farewell message needs inactivityMinutes under 1,440, because after 24 hours the WhatsApp window is closed and the message cannot go out.

closeStageId, stageOnTakeControl and stageOnHandoff take the id of a stage of the pipeline, so they cannot be set on creation: create the pipeline with its stages and then send them with PATCH. Deleting a stage that a setting names sets that setting to null. The dashboard shows and changes the same settings.

A setting that breaks a rule answers 400 invalid_request, and param names it, for example settings.autoClose or settings.stageOnHandoff.

Quick replies

quickReplies is a list of { shortcut, text } that your team sends from the inbox. The shortcut is 1 to 30 lowercase letters, numbers, hyphens or underscores, without a slash; the text has up to 4,096 characters. PATCH /v2/pipelines/{id} with quickReplies replaces the whole list, so send every reply you want to keep.

Code
await lelemon.pipelines.update(pipeline.id, { quickReplies: [ { shortcut: 'hours', text: 'We visit Monday to Saturday, from 9:00 to 18:00.' }, { shortcut: 'quote', text: 'Send us the address and a photo of the place and we reply with a quote today.' }, ], });

Move and close cases

POST /v2/cases/{id}/move with a stageId moves a case. A stage of another pipeline moves the case to that pipeline. The move answers 422 required_fields_missing when the stage requires a field the case lacks, and 409 conflict for a closed case.

POST /v2/cases/{id}/close ends the case. The contact can then have a new case in the pipeline. POST /v2/cases/{id}/reopen brings it back, and answers 409 conflict when the case is open or when the contact already opened another case in the pipeline.

Entering a stage fires case.stage_entered. A contact has one open case per pipeline: opening a second one answers 409 conflict.

Update and delete a pipeline

PATCH /v2/pipelines/{id} changes the name, the description, the status (draft, active, paused or archived), the quickReplies and the settings. Stages, fields and routing rules have their own routes.

DELETE /v2/pipelines/{id} answers 204. It answers 409 resource_in_use while the pipeline has open cases: close or move them first. The agents linked to its stages are not deleted.

Code
await lelemon.pipelines.update(pipeline.id, { status: 'paused' }); await lelemon.pipelines.delete(pipeline.id);

Errors you will meet

ErrorCause
400 invalid_requestA key, shortcut, setting, length or target stage breaks a rule; param names it
400 unknown_fieldA key of config or settings that the API does not have
403 scope_missingThe key lacks pipelines:write or cases:write
404 not_foundThe pipeline, stage, field or rule does not exist in this mode
409 conflictThe entry stage, a closed case, a second open case for the contact, or a WhatsApp number that already feeds another pipeline
409 resource_in_useDelete with cases in a stage, open cases in a pipeline, or a field that others depend on
422 required_fields_missingA move into a stage whose required fields the case lacks

All codes are in the error catalog.

Good practice

  • Name stages after what the customer did, not after your tool: "Quote sent", not "Stage 2".
  • Keep the entry stage for the agent and put the human work in later stages.
  • Create fields before the agent that fills them, and write an instruction for each field with source: "agent".
  • Use sensitive for anything the agent should never see, such as a national ID.
  • Put the fields a stage needs in requiredFields, so a case cannot reach "Visit booked" without an address.
  • Close cases with an outcome; it is what your reports group by.

What's next

  • Agents to build the agent that works a stage.
  • Build your own inbox to show cases and let your team answer.
  • Measure how long cases take once cases move.
AgentsKnowledge
On this page
  • Create a pipeline
  • Stages
    • The entry stage
    • Add, order and change stages
    • Stage kinds
    • Stages that close
    • The next stage and transitions
    • Settings of a stage
    • Escalate a case to your technical team
    • Start the cases of a WhatsApp number in a stage
    • Link an agent to a stage
    • Require fields before a stage
  • Fields
  • Routing rules
  • Pipeline settings
  • Quick replies
  • Move and close cases
  • Update and delete a pipeline
  • Errors you will meet
  • Good practice
  • What's next
TypeScript
curl https://api.lelemon.cl/v2/pipelines \ -H "Authorization: Bearer $LELEMON_API_KEY" \ -H "Idempotency-Key: sales-pipeline-1" \ --json '{ "name": "Home visits", "description": "Leads who ask for a quote for a home installation.", "stages": [ { "name": "New lead", "entry": true }, { "name": "Quote sent" }, { "name": "Visit booked" }, { "name": "Won" }, { "name": "Lost" } ], "quickReplies": [ { "shortcut": "hours", "text": "We visit Monday to Saturday, from 9:00 to 18:00." } ] }'
curl https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/stages \ -H "Authorization: Bearer $LELEMON_API_KEY" \ -H "Idempotency-Key: stage-follow-up-1" \ --json '{ "name": "Follow-up", "position": 2 }' curl -X PATCH https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/stages/$STAGE_ID \ -H "Authorization: Bearer $LELEMON_API_KEY" \ --json '{ "name": "Quote accepted", "position": 3 }' curl https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/stages \ -H "Authorization: Bearer $LELEMON_API_KEY"
curl -X PATCH https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/stages/$RESOLVED_STAGE_ID \ -H "Authorization: Bearer $LELEMON_API_KEY" \ --json '{ "closes": true, "closingOutcome": "Resolved", "statusType": "done" }'
TypeScript
TypeScript
TypeScript
curl -X PATCH https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/stages/$ENTRY_STAGE_ID \ -H "Authorization: Bearer $LELEMON_API_KEY" \ --json '{ "whatsappPhoneNumberId": "'"$PHONE_NUMBER_ID"'" }'
curl -X PATCH https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/stages/$ENTRY_STAGE_ID \ -H "Authorization: Bearer $LELEMON_API_KEY" \ --json '{ "agentId": "'"$AGENT_ID"'" }'
TypeScript
curl https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/fields \ -H "Authorization: Bearer $LELEMON_API_KEY" \ -H "Idempotency-Key: field-service-1" \ --json '{ "key": "service", "type": "select", "label": "Service", "required": true, "source": "agent", "instruction": "Ask which installation the customer needs.", "options": [ { "value": "solar", "label": "Solar panels" }, { "value": "heating", "label": "Heating" } ] }' curl https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/fields \ -H "Authorization: Bearer $LELEMON_API_KEY" \ -H "Idempotency-Key: field-model-1" \ --json '{ "key": "system_size", "type": "select", "label": "System size", "source": "agent", "dependsOn": "service", "options": [ { "value": "3kw", "label": "3 kW", "whenParent": ["solar"] }, { "value": "5kw", "label": "5 kW", "whenParent": ["solar"] }, { "value": "wall", "label": "Wall unit", "whenParent": ["heating"] } ] }'
TypeScript
curl https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID/routing-rules \ -H "Authorization: Bearer $LELEMON_API_KEY" \ -H "Idempotency-Key: rule-won-1" \ --json '{ "fromStageId": "'"$WON_STAGE_ID"'", "toPipelineId": "'"$ONBOARDING_PIPELINE_ID"'", "mode": "create" }'
curl -X PATCH https://api.lelemon.cl/v2/pipelines/$PIPELINE_ID \ -H "Authorization: Bearer $LELEMON_API_KEY" \ --json '{ "settings": { "timezone": "America/Santiago", "autoClose": { "enabled": true, "inactivityMinutes": 120, "message": "We close this chat for now. Write again when you want.", "closeStageId": "'"$LOST_STAGE_ID"'" }, "businessHours": { "days": { "mon": [{ "from": "09:00", "to": "18:00" }], "tue": [{ "from": "09:00", "to": "18:00" }], "sat": [{ "from": "10:00", "to": "14:00" }] }, "holidays": [{ "date": "2026-12-25" }] }, "waitThresholds": { "yellowMinutes": 10, "redMinutes": 30 }, "stageOnTakeControl": "'"$FOLLOW_UP_STAGE_ID"'" } }'
TypeScript
curl https://api.lelemon.cl/v2/cases/$CASE_ID/move \ -H "Authorization: Bearer $LELEMON_API_KEY" \ --json '{ "stageId": "'"$QUOTE_SENT_STAGE_ID"'" }' curl https://api.lelemon.cl/v2/cases/$CASE_ID/close \ -H "Authorization: Bearer $LELEMON_API_KEY" \ --json '{ "outcome": "won" }' curl -X POST https://api.lelemon.cl/v2/cases/$CASE_ID/reopen \ -H "Authorization: Bearer $LELEMON_API_KEY"
TypeScript