Bygg på Conecto
Et ryddig REST API for alt plattformen gjør: bygg boter som ikke bare svarer, men også kan handle , i databasen, faktureringen og produktet deres, send bilder, GIF-er, video og kort til chatten og bygge egne integrasjoner som KI-agenten kaller under samtalen, uavhengig av underliggende programvare. Hvis widgeten kan gjøre det, kan API-et styre det.
I produksjon · Signerte webhooks · 300 forespørsler/min
Det grunnleggende
Base URL https://conecto.chat/api/v1. Create a credential in Innstillinger → Utviklere , dere får en klient-ID og en hemmelighet (shown once, stored hashed). Authenticate with HTTP Basic — client ID as username, secret as password — or Authorization: Bearer <client_id>:<secret>. A credential can cover the whole workspace or be scoped to a single widget.
curl https://conecto.chat/api/v1/me/ -u "ck_your_client_id:cs_your_secret"Bruker dere Python? Den offisielt SDK (pip install conecto) wraps all of this, and does the parts that are easy to get subtly wrong for you: webhook signature verification, delivery deduplication, idempotent writes, retries, and block validation that fires before a request leaves your process. Everything below still applies — it is the same API underneath.
Hastighetsgrense 300 forespørsler/min per credential (429 + Retry-After beyond it). Errors are always {"error": {"code", "message"}}. List endpoints paginate with limit og before_id, returning next_before_id. Write endpoints accept an Idempotency-Key header (any UUID): retry the same key and you get the message that was already created, with a 200 instead of a 201, rather than a second copy in front of the visitor.
Ett endepunkt beskriver alle de andre
GET /schema/ returnerer hele overflaten som JSON: hvert endepunkt, hver hendelse, hver blokktype, hver reserverte handling, hver feilkode og hver numeriske grense. Den samme koden som håndhever grensene, leverer svaret, så det kan ikke avvike fra den kjørende serveren slik en dokumentasjonsside kan. Generer klienten derfra eller kontroller ved oppstart at funksjonen dere trenger er utrullet.
curl https://conecto.chat/api/v1/schema/ -u "ck_...:cs_..." | jq '.limits, .events[].name'Every response carries X-Conecto-Api-Version. Pin it in your client and log a warning when it changes — that header is how you find out a field moved before your users do.
Rikt innhold: bilder, GIF-er, video og kort
Any message you send can carry blocks — an ordered list of typed content rendered under the bubble in the widget, and in the agent's inbox exactly as the visitor saw it. Up to 10 per message, and every field is validated and re-projected server-side, so you never hand us markup and we never hand the browser a string.
curl -X POST https://conecto.chat/api/v1/conversations/42/messages/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{
"body": "Here is how to reset it — takes about 20 seconds:",
"blocks": [
{"type": "image", "url": "https://cdn.you.com/reset.gif", "alt": "Reset flow"},
{"type": "buttons", "items": [
{"label": "That worked"},
{"label": "Full guide", "url": "https://docs.you.com/reset"}
]}
]
}'Blokktypene
imageurl, alt, caption, link — animated GIFs are just imagesvideourl to an .mp4/.webm/.mov, plus poster, autoplay, loop, mutedembedprovider youtube · vimeo · loom · wistia · spotify og den vanlige delingslenken urlaudiourl til en .mp3/.wav/.m4a-fil, valgfritt titlefileurl, filename, size — rendered as a download rowcardsitems[] of title · subtitle · text · image · url · price · badge · buttons; layout carousel or listlistrows[] med etikett · verdi · undertittel · bilde · URL, for bestillingsoversikter og leveringstrinnbuttonsitems[]: {label, value} replies as the visitor, {label, url} opens a linktext · dividerekstra avsnitt og en vannrett linjeURLs must be https. A block that can't be built is a 400 naming the block and the reason, never a silent drop — an image that vanishes without explanation costs an afternoon to track down.
Send en GIF uten egen lagringsplass
POST /media/ takes a multipart file (≤10 MB) and hands back a URL you can drop straight into a block. Use the returned url — it is a path, resolved against the widget's own origin, so the same message works in development and in production.
URL=$(curl -s -X POST https://conecto.chat/api/v1/media/ -u "ck_...:cs_..." \
-F "file=@celebrate.gif" | jq -r .media.url)
curl -X POST https://conecto.chat/api/v1/conversations/42/messages/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d "{\"body\": \"All set!\", \"blocks\": [{\"type\": \"image\", \"url\": \"$URL\"}]}"Shipping a GIF as a muted, looping video block is usually the better trade: a tenth of the bytes, and the visitor cannot tell the difference.
En kortkarusell
{"blocks": [{
"type": "cards",
"items": [
{"title": "Trail Runner 2", "subtitle": "Road · Neutral",
"price": "89.00 USD", "badge": "Back in stock",
"image": "https://cdn.you.com/tr2.jpg",
"url": "https://shop.you.com/p/tr2",
"buttons": [{"label": "Add to cart", "url": "https://shop.you.com/cart/add/tr2"}]}
]
}]}Bygg en egen integrasjon
Shopify, Stripe og BigCommerce er integrasjoner som vi har skrevet. Dette er den som dere skrive. Beskriv tjenesten med en base-URL og en liste over handlinger, installer den på en widget, så kaller KI-agenten den under samtalen. Etterfølgende systemer kan ikke skille den fra en innebygd integrasjon. Det er hele poenget: Hvis butikken, faktureringen eller CRM-systemet kjører på en løsning vi ikke kjenner, trenger dere ikke lenger vente på at vi støtter den.
1 · Registrer den
curl -X POST https://conecto.chat/api/v1/integrations/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{
"slug": "acme-store",
"name": "Acme Store",
"base_url": "https://api.acme.example/conecto",
"auth_type": "bearer",
"credential": "sk_live_...",
"actions": [
{"name": "catalog.search_products", "path": "/search",
"description": "Search the Acme catalog by keyword.",
"parameters": [{"name": "query", "type": "string", "required": true},
{"name": "limit", "type": "integer"}]},
{"name": "orders.get_status", "path": "/orders/status", "risk": "verified_read",
"description": "Look up one of the visitor's orders by number.",
"parameters": [{"name": "order_number", "type": "string", "required": true}]},
{"name": "warranty.register", "path": "/warranty", "risk": "write",
"description": "Register a warranty for a product the visitor owns.",
"parameters": [{"name": "serial", "type": "string", "required": true}]}
]
}'The response includes a signing_secret. You need it to verify our calls — it is readable on every later GET too, and {"rotate_signing_secret": true} rolls it.
2 · Installer den på en widget
curl -X POST https://conecto.chat/api/v1/integrations/acme-store/install/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{"widget_ids": [7], "actions": ["catalog.search_products", "orders.get_status"]}'actions is an allowlist — omit it to enable everything you declared, or pass [] to keep the integration installed but idle. Nothing is exposed until you install it, and installing is per widget.
3 · Besvar kallet
We POST a signed JSON envelope to base_url + path. Verify the signature the same way you verify a webhook — one routine covers both directions:
// POST https://api.acme.example/conecto/search
{
"action": "catalog.search_products",
"integration": "acme-store",
"arguments": { "query": "trail shoes", "limit": 3 },
"source": "ai_agent",
"idempotency_key": "8f14e45fceea167a...",
"workspace": { "id": 12 },
"widget": { "id": 7, "key": "w_..." },
"conversation": { "id": 4821 },
"visitor": { "session": "…", "email": "maya@acme.io",
"verified": true, "verified_email": "maya@acme.io", "name": "Maya" }
}
// Headers: X-Conecto-Signature: sha256=<HMAC-SHA256(signing_secret, raw body)>
// X-Conecto-Timestamp, X-Conecto-Action, X-Conecto-Integration,
// X-Conecto-Idempotency-KeySvar med én av fem former:
{"ok": true, "result": {...}} // success — the agent reads it
{"ok": true, "result": {...}, "blocks": [...]} // …and attach rich content to the reply
{"ok": true, "not_found": true} // nothing matched (a normal outcome)
{"verify_required": true} // "I need a verified visitor for this"
{"ok": false, "error": "Already cancelled."} // a failure the agent may relayEt vanlig JSON-objekt uten noen av disse nøklene behandles som selve resultatet. Dere kan derfor peke en handling mot et endepunkt som allerede finnes. Grenser: 8 sek. timeout, 128 kB -svar. Alt dere returnerer, når modellen som data i et JSON-envelope, aldri som instruksjoner. Nøkler som ser ut som hemmeligheter, fjernes på vei inn.
4 · Test før en besøkende gjør det
curl -X POST https://conecto.chat/api/v1/integrations/acme-store/actions/catalog.search_products/run/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{"arguments": {"query": "trail shoes"}}'This runs the real call path — signature, credential, timeout, parsing — and shows you the envelope the agent will get. Pass conversation_id to run it in the context of a live chat, which is the only way a verified action can succeed.
Risikonivåer og den ene regelen som ikke kan slås av
public_readkatalog, tilgjengelighet, dokumentasjon, ingen identitet krevesverified_readén persons data. Avvises til den besøkendes e-postadresse er verifisertpublic_writeen endring som ikke krever identitet, for eksempel påmelding til nyhetsbrev eller innsamling av leadswriteen endring på én persons konto. Verifisert og aldri forsøkt på nytt uten varselFor de to siste leveres den verifiserte adressen av oss, in visitor.verified_email — never taken from the model's arguments. Verification comes from an emailed code, or from your own site attestering av en innlogget bruker. Ingen widgetinnstilling kan unnta en handling fra regelen, fordi «hvem sin bestilling er dette?» ikke er et spørsmål en bryter skal besvare.
Reserverte handlinger: butikken deres, koblet til som en innebygd integrasjon
A few action names mean something to the platform itself. Declare catalog.search_products returning {"products": [{title, url, image, price_from, currency, available}]} and its results become product cards under the AI's replies and fill the widget's Home showcase — the same treatment a Shopify connection gets, from whatever your catalog actually runs on. orders.get_status, orders.get_tracking, orders.list_recent og account.lookup are reserved the same way, and are always verified reads. GET /integrations/{slug}/actions/ returns the full catalog with the shape each one expects.
Egendefinerte integrasjoner inngår i KI-agentabonnementene og er begrenset til 20 per arbeidsområde med 40 handlinger hver. Utgående kall bruker bare HTTPS, løses og låses til en offentlig IP-adresse før tilkobling, og videresendinger avvises. En integrasjons-URL kan derfor aldri peke mot et privat mål.
Hurtigstart: en egen bot i tre trinn
A bot is a webhook and a reply. Subscribe to message.created, answer through the messages endpoint, and the widget renders it live — quick-reply buttons, email capture, the native ticket form, typing indicators. Turn the built-in AI off on the widget and your bot owns the conversation.
1. Abonner med serveren (Innstillinger → Utviklere → Webhooks eller via API):
curl -X POST https://conecto.chat/api/v1/webhooks/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{"url": "https://bots.yourapp.com/conecto",
"events": ["message.created", "conversation.created"]}'2. Verifiser og les hendelsen. Every delivery is signed: X-Conecto-Signature: sha256=<HMAC-SHA256(secret, raw body)>.
// Node/Express
app.post('/conecto', express.raw({ type: '*/*' }), (req, res) => {
const sig = 'sha256=' + crypto.createHmac('sha256', WEBHOOK_SECRET)
.update(req.body).digest('hex')
if (sig !== req.get('X-Conecto-Signature')) return res.sendStatus(401)
const { event, data } = JSON.parse(req.body)
if (event === 'message.created' && data.message.sender === 'visitor') {
handle(data) // your bot logic — reply async, respond 200 fast
}
res.sendStatus(200)
})3. Svar med funksjoner.
curl -X POST https://conecto.chat/api/v1/conversations/42/messages/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{"body": "I can refund order #1284 right away — confirm?",
"buttons": ["Yes, refund it", "Talk to a human"]}'Button taps come back to your webhook as normal visitor messages containing the button text — your bot's state machine lives entirely on your side. Other reply powers: blocks sends images, GIFs, video and cards (see Rikt innhold), {"ask_email": true} renders the email-capture form, {"ticket_form": true} attaches the native open-a-ticket form, products renders tappable product cards, {"internal": true} leaves an agent-only note, /typing/ shows “…is typing”, /handoff/ summons a human, and PATCH closes the conversation when you're done.
Botoppskrifter
Oppskrifter som faktisk brukes i produksjon. Hver består av en webhookhandler og noen API-kall.
1 · Handlingsboten, endrer ting i deres programvare
Fordi webhooken treffer deres kan boten gjøre alt på serveren som backend kan: skrive til databasen, kalle faktureringssystemet eller oppdatere en post i regnskapsprogrammet. Sammen med attestert identitet dere vet nøyaktig hvem som spør. Derfor kan «bokfør denne kvitteringen på 250 dollar under Markedsføring» utføres trygt:
async function handle({ conversation, visitor, message }) {
const convo = conversation.id
// "file 250 under Marketing" — your parsing, your rules
const cmd = parseAccountingCommand(message.body)
if (!cmd) return reply(convo, "Tell me e.g. 'file 250 under Marketing'.")
// Only act for users YOUR backend has vouched for (logged in on your site)
if (!visitor.verified)
return reply(convo, "Please sign in first, then ask me again.", ["Log in"])
await ledger.addEntry({ // <- YOUR accounting system
account: cmd.account,
amount: cmd.amount,
user: visitor.verified_email, // identity Conecto guarantees
})
await reply(convo,
`Done — $${cmd.amount} filed under ${cmd.account}. Anything else?`,
["Show this month's entries", "Undo that"])
}Det samme mønsteret fungerer for «legg til en plass i abonnementet mitt», «gi prosjektet mitt nytt navn» eller «bestill en time torsdag». Boten er et tynt samtalelag over deres eget API. Vil dere heller bruke den innebygde KI-en enn å skrive en bot? Registrer de samme endepunktene som en integrasjon og Conectos KI kaller dem under samtalen med samme identitetsverifisering, uten en tilstandsmaskin å vedlikeholde. Hvis dere allerede bruker MCP, fungerer også en ekstern MCP-verktøyserver: Dashboard → KI-agenter → Integrasjoner.
2 · Bot for bestillingsstatus
if (/where.*order|track/i.test(message.body)) {
await typing(convo, 'OrderBot', true)
const order = await shop.lastOrder(visitor.email) // your store
await reply(convo, order
? `Order #${order.id} is ${order.state} — arriving ${order.eta}.`
: "I couldn't find an order for this email.",
order ? [`Track #${order.id}`] : undefined)
}3 · Bot for å redusere saker
Søk først i hjelpesenteret; åpne bare en sak når ingenting passer:
const { articles } = await api('GET', '/articles/?q=' + q + '&published=true')
if (articles.length)
await reply(convo, `This might help: “${articles[0].title}”. Did that solve it?`,
["Solved it", "Open a ticket"])
else
await api('POST', `/conversations/${convo}/messages/`,
{ body: "Let's get this to the team.", ticket_form: true })4 · Bot for kvalifisering av leads
// no email yet? capture it natively, then enrich + route
if (!visitor.email)
return api('POST', `/conversations/${convo}/messages/`,
{ body: "Happy to help — what's your work email?", ask_email: true })
await api('POST', '/contacts/', { email: visitor.email,
custom_fields: { lead_source: 'chat', intent: classify(message.body) } })
await api('POST', `/conversations/${convo}/messages/`,
{ body: "Routing you to sales…", internal: true })
await api('POST', `/conversations/${convo}/assign/`, { user_id: SALES_USER_ID })
await api('POST', `/conversations/${convo}/handoff/`)5 · Proaktive meldinger gjennom kundereisen
Send til en besøksøkt uten å vente på en melding, for eksempel leveringsoppdateringer, prøvepåminnelser eller gjenoppretting av handlekurven:
curl -X POST https://conecto.chat/api/v1/widgets/7/visitors/$SESSION/message/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{"body": "Your order shipped — want live tracking?",
"buttons": ["Track my order"]}'Cart recovery works the same way, with products putting the item itself back in front of them as a tappable card:
-d '{"body": "Still thinking it over? Your cart is saved:",
"products": [{"title": "Trail Runner 2", "price_from": "89.00",
"currency": "USD", "image": "https://cdn.you.com/tr2.jpg",
"url": "https://shop.you.com/cart"}]}'6 · En ukjent butikk, koblet til KI
Ingen webhook og ingen tilstandsmaskin: deklarer den reserverte kataloghandlingen, pek den mot søkeendepunktet, så anbefaler KI-en varer fra katalogen med ekte produktkort.
// POST /conecto/search on your server
app.post('/conecto/search', verifyConectoSignature, async (req, res) => {
const { query, limit = 4 } = req.body.arguments
const hits = await catalog.search(query, { limit }) // <- YOUR catalog
res.json({ ok: hits.length > 0, not_found: hits.length === 0,
products: hits.map(p => ({
title: p.name, url: p.permalink, image: p.thumbnail,
price_from: p.price.toFixed(2), currency: p.currency,
available: p.stock > 0,
})) })
})Det er hele integrasjonen. Kortene, Home-utvalget, regelen «kall på nytt før et produkt nevnes» og forbudet mot at modellen limer inn rå URL-er, følger automatisk med det reserverte navnet.
7 · CSAT-oppfølging
Subscribe to conversation.rated; thank promoters, rescue detractors:
if (event === 'conversation.rated') {
if (data.rating.score <= 2)
await api('POST', '/tickets/', { email: data.visitor.email,
message: `Low CSAT (${data.rating.score}/5): ${data.rating.comment}`,
priority: 'high' })
else
await push(data.widget.id, data.visitor.session,
"Glad we could help! Here's 10% off your next order: THANKS10")
}Handle trygt på deres egne systemer
Tre regler gjør handlingsboter produksjonsklare:
1. Identiteten først. Only mutate data for sessions where visitor.verified is true — your backend vouched for them via /identify/. The vouch is time-boxed and session-scoped; revoke it with /unverify/ on logout.
2. Bekreft destruktive trinn. Send handlingen som et spørsmål med knapper («Refundere bestilling #1284?» · Ja / Nei), trykket kommer tilbake som knappens tekst, den idempotente handleren kjøres, og transkripsjonen dokumenterer samtykket.
3. Overfør til en person ved usikkerhet. POST /conversations/{id}/handoff/ flags the thread human-needed (your routing rules apply), and {"internal": true} notes give the teammate full context your bot gathered.
Endepunktreferanse
Samtaler og meldinger
/conversations/Newest first. Filters: status (open · pending · closed), widget_id, session; paginate with limit/before_id.
/conversations/{id}/Conversation + visitor-facing transcript (≤500 messages, since_id for increments).
/conversations/{id}/messages/body (≤4000), buttons (≤6 × 60 chars), blocks (≤10 — see Rikt innhold), ask_email, ticket_form (native ticket form), internal (agent-only note), products (≤4 cards rendered as a mini carousel under the bubble: {title, url, price_from, currency, image} — title required, everything else optional). Honors Idempotency-Key. 409 when closed.
/conversations/{id}/typing/{"name": "OrderBot", "on": true} , utløper automatisk etter omtrent 8 sek.
/conversations/{id}/assign/{"user_id": 12} (or null to unassign) — teammates come from /members/.
/conversations/{id}/handoff/Marker at en person trengs; vises i innboksen som en KI-overføring, inkludert rutingsregler.
/conversations/{id}/{"status": "closed" | "open"}. Closing fires conversation.closed.
/widgets/{widget_id}/visitors/{session}/message/Proactive push: reuses the session's live conversation or opens one; body + buttons + blocks + products. Honors Idempotency-Key.
Integrasjoner, deres egen programvare som fullverdig integrasjon
/integrations/ · POSTList, or register one: slug, name, base_url (https), optional description/icon_url/homepage_url, auth_type (none · bearer · api_key · basic) + credential, and actions inline. Returns the signing_secret you verify our calls with.
/integrations/{slug}/ · PATCH · DELETEPATCH takes the same fields; actions upserts by name and replace_actions: true makes your list authoritative (deploy-from-source). rotate_signing_secret rolls the secret; active: false switches it off everywhere at once.
/integrations/{slug}/actions/ · POST · DELETE /{name}/Each action: name (dotted, e.g. orders.lookup), path, method, risk, description (what the AI reads), parameters ({name, type, required, description, enum}), ai_enabled. GET also returns the reserved-action catalog.
/integrations/{slug}/install/ · /uninstall/widget_ids (all visible widgets when omitted), actions allowlist, enabled.
/integrations/{slug}/actions/{name}/run/Invoke it now through the real call path. arguments, optional conversation_id for visitor context. Returns {status, result, blocks}.
Medier
/media/Multipart file (≤10 MB) → {media: {url, absolute_url, filename, content_type, size, is_image}}. Put url in an image/video/file block.
Saker
/tickets/Filters: status (open · pending · resolved), email; paginated.
/tickets/email, message, optional name, category_id, priority (low · normal · high · urgent), submission_id (UUID idempotency key). The requester gets the standard acknowledgement email.
/tickets/{id}/ · PATCHDetail with the comment thread; PATCH status, priority, assignee_user_id.
/tickets/{id}/reply/body — emails the requester; internal: true for a private note.
/ticket-categories/Arbeidsområdets kategorier for å opprette saker.
Kontakter, synkroniser brukerdatabasen
/contacts/Upsert by email (201 created / 200 updated): profile fields + custom_fields (≤30 keys, merged).
/contacts/ · GET/PATCH/DELETE /contacts/{id}/Search with email (exact) or q; standard pagination.
Besøkende, identitet og personalisering
/widgets/{widget_id}/visitors/{session}/identify/email (required), name, data (custom fields), verified + verify_hours (≤72, default 12) — see Identitet. Økter kan klargjøres på forhånd.
/widgets/{widget_id}/visitors/{session}/unverify/Trekk tilbake attesteringen, kall ved utlogging.
/widgets/{widget_id}/visitors/{session}/Gjeldende identitet: e-post, navn og verifiseringsstatus.
Kunnskapsbase
/articles/q full-text search, published=true filter — perfect for bot answer lookups.
/articles/ · GET/PATCH/DELETE /articles/{id}/Synkroniser dokumentasjon gjennom kode. HTML-innhold renses på serveren etter en tillatelsesliste.
Konfigurasjon og metadata
/widgets/{widget_id}/ · PATCHLes eller oppdater widgetkonfigurasjon, hilsen, farger, handlingsknapper på Home, hurtigspørsmål, åpningstider og de samme validerte feltene som dashboardets tilpasningsverktøy redigerer.
/members/Teammedlemmer (user_id, name, role) for tildeling.
/stats/Direktetall: åpne/ventende samtaler, åpne saker, kontakter og publiserte artikler.
/me/Arbeidsområdet, omfanget for påloggingsopplysningen og widgetene deres (ID-er + innebyggingsnøkler).
/schema/Den maskinlesbare beskrivelsen av alt ovenfor: endepunkter, hendelser, blokktyper, reserverte handlinger, feilkoder og grenser. Generer klienten fra den.
Identitet: hopp over ny verifisering for innloggede brukere
Widgeten lagrer økt-ID-en i nettleseren. Les den på klientsiden, send den til backend med deres egen øktinformasjonskapsel og attester deretter identiteten fra server til server:
# your backend, right after your own auth check
curl -X POST https://conecto.chat/api/v1/widgets/7/visitors/$CONECTO_SESSION/identify/ \
-u "ck_...:cs_..." -H "Content-Type: application/json" \
-d '{"email": "maya@acme.io", "name": "Maya",
"verified": true, "verify_hours": 24,
"data": {"plan": "pro", "customer_since": "2024"}}'While the vouch lasts, Conecto treats the email as verified: the widget knows their name, chats attach to the right CRM contact, and flows that normally demand an email OTP — refund lookups, order changes, sensitive account data through the AI's tools — proceed without one. Your attestation is as strong as our code-by-email, because you actually authenticated them. Only vouch sessions your backend has verified, and call /unverify/ on logout.
Webhooks
Manage in the dashboard or via GET/POST /webhooks/ og DELETE /webhooks/{id}/ (https only, ≤10 per workspace, optional per-widget scope). Deliveries carry X-Conecto-Event, X-Conecto-Delivery, X-Conecto-Timestamp and the HMAC signature, and time out after 2.5s — respond 200 fast, process async. Events:
conversation.createdførste besøksmelding i en ny tråd, inkludert skjemaer på Home-fanenmessage.createdhver besøksmelding, utløseren for den egne botenconversation.closedlukket av en medarbeider eller API-etconversation.assignedtildelt et teammedlem eller ikke lenger tildeltconversation.handoffmarkert som at en person trengsconversation.ratedden besøkendes CSAT-vurdering (1–5 + kommentar)ticket.createdalle kilder: widgetskjema, KI, boter, automatiseringer, APIticket.updatedstatus, prioritet eller tildelt person endretcontact.createden ny person ble lagt til i CRM, synkroniser personen med deres systemvisitor.identifieden økt ble identifisert gjennom API-et, med sin attesteringsstatusLeveringen skjer minst én gang og uten garantert rekkefølge. Every payload carries an id (also in X-Conecto-Delivery): store it, skip ids you have already handled, and both replays and duplicates stop being your problem. When your bot answers a delivery, pass that same id as the Idempotency-Key and a redelivery can never make it speak twice.
app.post('/conecto', express.raw({ type: '*/*' }), async (req, res) => {
const sig = 'sha256=' + crypto.createHmac('sha256', WEBHOOK_SECRET)
.update(req.body).digest('hex')
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(req.get('X-Conecto-Signature') || '')))
return res.sendStatus(401)
const { id, event, data } = JSON.parse(req.body)
res.sendStatus(200) // ack first, work after
if (await seen(id)) return // at-least-once: dedupe on the delivery id
if (event === 'message.created' && data.message.sender === 'visitor') {
await fetch(`https://conecto.chat/api/v1/conversations/${data.conversation.id}/messages/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Idempotency-Key': id, ...auth },
body: JSON.stringify({ body: await answer(data) }),
})
}
})Everything here is designed to sit under an SDK: stable envelopes, slug-addressed integrations, typed errors, cursor pagination, idempotent writes, one signature scheme in both directions, and GET /schema/ to generate from. Building something? Snakk med oss , vi ønsker at utviklere skal bygge på Conecto og prioriterer ønskene deres.