Webhooks
Webhooks
Gemlead schickt eine HTTPS-Anfrage an deinen Server, sobald ein Lead gefunden wird, heiß wird, antwortet oder auf deine Nachricht reagiert, oder sobald Sam AI eine Antwort bereithält, eine sendet oder dir eine Unterhaltung übergibt. Sie ist signiert, damit du weißt, dass sie von uns kommt.
Endpoint einrichten
Füge in der App unter API einen Endpoint hinzu oder nutze Webhook-Endpoint erstellen. Gib ihm eine öffentliche HTTPS-URL und die gewünschten Ereignistypen, und bewahre das zurückgegebene secret auf, um Signaturen zu prüfen.
- Nur HTTPS, keine Zugangsdaten in der URL und keine private, Loopback- oder Link-Local-Adresse.
- Bis zu 10 Endpoints pro Konto.
filters.persona_idsbeschränkt die Ereignisse eines Endpoints auf die Leads bestimmter Personas, egal welchen Typs.- Sende ein Testereignis, um deinen Server zu prüfen, bevor echte Ereignisse ankommen.
Webhooks sind in den Tarifen Business und Enterprise enthalten. Wechselt das Konto zu Free oder Starter, bleiben seine Endpoints erhalten, senden aber nichts, bis es wieder Business oder Enterprise nutzt.
curl -X POST https://gemlead.ai/api/v1/webhook_endpoints \
-H "Authorization: Bearer $GEMLEAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/gemlead",
"events": ["lead.hot", "reply.received"],
"description": "CRM sync",
"filters": {
"persona_ids": ["lvWBPnytpS"]
}
}'Ereignistypen
Jedes Ereignis hat denselben Aufbau. Sein data hängt von seinem type ab.
| Typ | Gesendet, wenn |
|---|---|
lead.created | Gemlead findet und bewertet einen neuen Lead, egal mit welchem Score. Jeder Lead löst es einmal aus, mit seinem ersten Score, und nur innerhalb von 3 Tagen, nachdem er gefunden wurde. Eine neue Bewertung eines älteren Leads löst es also nie aus. Ein Lead, der gleich 60 oder mehr erreicht, löst auch lead.hot aus. |
lead.hot | Der Score eines Leads erreicht zum ersten Mal 60 oder mehr. Jeder Lead löst es einmal aus, eine neue Bewertung nie wieder. |
reply.received | Ein Lead schickt dir eine neue Nachricht, ob in einer Kampagne oder nicht. Jede Nachricht löst es einmal aus, wenn sie jünger als 6 Stunden ist. Kommen viele Nachrichten des Leads auf einmal an, lösen es nur die 5 neuesten aus. |
reaction.received | Ein Lead reagiert mit einem Emoji auf eine deiner Nachrichten. Jedes Emoji des Leads auf einer Nachricht löst es einmal aus. |
sam.suggestion.ready | Sam AI hält in einer Unterhaltung im Modus draft eine neue Antwort bereit, die du senden kannst. Jeder Vorschlag löst es einmal aus, wenn er jünger als 6 Stunden ist. |
sam.reply.sent | Eine Antwort von Sam AI geht von deinem X-Konto raus, selbstständig im Modus auto oder sobald du sie in der App freigibst. Jede Antwort löst es einmal aus, wenn sie jünger als 6 Stunden ist. Nachrichten, die du selbst schreibst, lösen es nie aus, du findest sie über Unterhaltung abrufen. |
sam.handoff | Sam AI übergibt dir eine Unterhaltung, wenn er ohne dich keine gute Antwort sieht, der Lead nur ein Foto oder eine Sprachnachricht geschickt hat oder seine Antwort nicht rausgehen konnte. Im Modus auto überlässt er dir danach die nächsten Nachrichten des Leads. Jede Übergabe löst es einmal aus, wenn sie jünger als 6 Stunden ist. |
Das Ereignisobjekt
- idstringEindeutige Kennung des Ereignisses,
evt_und 24 Zeichen. Steht auch im HeaderGemlead-Event-Id. - objectstringImmer
event. - typestringDer Ereignistyp.
lead.createdlead.hotreply.receivedreaction.receivedsam.suggestion.readysam.reply.sentsam.handoff - created_atstringWann das Ereignis eingetreten ist, ISO 8601.
- account_idstringDas Gemlead-Konto, in dem es eingetreten ist.
- dataobjectDer Inhalt des Ereignisses, abhängig von seinem Typ.
lead.created
Gemlead findet und bewertet einen neuen Lead, egal mit welchem Score. Jeder Lead löst es einmal aus, mit seinem ersten Score, und nur innerhalb von 3 Tagen, nachdem er gefunden wurde. Eine neue Bewertung eines älteren Leads löst es also nie aus. Ein Lead, der gleich 60 oder mehr erreicht, löst auch lead.hot aus.
Daten
- objectobjectDer Lead, so wie ihn Lead abrufen zurückgibt.
{
"id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
"object": "event",
"type": "lead.created",
"created_at": "2026-11-05T14:03:40.117Z",
"account_id": "a9PzK2vRtM",
"data": {
"object": {
"id": "k3VnQ8wZpR",
"object": "lead",
"profile": {
"x_user_id": "1592047713",
"username": "mark_picks",
"name": "Mark Ellis",
"bio": "Free NBA picks every day. Sports fan first.",
"followers_count": 2150,
"following_count": 940,
"location": "Denver, CO",
"website": "https://markpicks.net",
"profile_image_url": "https://pbs.twimg.com/profile_images/1592047713/mark_400x400.jpg",
"verified": false,
"url": "https://x.com/mark_picks"
},
"score": 38,
"score_reason": "Shares free picks for fun and sells nothing yet, no sign of a paying community.",
"hot": false,
"status": "scored",
"persona": {
"id": "lvWBPnytpS",
"name": "Tipsters"
},
"campaign": null,
"conversation_id": null,
"locked_to": null,
"found_at": "2026-11-05T14:02:11.482Z",
"scored_at": "2026-11-05T14:03:40.117Z",
"updated_at": "2026-11-05T14:03:40.117Z",
"metadata": {}
}
}
}lead.hot
Der Score eines Leads erreicht zum ersten Mal 60 oder mehr. Jeder Lead löst es einmal aus, eine neue Bewertung nie wieder.
Daten
- objectobjectDer Lead, so wie ihn Lead abrufen zurückgibt.
{
"id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
"object": "event",
"type": "lead.hot",
"created_at": "2026-11-05T14:03:40.117Z",
"account_id": "a9PzK2vRtM",
"data": {
"object": {
"id": "msgOtJ8dvT",
"object": "lead",
"profile": {
"x_user_id": "1460283925",
"username": "jane_builds",
"name": "Jane Doe",
"bio": "Runs a paid trading community. Daily setups, no hype.",
"followers_count": 12400,
"following_count": 380,
"location": "Austin, TX",
"website": "https://janedoe.com",
"profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
"verified": true,
"url": "https://x.com/jane_builds"
},
"score": 86,
"score_reason": "Runs a paid trading community and asks how to collect payments for it.",
"hot": true,
"status": "scored",
"persona": {
"id": "lvWBPnytpS",
"name": "Tipsters"
},
"campaign": null,
"conversation_id": null,
"locked_to": null,
"found_at": "2026-11-05T14:02:11.482Z",
"scored_at": "2026-11-05T14:03:40.117Z",
"updated_at": "2026-11-05T14:03:40.117Z",
"metadata": {}
}
}
}reply.received
Ein Lead schickt dir eine neue Nachricht, ob in einer Kampagne oder nicht. Jede Nachricht löst es einmal aus, wenn sie jünger als 6 Stunden ist. Kommen viele Nachrichten des Leads auf einmal an, lösen es nur die 5 neuesten aus.
Daten
- leadobjectDer Lead, der geschrieben hat.
- messageobject
- campaignobject oder nullDie Kampagne des Leads, mit
id,nameundstatus. - conversation_idstringDamit holst du über Unterhaltung abrufen den ganzen Verlauf.
{
"id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
"object": "event",
"type": "reply.received",
"created_at": "2026-11-05T14:03:40.117Z",
"account_id": "a9PzK2vRtM",
"data": {
"lead": {
"id": "msgOtJ8dvT",
"object": "lead",
"profile": {
"x_user_id": "1460283925",
"username": "jane_builds",
"name": "Jane Doe",
"bio": "Runs a paid trading community. Daily setups, no hype.",
"followers_count": 12400,
"following_count": 380,
"location": "Austin, TX",
"website": "https://janedoe.com",
"profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
"verified": true,
"url": "https://x.com/jane_builds"
},
"score": 86,
"score_reason": "Runs a paid trading community and asks how to collect payments for it.",
"hot": true,
"status": "in_conversation",
"persona": {
"id": "lvWBPnytpS",
"name": "Tipsters"
},
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"conversation_id": "msgOtJ8dvT",
"locked_to": null,
"found_at": "2026-11-05T14:02:11.482Z",
"scored_at": "2026-11-05T14:03:40.117Z",
"updated_at": "2026-11-05T14:03:40.117Z",
"metadata": {}
},
"message": {
"id": "1985321409876543210",
"object": "message",
"direction": "inbound",
"text": "Yes, I want to charge for my Discord. How does it work?",
"created_at": "2026-11-06T08:12:44.000Z",
"media": [],
"reactions": [],
"encrypted": false,
"reply_to_message_id": null
},
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"conversation_id": "msgOtJ8dvT"
}
}reaction.received
Ein Lead reagiert mit einem Emoji auf eine deiner Nachrichten. Jedes Emoji des Leads auf einer Nachricht löst es einmal aus.
{
"id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
"object": "event",
"type": "reaction.received",
"created_at": "2026-11-05T14:03:40.117Z",
"account_id": "a9PzK2vRtM",
"data": {
"lead": {
"id": "msgOtJ8dvT",
"object": "lead",
"profile": {
"x_user_id": "1460283925",
"username": "jane_builds",
"name": "Jane Doe",
"bio": "Runs a paid trading community. Daily setups, no hype.",
"followers_count": 12400,
"following_count": 380,
"location": "Austin, TX",
"website": "https://janedoe.com",
"profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
"verified": true,
"url": "https://x.com/jane_builds"
},
"score": 86,
"score_reason": "Runs a paid trading community and asks how to collect payments for it.",
"hot": true,
"status": "in_conversation",
"persona": {
"id": "lvWBPnytpS",
"name": "Tipsters"
},
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"conversation_id": "msgOtJ8dvT",
"locked_to": null,
"found_at": "2026-11-05T14:02:11.482Z",
"scored_at": "2026-11-05T14:03:40.117Z",
"updated_at": "2026-11-05T14:03:40.117Z",
"metadata": {}
},
"message": {
"id": "1985329981234567890",
"object": "message",
"direction": "outbound",
"text": "Happy to show you. Do you sell picks monthly or per event?",
"created_at": "2026-11-06T08:20:03.000Z",
"media": [],
"reactions": [
{
"emoji": "👍",
"direction": "inbound",
"created_at": "2026-11-06T08:24:51.000Z"
}
],
"encrypted": false,
"reply_to_message_id": "1985321409876543210"
},
"reaction": {
"emoji": "👍",
"direction": "inbound",
"created_at": "2026-11-06T08:24:51.000Z"
}
}
}sam.suggestion.ready
Sam AI hält in einer Unterhaltung im Modus draft eine neue Antwort bereit, die du senden kannst. Jeder Vorschlag löst es einmal aus, wenn er jünger als 6 Stunden ist.
Daten
- leadobjectDer Lead, dem Sam AI antwortet.
- conversation_idstringDamit liest du über Sam AI einer Unterhaltung abrufen den Vorschlag erneut oder änderst den Modus.
- campaignobject oder nullDie Kampagne des Leads, mit
id,nameundstatus. - suggestionobjectDie Antwort, die Sam AI bereithält.
{
"id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
"object": "event",
"type": "sam.suggestion.ready",
"created_at": "2026-11-05T14:03:40.117Z",
"account_id": "a9PzK2vRtM",
"data": {
"lead": {
"id": "msgOtJ8dvT",
"object": "lead",
"profile": {
"x_user_id": "1460283925",
"username": "jane_builds",
"name": "Jane Doe",
"bio": "Runs a paid trading community. Daily setups, no hype.",
"followers_count": 12400,
"following_count": 380,
"location": "Austin, TX",
"website": "https://janedoe.com",
"profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
"verified": true,
"url": "https://x.com/jane_builds"
},
"score": 86,
"score_reason": "Runs a paid trading community and asks how to collect payments for it.",
"hot": true,
"status": "in_conversation",
"persona": {
"id": "lvWBPnytpS",
"name": "Tipsters"
},
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"conversation_id": "msgOtJ8dvT",
"locked_to": null,
"found_at": "2026-11-05T14:02:11.482Z",
"scored_at": "2026-11-05T14:03:40.117Z",
"updated_at": "2026-11-05T14:03:40.117Z",
"metadata": {}
},
"conversation_id": "msgOtJ8dvT",
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"suggestion": {
"messages": [
"It takes two minutes. You set a price, members pay, and they get their Discord role right away.",
"Want the link to set it up?"
],
"stage": "answer_question",
"why": "She asked how it works, so the reply explains it in one line and offers the link.",
"replying_to_message_id": "1985321409876543210",
"created_at": "2026-11-06T08:13:20.000Z"
}
}
}sam.reply.sent
Eine Antwort von Sam AI geht von deinem X-Konto raus, selbstständig im Modus auto oder sobald du sie in der App freigibst. Jede Antwort löst es einmal aus, wenn sie jünger als 6 Stunden ist. Nachrichten, die du selbst schreibst, lösen es nie aus, du findest sie über Unterhaltung abrufen.
Daten
- leadobjectDer Lead, dem Sam AI geantwortet hat.
- conversation_idstringDamit holst du über Unterhaltung abrufen den ganzen Verlauf.
- campaignobject oder nullDie Kampagne des Leads, mit
id,nameundstatus. - messagesArray von stringsDie DMs, die Sam AI gesendet hat, in ihrer Reihenfolge.
- sent_bystring
auto, wenn Sam AI sie selbstständig gesendet hat,approved, wenn du sie in der App freigegeben hast.autoapproved - replying_to_message_idstring oder nullDie Nachricht des Leads, auf die sie geantwortet hat.
- sent_atstringWann sie rausging, ISO 8601.
{
"id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
"object": "event",
"type": "sam.reply.sent",
"created_at": "2026-11-05T14:03:40.117Z",
"account_id": "a9PzK2vRtM",
"data": {
"lead": {
"id": "msgOtJ8dvT",
"object": "lead",
"profile": {
"x_user_id": "1460283925",
"username": "jane_builds",
"name": "Jane Doe",
"bio": "Runs a paid trading community. Daily setups, no hype.",
"followers_count": 12400,
"following_count": 380,
"location": "Austin, TX",
"website": "https://janedoe.com",
"profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
"verified": true,
"url": "https://x.com/jane_builds"
},
"score": 86,
"score_reason": "Runs a paid trading community and asks how to collect payments for it.",
"hot": true,
"status": "in_conversation",
"persona": {
"id": "lvWBPnytpS",
"name": "Tipsters"
},
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"conversation_id": "msgOtJ8dvT",
"locked_to": null,
"found_at": "2026-11-05T14:02:11.482Z",
"scored_at": "2026-11-05T14:03:40.117Z",
"updated_at": "2026-11-05T14:03:40.117Z",
"metadata": {}
},
"conversation_id": "msgOtJ8dvT",
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"messages": [
"It takes two minutes. You set a price, members pay, and they get their Discord role right away.",
"Want the link to set it up?"
],
"sent_by": "auto",
"replying_to_message_id": "1985321409876543210",
"sent_at": "2026-11-06T08:14:05.000Z"
}
}sam.handoff
Sam AI übergibt dir eine Unterhaltung, wenn er ohne dich keine gute Antwort sieht, der Lead nur ein Foto oder eine Sprachnachricht geschickt hat oder seine Antwort nicht rausgehen konnte. Im Modus auto überlässt er dir danach die nächsten Nachrichten des Leads. Jede Übergabe löst es einmal aus, wenn sie jünger als 6 Stunden ist.
Daten
- leadobjectDer Lead, dem du antworten sollst.
- conversation_idstringDamit holst du über Unterhaltung abrufen den ganzen Verlauf.
- campaignobject oder nullDie Kampagne des Leads, mit
id,nameundstatus. - reasonstring oder nullWarum Sam AI sie dir übergibt, so wie er es formuliert hat.
{
"id": "evt_8kQ2vXr4LmT9wPz1Hc6YbN3d",
"object": "event",
"type": "sam.handoff",
"created_at": "2026-11-05T14:03:40.117Z",
"account_id": "a9PzK2vRtM",
"data": {
"lead": {
"id": "msgOtJ8dvT",
"object": "lead",
"profile": {
"x_user_id": "1460283925",
"username": "jane_builds",
"name": "Jane Doe",
"bio": "Runs a paid trading community. Daily setups, no hype.",
"followers_count": 12400,
"following_count": 380,
"location": "Austin, TX",
"website": "https://janedoe.com",
"profile_image_url": "https://pbs.twimg.com/profile_images/1460283925/jane_400x400.jpg",
"verified": true,
"url": "https://x.com/jane_builds"
},
"score": 86,
"score_reason": "Runs a paid trading community and asks how to collect payments for it.",
"hot": true,
"status": "in_conversation",
"persona": {
"id": "lvWBPnytpS",
"name": "Tipsters"
},
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"conversation_id": "msgOtJ8dvT",
"locked_to": null,
"found_at": "2026-11-05T14:02:11.482Z",
"scored_at": "2026-11-05T14:03:40.117Z",
"updated_at": "2026-11-05T14:03:40.117Z",
"metadata": {}
},
"conversation_id": "msgOtJ8dvT",
"campaign": {
"id": "c7RkQ2wLxe",
"name": "Tipsters warm intro",
"status": "in_progress"
},
"reason": "She wants a call before she signs up."
}
}Zustellung
Gemlead sendet jedes Ereignis als JSON-POST und wartet 10 Sekunden auf deine Antwort. Jeder 2xx gilt als zugestellt. Eine Weiterleitung, jeder andere Status, ein Timeout oder ein Verbindungsfehler gilt als Fehlschlag, und das Ereignis wird erneut gesendet.
| Header | Wert |
|---|---|
Gemlead-Signature | Der Zeitstempel und die Signatur, t=1762444800,v1=5f2b... |
Gemlead-Event-Id | Die id des Ereignisses, um bereits verarbeitete Ereignisse zu überspringen. |
Gemlead-Event-Type | Der type des Ereignisses. |
User-Agent | Gemlead-Webhooks/1.0 |
POST /webhooks/gemlead HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Gemlead-Webhooks/1.0
Gemlead-Event-Id: evt_8kQ2vXr4LmT9wPz1Hc6YbN3d
Gemlead-Event-Type: lead.hot
Gemlead-Signature: t=1762444800,v1=58ca5e964b92d617c979d3f067cdc2035a1a1a9d3f848d7d927c2db09b8e9baaSignaturen prüfen
Jeder kann eine Anfrage an deine URL schicken. Prüfe bei jeder, ob sie von Gemlead kommt, bevor du ihr vertraust.
- Lies den rohen Body als Bytes, vor jedem JSON-Parsing. Parsen und erneutes Schreiben verändert die Bytes.
- Teile den Header
Gemlead-Signaturean den Kommas.tist eine Unix-Zeit in Sekunden,v1die Signatur. - Berechne den HMAC SHA256 aus
t, einem Punkt und dem rohen Body, mit dem ganzen Secret des Endpoints als Schlüssel,whsec_eingeschlossen, und kodiere ihn als Hex. - Vergleiche ihn in konstanter Zeit mit jedem
v1. - Lehne ein
tab, das mehr als 5 Minuten von deiner Uhr abweicht, damit sich eine alte Anfrage nicht wieder einspielen lässt. Jeder neue Versuch wird mit einem frischentsigniert.
Antworte mit 400, wenn die Prüfung fehlschlägt. Bewahre das Secret in einer Umgebungsvariable wie GEMLEAD_WEBHOOK_SECRET auf.
const crypto = require("crypto");
const express = require("express");
// rawBody: the request body exactly as received, before any JSON parsing.
function verifyGemleadSignature(rawBody, header, secret, toleranceSeconds = 300) {
if (typeof header !== "string") return false;
let timestamp = null;
const signatures = [];
for (const part of header.split(",")) {
const [key, value] = part.split("=", 2).map((s) => (s || "").trim());
if (key === "t") timestamp = value;
if (key === "v1" && value) signatures.push(value);
}
if (!/^\d+$/.test(timestamp || "") || signatures.length === 0) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSeconds) return false;
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.`).update(rawBody).digest();
return signatures.some((signature) => {
const given = Buffer.from(signature, "hex");
return given.length === expected.length && crypto.timingSafeEqual(given, expected);
});
}
const app = express();
// The body must stay raw on this route.
app.post("/webhooks/gemlead", express.raw({ type: "application/json" }), (req, res) => {
const ok = verifyGemleadSignature(
req.body,
req.get("Gemlead-Signature"),
process.env.GEMLEAD_WEBHOOK_SECRET,
);
if (!ok) return res.status(400).send("Invalid signature");
const event = JSON.parse(req.body.toString("utf8"));
// Already handled? Skip it, retries send the same event.id again.
if (event.type === "lead.created") {
// event.data.object is the new lead, hot or not
} else if (event.type === "lead.hot") {
// event.data.object is the lead
} else if (event.type === "reply.received") {
// event.data.lead, event.data.message, event.data.campaign, event.data.conversation_id
}
res.sendStatus(200);
});
app.listen(3000);Wiederholungen
Schlägt eine Zustellung fehl, versucht Gemlead es noch 7-mal, mit jeweils längerer Pause. Nach dem 8. Versuch, etwa 45 Stunden nach dem ersten, wird die Zustellung als fehlgeschlagen markiert.
| Versuch | Gesendet |
|---|---|
| 1 | Sofort |
| 2 | 1 Minute nach dem vorherigen Fehlschlag |
| 3 | 5 Minuten nach dem vorherigen Fehlschlag |
| 4 | 30 Minuten nach dem vorherigen Fehlschlag |
| 5 | 2 Stunden nach dem vorherigen Fehlschlag |
| 6 | 6 Stunden nach dem vorherigen Fehlschlag |
| 7 | 12 Stunden nach dem vorherigen Fehlschlag |
| 8 | 24 Stunden nach dem vorherigen Fehlschlag |
Ein Endpoint, der 3 Tage in Folge fehlschlägt, mit mindestens 8 fehlgeschlagenen Versuchen, wird deaktiviert. Sein status wechselt auf disabled, sein disabled_reason auf failing, und die noch wartenden Zustellungen enden als fehlgeschlagen. Repariere deinen Server und schalte den Endpoint dann in der App oder mit Webhook-Endpoint ändern wieder ein, damit beginnt die Zählung von vorn. Testereignisse werden einmal gesendet und zählen nie mit.
Zustellungen auflisten zeigt Statuscode und Fehler jedes Versuchs, damit du siehst, was dein Server geantwortet hat.
Best Practices
- Antworte innerhalb von 10 Sekunden mit 2xx und erledige die Arbeit danach in einer Queue.
- Jedes Ereignis wird mindestens einmal zugestellt. Nutze seine
id, die auch inGemlead-Event-Idsteht, um ein bereits verarbeitetes Ereignis zu überspringen. - Ereignisse können in falscher Reihenfolge ankommen. Vergleiche
created_atoder rufe den Lead erneut ab, um seinen aktuellen Stand zu bekommen. - Prüfe jede Signatur und lehne alte Zeitstempel ab.
- Wenn du das Secret erneuerst, wird es sofort ersetzt. Deploye das neue direkt danach. Zustellungen, die in der Zwischenzeit fehlschlagen, werden wiederholt und mit dem neuen signiert.
- Ereignisse und Zustellungen werden 30 Tage aufbewahrt.