Webhook

Webhook

Gemlead invia una richiesta HTTPS al tuo server nel momento in cui un lead viene trovato, diventa caldo, risponde o reagisce al tuo messaggio, oppure quando Sam AI ha una risposta pronta, ne invia una o ti passa una conversazione. È firmata, così sai che arriva da noi.

Configura un endpoint

Aggiungi un endpoint nell'app, alla voce API, oppure con Crea un endpoint webhook. Dagli un URL HTTPS pubblico e i tipi di evento che vuoi, poi conserva il secret che restituisce per verificare le firme.

  • Solo HTTPS, nessuna credenziale nell'URL e nessun indirizzo privato, di loopback o link local.
  • Fino a 10 endpoint per account.
  • filters.persona_ids limita gli eventi che riceve un endpoint ai lead di alcune buyer persona, qualunque sia il tipo di evento.
  • Invia un evento di test per verificare il tuo server prima che arrivino gli eventi reali.

I webhook sono inclusi nei piani Business ed Enterprise. Se l'account passa a Free o Starter, i suoi endpoint restano ma non inviano nulla finché non torna a Business o Enterprise.

POST/v1/webhook_endpoints
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"]
    }
  }'

Tipi di evento

Ogni evento ha la stessa struttura. Il suo data dipende dal suo type.

TipoInviato quando
lead.createdGemlead trova e valuta un nuovo lead, qualunque sia il punteggio. Arriva una sola volta per ogni lead, con il suo primo punteggio, e solo entro 3 giorni da quando è stato trovato, quindi una nuova valutazione di un lead più vecchio non lo invia mai. Un lead che ottiene subito 60 o più invia anche lead.hot.
lead.hotIl punteggio di un lead raggiunge 60 o più per la prima volta. Arriva una sola volta per ogni lead, una nuova valutazione non lo invia più.
reply.receivedUn lead ti invia un nuovo messaggio, in una campagna o no. Arriva una volta per ogni messaggio che ha meno di 6 ore. Quando arrivano molti messaggi del lead insieme, lo inviano solo i 5 più recenti.
reaction.receivedUn lead reagisce a uno dei tuoi messaggi con un'emoji. Arriva una volta per ogni emoji del lead su un messaggio.
sam.suggestion.readySam AI ha pronta una nuova risposta da inviare, in una conversazione in modalità draft. Arriva una volta per ogni suggerimento che ha meno di 6 ore.
sam.reply.sentUna risposta di Sam AI parte dal tuo account X, da sola in modalità auto o dopo che l'hai approvata nell'app. Arriva una volta per ogni risposta che ha meno di 6 ore. I messaggi che scrivi tu non lo inviano mai, li ritrovi con Recupera una conversazione.
sam.handoffSam AI ti passa una conversazione quando non vede una buona risposta senza di te, quando il lead ha inviato solo una foto o un messaggio vocale, o quando la sua risposta non è riuscita a partire. In modalità auto lascia poi a te i messaggi successivi del lead. Arriva una volta per ogni passaggio che ha meno di 6 ore.

L'oggetto evento

  • idstring
    Identificatore univoco dell'evento, evt_ e 24 caratteri. Presente anche nell'header Gemlead-Event-Id.
  • objectstring
    Sempre event.
  • typestring
    Il tipo di evento.
    lead.createdlead.hotreply.receivedreaction.receivedsam.suggestion.readysam.reply.sentsam.handoff
  • created_atstring
    Quando è avvenuto l'evento, ISO 8601.
  • account_idstring
    L'account Gemlead su cui è avvenuto.
  • dataobject
    Il contenuto dell'evento, che dipende dal suo tipo.

lead.created

Gemlead trova e valuta un nuovo lead, qualunque sia il punteggio. Arriva una sola volta per ogni lead, con il suo primo punteggio, e solo entro 3 giorni da quando è stato trovato, quindi una nuova valutazione di un lead più vecchio non lo invia mai. Un lead che ottiene subito 60 o più invia anche lead.hot.

Dati

