LegoTechApps

Chatbot integrations

Let the chatbot talk to your systems.

The bot sends what customers report to your server as signed events, gives them a case number, and passes your answer back to them in their language — on WhatsApp, Instagram, Messenger or your website.

End to end

Customers report bugs, your AI fixes them.

  1. In the dashboard: Chatbot → Advanced → Actions → “Report a bug”. Point it at your server URL, or at a GitHub repository. Switch it on.
  2. A customer writes “the app crashes when I open the cart”. The bot collects the fields you defined and replies with a case number, e.g. C-48213.
  3. Your server receives a signed action.called event. Verify it, then open a ticket or hand it to a coding agent (for example Claude Code in GitHub Actions). Keep a person approving the pull request before it ships.
  4. When the fix is out, call the reply URL with an API key. The answer reaches the customer in their language — straight away, or after the owner approves it, as the action is set.
  5. Customers can ask “what is happening with C-48213?” — the bot answers from the case status and the last answer that was actually sent, only inside the conversation that opened it.
{
  "id": "6f1c…", "type": "action.called", "created_at": "2026-11-01T10:00:00+00:00",
  "business_id": 5, "bot": { "id": 74, "name": "Support" },
  "data": {
    "ref": "C-48213", "action": "report_bug", "title": "Report a bug",
    "input": { "description": "The app closes when I open the cart", "device": "iPhone 15, 2.3.1" },
    "conversation_id": 1234, "channel": "whatsapp",
    "reply_url":  "https://legotechapps.com/lt/api/v1/cases/C-48213/reply",
    "status_url": "https://legotechapps.com/lt/api/v1/cases/C-48213/status"
  }
}
curl -X POST https://legotechapps.com/lt/api/v1/cases/C-48213/reply \
  -H "Authorization: Bearer ltk_…" -H "Content-Type: application/json" \
  -d '{"text": "Fixed in version 2.3.2 — please update the app."}'

200 = sent · 202 = waiting for the owner's approval. Send "verbatim": true to skip the rewrite into the customer's language.

WhatsApp delivers a free-form message only within 24 hours of the customer's last message. After that the answer goes inside the business's approved order_update template (case number + your text), when it is approved and the business allows first messages; otherwise the owner is alerted with your text.

Security

Every request is signed (Standard Webhooks).

Headers webhook-id, webhook-timestamp, webhook-signature: v1,<base64>. Secret format whsec_…. Signature = base64(HMAC-SHA256(base64-decoded secret, "{id}.{timestamp}.{raw body}")). Reject timestamps older than 5 minutes; dedupe on webhook-id. The secret is never sent.

Node

import { Webhook } from "standardwebhooks";
const event = new Webhook(process.env.LEGOTECH_SECRET)
  .verify(rawBody, req.headers);

PHP

$key = base64_decode(substr($secret, 6));
$want = 'v1,' . base64_encode(
  hash_hmac('sha256', "$id.$ts.$raw", $key, true));

Retries

1 min, 5 min, 30 min, 2 h, 6 h, 24 h — then the delivery is marked dead. The dashboard's delivery log shows every attempt and has “send again”.

Actions

Fire-and-forget, or wait for an answer.

Queue

The customer gets a case number at once; your server is called from a queue with retries. Answer later with the reply API.

Wait (≤10 s)

Answer the POST with JSON — reply, message, answer or text is what the bot tells the customer, treated as data. Optional status, external_ref. A timeout falls back to the queue.

GitHub

Opens an issue per case. Comment /reply <text> to answer, close the issue when fixed, or mention C-48213 in a release to say which version fixed it.

Reference

API — https://legotechapps.com/lt/api

Authenticate with Authorization: Bearer ltk_…. Keys are created by the business owner (Chatbot → Advanced → API & cases), shown once, scoped, limited to 120 requests a minute, and optionally limited to allowed addresses (IPs or CIDR ranges — anything else gets 403 IP_NOT_ALLOWED). Every key, webhook and action change is listed in the dashboard's activity log.

MethodPathScopePurpose
GET/v1/meanyWhich business the key belongs to
GET/v1/cases/{ref}casesCase details, status, can_reply_now
POST/v1/cases/{ref}/replycases{text, verbatim?, status?, external_ref?, external_url?}
POST/v1/cases/{ref}/statuscases{status: open|waiting|answered|closed, note?, notify?}
POST/v1/hookshooksSubscribe {url, event|events} → {id, secret} (Zapier REST hooks)
DELETE/v1/hooks/{id}hooksUnsubscribe
GET/v1/samples/{event}hooksSample payload (a list)
POST/v1/datasources/{id}/rowsdataPush rows {rows, replace?} (≤256 KB) — for a database behind a firewall
PUT/v1/knowledge/{key}knowledgeUpsert an entry {title, body, bot_id?}
DELETE/v1/knowledge/{key}knowledgeRemove it

Events: lead.captured, handoff.requested, alert.raised, gap.noted, booking.created, order.created, action.called, case.updated, and — only when picked — message.received, message.sent. Customer name and phone are included only when the owner switched that on.

Live data

Answer from your own system.

Copy (default)

We read your JSON or CSV URL on a timer (5 minutes to daily) and search the copy. Nothing the customer types leaves us. A Google Sheet published as CSV works.

Real time

Your URL contains {query}; the bot calls it with the customer's search words (5 s timeout, falls back to the copy).

Push

POST /v1/datasources/{id}/rows from your side. We never connect to your database.