Package Information
Available Nodes
Documentation generating…
Documentation
n8n-nodes-letsbot
n8n community nodes for LetsBot. Version 0.2.0 · License: MIT.
Install
In n8n: Settings → Community Nodes → Install and enter n8n-nodes-letsbot. Self-hosted with npm:npm install n8n-nodes-letsbot in your n8n custom nodes folder (~/.n8n/nodes), then restart n8n.
Nodes
LetsBot (action node)
| Resource | Operation | LetsBot endpoint (https://<workspace-domain>/api) |
|---|---|---|
| Message | Send Text | POST /zapier-integration/actions/send-text {phone, message, channel_id?} |
| Message | Send Template | POST /zapier-integration/actions/send-template {phone, slug, variables{}, header_media_url?, header_media_filename?, channel_id?} |
| Contact | Create or Update | POST /zapier-integration/actions/contacts {phone, name?, email?} |
| Contact | Find by Phone | GET /zapier-integration/actions/contacts/find-by-phone?phone= (404 → no items) |
| Contact | Add Label / Remove Label | POST /zapier-integration/actions/contacts/{add,remove}-label {phone, label_id | label_name} |
| Contact | Update Custom Field | POST /zapier-integration/actions/contacts/update-field {phone | contact_id, key, value} |
| Channel | Get Many | GET /zapier-integration/lookup/channels |
| (dropdowns) | Labels, Templates, Channels, Custom Fields, Lifecycle Stages | GET /zapier-integration/lookup/{labels,templates,channels,custom-fields,lifecycle-stages} |
LetsBot Trigger — events: Message Received (new_message_received), Contact Created (new_contact_created),
Label Added / Removed (contact_labeled / contact_unlabeled, optional label filter), Lifecycle Stage Changed
(contact_lifecycle_changed, optional stage picked from lookup/lifecycle-stages).
- Activate →
POST /zapier-integration/webhooks/subscribe{hookUrl, trigger, name, source: "n8n", event_filters?};
the returnedidandsecretare kept in the node's static data. - Deactivate →
DELETE /zapier-integration/webhooks/unsubscribe/{id}. - Each delivery is checked:
X-Zapier-Signaturemust equalsha256=+ HMAC-SHA256(raw body, secret) andX-Zapier-Subscription-Idmust match; otherwise the node answers 401 and starts nothing. The output item is LetsBot's
flat payload.
LetsBot CRM (action node, public CRM API https://<workspace-domain>/api/v1/crm; the API key needs the
crm scope ticked under Panel → Zapier → API keys, otherwise every call answers 403 missing_scope)
| Resource | Operations | Endpoint |
|---|---|---|
| Contact | Create (409 → existing contact, already_existed: true), Get, Get Many (lists-engine filter JSON, text), Search (phone/email/text), Update |
/contacts, /contacts/{id}, /contacts/search |
| Company | Create, Get, Get Many, Search (domain/name/text), Update, Delete, Link Contact | /companies…, POST /companies/{id}/contacts |
| Deal | Create, Get, Get Many (status/stage/owner/contact/updated since), Update, Delete, Move Stage, Mark Won, Mark Lost (lost reason) | /deals…, POST /deals/{id}/{stage,won,lost} |
| Task | Create, Get, Get Many, Update, Delete, Complete | /tasks…, POST /tasks/{id}/complete |
| Note | Create (on a contact, company or deal), Get Many (the record's timeline) | POST /{contacts,companies,deals}/{id}/notes, GET /activities?subject_type=&subject_id= |
| (dropdowns) | Stages, Lost Reasons | GET /pipelines, GET /deals/lost-reasons |
LetsBot CRM Trigger — any of the 18 CRM events (contact.created|updated|deleted, company.*, deal.created|updated| deleted|stage_changed|won|lost, task.created|completed, ticket.created, quote.sent|viewed|accepted).
- Activate →
POST /v1/crm/hooks{target_url, events[], source: "n8n", description};data.idanddata.secretare kept
in static data. Deactivate →DELETE /v1/crm/hooks/{id}(404 = already gone). - Each delivery is checked:
X-LetsBot-Signature: t=<unix>,v1=<hex HMAC-SHA256 of "t.<raw body>">with the secret, within
5 minutes; otherwise 401. Output: the record's fields plusevent,event_id,occurred_at,previous,changes
(or the raw delivery).
Source of truth: packages/zapier/routes/tenant.php (routes), packages/zapier/src/Http/Controllers/** (bodies),packages/zapier/src/Http/Controllers/Triggers/SamplesController.php (payloads).
Credential
LetsBot API: Workspace Domain (e.g. mystore.letsbot.net; a pasted https://…/panel is normalized) and API Key
(lbz_…, from Panel → Zapier → API keys (/panel/v2/zapier/api-keys)). Sent as X-Zapier-Api-Key. The credential test calls GET /api/user.
Scopes the key needs (a key with no scopes has full access): manage_subscriptions, read_events, send_text,send_template, create_contact, manage_labels, update_contact, poll_contacts.
Develop
npm install # .npmrc sets ignore-scripts: n8n-workflow pulls isolated-vm, whose native build fails on Node 26
npm run build # tsc → dist/ + copies the SVG icons
npm run lint # eslint (typescript-eslint + eslint-plugin-n8n-nodes-base)
npm run typecheck
npx jest test/LetsBot.node.test.ts # one file per run (workspace rule)
npx jest test/LetsBotTrigger.node.test.ts
npx jest test/LetsBotApi.credentials.test.ts
Tests mock httpRequestWithAuthentication; nothing reaches the network.
Try it in a local n8n without publishing: npm run build && npm link, then in ~/.n8n/custom runnpm link n8n-nodes-letsbot and restart n8n. The trigger needs a public HTTPS webhook URL — LetsBot refuseslocalhost/private hosts (SSRF guard). Run n8n with WEBHOOK_URL=https://<your-tunnel>/.
Known server behaviour
- Create or Update clears an existing name/email when the field is empty (known, left as-is by owner decision).
- Update Custom Field and the label/lifecycle triggers need the workspace's
integrationsarea; otherwise update-field
answers404 not_foundand those subscriptions never fire. - Send Text / Send Template take an optional Channel; empty = the workspace's oldest channel (as before). An id that is not one
of the workspace's channels fails withchannel_not_foundand sends nothing. - The Custom Field and Lifecycle Stage dropdowns are empty while the workspace has not adopted the
integrationsarea
(stages also need thelifecyclearea). - LetsBot has no "list subscriptions" endpoint, so
checkExiststrusts the id stored in static data.