lead.created
{
  "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

Il punteggio di un lead raggiunge 60 o più per la prima volta. Arriva una sola volta per ogni lead, una nuova valutazione non lo invia più.

Dati

lead.hot
{
  "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

Un lead ti invia un nuovo messaggio, in una campagna o no. Arriva una volta per ogni messaggio che ha meno di 6 ore. Quando arrivano molti messaggi del lead insieme, lo inviano solo i 5 più recenti.

Dati

  • leadobject
    Il lead che ha scritto.
  • messageobject
    Il nuovo messaggio, con direction impostato su inbound.
  • campaignobject o null
    La campagna in cui si trova il lead, con id, name e status.
  • conversation_idstring
    Usalo con Recupera una conversazione per avere tutto il thread.
reply.received
{
  "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

Un lead reagisce a uno dei tuoi messaggi con un'emoji. Arriva una volta per ogni emoji del lead su un messaggio.

Dati

  • leadobject
    Il lead che ha reagito.
  • messageobject
    Il tuo messaggio a cui il lead ha reagito, con direction impostato su outbound.
  • reactionobject
    La nuova reazione, con direction impostato su inbound.
reaction.received
{
  "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 ha pronta una nuova risposta da inviare, in una conversazione in modalità draft. Arriva una volta per ogni suggerimento che ha meno di 6 ore.

Dati

  • leadobject
    Il lead a cui risponde Sam AI.
  • conversation_idstring
    Usalo con Recupera il Sam AI di una conversazione per rileggere il suggerimento o cambiare la modalità.
  • campaignobject o null
    La campagna in cui si trova il lead, con id, name e status.
  • suggestionobject
    La risposta che Sam AI ha pronta.
sam.suggestion.ready
{
  "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

Una risposta di Sam AI parte dal tuo account X, da sola in modalità auto o dopo che l'hai approvata nell'app. Arriva una volta per ogni risposta che ha meno di 6 ore. I messaggi che scrivi tu non lo inviano mai, li ritrovi con Recupera una conversazione.

Dati

  • leadobject
    Il lead a cui ha risposto Sam AI.
  • conversation_idstring
    Usalo con Recupera una conversazione per avere tutto il thread.
  • campaignobject o null
    La campagna in cui si trova il lead, con id, name e status.
  • messagesarray di strings
    I DM che Sam AI ha inviato, in ordine.
  • sent_bystring
    auto quando Sam AI l'ha inviata da solo, approved quando l'hai approvata tu nell'app.
    autoapproved
  • replying_to_message_idstring o null
    Il messaggio del lead a cui ha risposto.
  • sent_atstring
    Quando è partita, ISO 8601.
sam.reply.sent
{
  "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 ti passa una conversazione quando non vede una buona risposta senza di te, quando il lead ha inviato solo una foto o un messaggio vocale, o quando la sua risposta non è riuscita a partire. In modalità auto lascia poi a te i messaggi successivi del lead. Arriva una volta per ogni passaggio che ha meno di 6 ore.

Dati

  • leadobject
    Il lead a cui rispondere.
  • conversation_idstring
    Usalo con Recupera una conversazione per avere tutto il thread.
  • campaignobject o null
    La campagna in cui si trova il lead, con id, name e status.
  • reasonstring o null
    Perché Sam AI te la passa, come l'ha spiegato.
sam.handoff
{
  "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."
  }
}

Consegna

Gemlead invia ogni evento come POST JSON e attende la tua risposta per 10 secondi. Qualsiasi 2xx conta come consegnato. Un redirect, qualsiasi altro stato, un timeout o un errore di connessione contano come fallimento, e l'evento viene inviato di nuovo.

HeaderValore
Gemlead-SignatureIl timestamp e la firma, t=1762444800,v1=5f2b...
Gemlead-Event-IdL'id dell'evento, per saltare gli eventi che hai già gestito.
Gemlead-Event-TypeIl type dell'evento.
User-AgentGemlead-Webhooks/1.0
Richiesta
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=58ca5e964b92d617c979d3f067cdc2035a1a1a9d3f848d7d927c2db09b8e9baa

Verifica le firme

Chiunque può inviare una richiesta al tuo URL. Verifica che ognuna arrivi da Gemlead prima di fidarti.

  1. Leggi il body grezzo come byte, prima di qualsiasi parsing JSON. Fare il parsing e riscriverlo cambia i byte.
  2. Dividi l'header Gemlead-Signature sulle virgole. t è un timestamp Unix in secondi, v1 è la firma.
  3. Calcola l'HMAC SHA256 di t, un punto e il body grezzo, usando come chiave l'intero segreto dell'endpoint, whsec_ compreso, e scrivilo in esadecimale.
  4. Confrontalo con ogni v1 in tempo costante.
  5. Rifiuta un t che si discosta di più di 5 minuti dal tuo orologio, così nessuno può riprodurre una vecchia richiesta. Ogni nuovo tentativo è firmato con un t nuovo.

Rispondi 400 quando la verifica fallisce. Conserva il segreto in una variabile d'ambiente come GEMLEAD_WEBHOOK_SECRET.

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);

Nuovi tentativi

Quando una consegna fallisce, Gemlead riprova 7 volte, ogni volta dopo un'attesa più lunga. Dopo l'8º tentativo, circa 45 ore dopo il primo, la consegna viene segnata come fallita.

TentativoInviato
1Subito
21 minuto dopo il fallimento precedente
35 minuti dopo il fallimento precedente
430 minuti dopo il fallimento precedente
52 ore dopo il fallimento precedente
66 ore dopo il fallimento precedente
712 ore dopo il fallimento precedente
824 ore dopo il fallimento precedente

Un endpoint che fallisce per 3 giorni di fila, con almeno 8 tentativi falliti, viene disattivato. Il suo status diventa disabled, il suo disabled_reason diventa failing e le consegne ancora in attesa finiscono come fallite. Sistema il tuo server, poi riattivalo nell'app o con Aggiorna un endpoint webhook, che fa ripartire il conteggio. Gli eventi di test vengono inviati una sola volta e non vengono mai conteggiati.

Elenca le consegne mostra il codice di stato e l'errore di ogni tentativo, così vedi cosa ha risposto il tuo server.

Buone pratiche

  • Rispondi 2xx entro 10 secondi, poi esegui il lavoro in una coda.
  • Ogni evento viene consegnato almeno una volta. Usa l'id dell'evento, presente anche in Gemlead-Event-Id, per saltare un evento che hai già gestito.
  • Gli eventi possono arrivare in ordine sparso. Confronta created_at, oppure recupera di nuovo il lead per avere il suo stato più recente.
  • Verifica ogni firma e rifiuta i timestamp vecchi.
  • Quando rinnovi il segreto, viene sostituito all'istante. Fai subito il deploy di quello nuovo. Le consegne che falliscono nel frattempo vengono ritentate e firmate con il nuovo.
  • Eventi e consegne vengono conservati 30 giorni.