Endpoint Invii email
GET /api/v1/sends — stato corrente degli invii email, filtrabile per campagna, stato e data di creazione.
L'endpoint sends restituisce gli invii email dell'organizzazione. Ogni riga rappresenta un invio e mostra il suo stato corrente, insieme alle date disponibili per invio, consegna, apertura e clic.
Non è uno stream delle transizioni attraversate. Se un invio già esistente cambia stato dopo la creazione, il filtro since non lo ripropone: per ricevere notifiche asincrone sui cambiamenti usa i webhook.
GET /api/v1/sends
Scope richiesto: sends:read
Query params
| Param | Tipo | Default | Descrizione |
|---|---|---|---|
limit | int | 100 | 1–500 |
since | ISO timestamp | — | Restituisce sends con created_at > questo valore |
campaignId | UUID | — | Filtra per una specifica campagna |
status | enum | — | queued | sent | delivered | opened | clicked | bounced | complained | suppressed | failed | delayed |
Gli invii sono ordinati per created_at ascendente. Il parametro since filtra la data di creazione della riga, non la data del suo ultimo aggiornamento.
Esempio cURL
curl -s -H "Authorization: Bearer $SMARTCQ_KEY" \
"https://app.smartcq.it/api/v1/sends?since=2026-05-09T00:00:00Z&limit=200"
Risposta 200
{
"data": [
{
"id": "00000000-0000-0000-0000-000000000a01",
"campaignId": "00000000-0000-0000-0000-000000000c01",
"contactId": "00000000-0000-0000-0000-000000000001",
"status": "delivered",
"sentAt": "2026-05-10T08:00:00.000Z",
"deliveredAt": "2026-05-10T08:00:03.000Z",
"openedAt": null,
"clickedAt": null,
"error": null,
"createdAt": "2026-05-10T08:00:00.000Z"
}
],
"next": "2026-05-10T08:00:00.000Z"
}
Riconciliazione per data di creazione
let since = loadCheckpoint() ?? "1970-01-01T00:00:00.000Z";
while (true) {
const url = new URL("https://app.smartcq.it/api/v1/sends");
url.searchParams.set("since", since);
url.searchParams.set("limit", "500");
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.SMARTCQ_KEY}` },
});
const j = await res.json();
for (const send of j.data) {
await reconcileSend(send);
}
if (j.data.length > 0) {
since = j.data.at(-1).createdAt;
saveCheckpoint(since);
}
if (j.next === null) {
break;
}
since = j.next;
}
Deduplica sempre per id. Poiché il cursore è un timestamp con confronto stretto, per volumi elevati è prudente ripartire da un piccolo intervallo precedente e scartare gli identificativi già elaborati.
Nota — L'endpoint è adatto a elenchi, backfill e riconciliazioni. Per non perdere un bounce o un'altra variazione successiva alla creazione della riga, usa i webhook oppure riesegui periodicamente una riconciliazione più ampia.