LeadAdapter

Dokumentation

API og webhooks

Webhooks skubber hændelser ud til dine systemer, når de sker. Denne side indeholder alt, hvad der skal til for at verificere en — præcist nok til at implementere efter.

API-nøgler

Opret en nøgle under Indstillinger og derefter API-nøgler. Den begynder med la_live_ og vises én gang — vi gemmer kun et hash af den, så en mistet nøgle bliver erstattet frem for genfundet.

Nøgler hører til et workspace og ikke til en person, og de overlever, at personen holder op. Tilbagekald en, og den holder øjeblikkeligt op med at virke, overalt, også i den agent der brugte den.

En nøgle er også måden at tilslutte en MCP-klient, der ikke kan åbne en browser. Send den som bearer-token.

Hvad REST-API'et dækker i dag

Webhook-abonnementer og MCP-endepunktet er tilgængelige nu. Det fulde læse- og skrive-REST-API er en Operator-funktion planlagt til en senere fase, og denne side beskriver det, når det findes — ikke før.

Har du brug for at læse eller ændre noget programmatisk i dag, er MCP-værktøjerne den understøttede vej, og de virker fra en almindelig HTTP-klient lige så vel som fra en agent.

Webhooks

En webhook er et HTTPS-endepunkt hos dig plus en hemmelighed, vi genererer. Vi sender en JSON-payload til det, hver gang en hændelse, du abonnerer på, sker — signeret, så du kan bevise, at den kom fra os.

Webhooks findes fra Pro og opefter. Hver levering registreres med sine forsøg, svarkoden og den første del af svarets indhold, så en modtager, der stille afviser leveringer, er synlig frem for mystisk.

Hændelser

Navnene er en stabil del af grænsefladen. Vi kan tilføje til listen; vi omdøber ikke noget på den.

De hændelser, en webhook kan abonnere på.
Hændelse Sendes når
comment.captured En kommentar på et opslag, en af dine automatiseringer holder øje med, blev læst.
lead.created Et nyt lead blev oprettet, uanset kilde.
lead.email_captured Et lead afgav en e-mailadresse på en leadside.
dm.sent En direkte besked blev leveret af din browser.
dm.replied Nogen svarede på en besked, du sendte.
connect.accepted En kontaktanmodning, du sendte, blev accepteret.
approval.requested Noget venter i godkendelseskøen.
approval.decided Nogen godkendte eller afviste en handling i køen.
page.viewed En leadside blev vist.

En webhook kan abonnere på en liste af disse eller på * for det hele — inklusive hændelser, der kommer til senere.

Signaturen

Hver levering signeres med HMAC over tidsstemplet og den rå payload. Tidsstemplet er inde i den signerede payload og ikke bare en header ved siden af — det er den del, de fleste genimplementeringer får galt, og det betyder noget: signerer man kun indholdet, får man en signatur, der gælder for evigt, og et usigneret tidsstempel kan skrives om og sætte dit eget friskhedstjek ud af kraft.

Headere på hver eneste webhook-levering.
Header Betydning
X-LeadAdapter-Signature HMAC af den signerede payload, som små bogstaver i hex, med algoritmen foran.
X-LeadAdapter-Timestamp Unix-sekunder, UTC, på det tidspunkt dette forsøg blev signeret. Gensendelser signeres på ny med et nyt tidsstempel.
X-LeadAdapter-Delivery Leverings-id'et. Det er det samme ved hver gensendelse af samme hændelse — brug det som din idempotensnøgle.
X-LeadAdapter-Event Hændelsens navn, som også står i selve payloaden.

Sådan beregnes signaturen

signed_payload = <X-LeadAdapter-Timestamp> + "." + <raw request body>
signature      = "sha256=" + lowercase_hex(
                     HMAC_SHA256(signed_payload, webhook_secret)
                 )

Et gennemregnet eksempel

De tre input giver præcis denne signatur. Sæt dem ind i din egen implementering, og sammenlign — værdien nedenfor er beregnet af den samme kode, der signerer dine leveringer.

secret    = whsec_example_do_not_use
timestamp = 1789012345
body      = {"id":"01JBXQ8P2R4S6T8V0W2X4Y6Z8A","event":"lead.created"}

X-LeadAdapter-Signature: sha256=b959110ea48a9bb42c68cf1b0be05720089c84a7d05d92a24644144d8e55870f

Verificering, i PHP

$body      = file_get_contents('php://input');   // raw, unparsed
$timestamp = $_SERVER['HTTP_X_LEADADAPTER_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_LEADADAPTER_SIGNATURE'] ?? '';

if (abs(time() - (int) $timestamp) > 300) {
    http_response_code(400); exit;               // outside the replay window
}

$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);

if (! hash_equals($expected, $signature)) {
    http_response_code(400); exit;               // constant-time, never ===
}

Gensendelser

Vi prøver igen ved 5xx, 429, 408 og ved transportfejl. Vi prøver ikke igen ved andre 4xx: dit endepunkt forstod kaldet og afviste det, og de samme bytes får det samme svar.

Hver gensendelse bærer det samme leverings-id og den samme payload, med et nyt tidsstempel og dermed en ny signatur. Det er med vilje, så en gensendelse, der kommer to timer senere, stadig består dit friskhedstjek.

Levering forsøges op til 6 gange.
Forsøg Pause inden
2 10 sekunder
3 1 minutter
4 5 minutter
5 30 minutter
6 120 minutter

Hvad din modtager skal gøre

Seks ting, i denne rækkefølge. Den første er den, der vælter implementeringer: læs de rå bytes, før noget JSON-mellemlag rører dem, for at gendanne indholdet ændrer det, og så passer signaturen ikke.

  1. Læs den rå payload, uden at parse den.
  2. Afvis leveringen, hvis tidsstemplet ligger længere fra dit eget ur end tolerancen.
  3. Genberegn signaturen, og sammenlign i konstant tid. Aldrig med en almindelig strengsammenligning.
  4. Først derefter: parse JSON.
  5. Fjern dubletter på leverings-id'et — gensendelser gentager det.
  6. Svar hurtigt med 2xx, og lav det egentlige arbejde bagefter.

Hver grænse, hvert loft, hver timeout og hvert værktøjsnavn på denne side læses fra det kørende produkt, når siden hentes. Ændrer softwaren sig, ændrer siden sig med.