REST reference
Every REST endpoint grouped by area. Base https://sending.dev/api/v1
Every route lives under https://sending.dev/api/v1 and requires the
Authorization: Bearer sk_... header.
Email e messaggi
| POST | /api/v1/emails | Invia un'email transazionale. `idempotencyKey` nel body obbligatoria (min 8 char); `from`/`replyTo` accettano 'Nome <a@b.com>'; `replyTo` anche piu' indirizzi (virgola o array, max 10); solo `text` senza `html` = email di solo testo.(scope: email:send) |
| GET | /api/v1/emails | Elenca gli invii col riassunto di engagement (aperture umane e da proxy, click, click sul contenuto); filtri campaignId, contactId, status, engagement, q, since.(scope: emails:read|email:send) |
| GET | /api/v1/emails/:id | Stato di un invio: metadati, engagement, link cliccati col ruolo e timeline eventi (sui click: linkUrl, linkId, linkRole). |
| POST | /api/v1/messages | Invio transazionale unificato email/WhatsApp/Telegram.(scope: messages:send) |
Allegati
| GET/POST | /api/v1/attachments | Elenca o carica un allegato riusabile: `content` base64 per l'upload immediato, `size` per ottenere una `uploadUrl` firmata (file grandi).(scope: email:send|inbox:send) |
| GET/DELETE | /api/v1/attachments/:id | Metadati + URL di download firmata, oppure eliminazione.(scope: email:send|inbox:send) |
| POST | /api/v1/attachments/:id/confirm | Conferma un upload firmato (allinea dimensione e Content-Type reali).(scope: email:send|inbox:send) |
Domini
| GET/POST | /api/v1/domains | Elenca o aggiungi un dominio (ritorna i record DNS).(scope: domains:write) |
| GET/PATCH | /api/v1/domains/:id | Dettaglio dominio e nome mittente di default (display name del From).(scope: domains:write) |
| POST | /api/v1/domains/:id/verify | Verifica SPF, DKIM, DMARC.(scope: domains:write) |
| POST/DELETE | /api/v1/domains/:id/inbound | Abilita o disabilita la ricezione inbound (MX) per il dominio.(scope: domains:write) |
Contatti e CRM
| GET/POST | /api/v1/contacts | Elenca o crea contatti (con attributi e campi).(scope: contacts:read|write) |
| POST/DELETE | /api/v1/contacts/:id/tags | Aggiungi o rimuovi tag a un contatto.(scope: contacts:write) |
| GET/POST | /api/v1/tags | Elenca o crea tag.(scope: contacts:write) |
| DELETE | /api/v1/tags/:id | Elimina un tag.(scope: contacts:write) |
| GET/POST | /api/v1/lists | Elenca o crea liste.(scope: contacts:write) |
| DELETE | /api/v1/lists/:id | Elimina una lista.(scope: contacts:write) |
| POST/DELETE | /api/v1/lists/:id/contacts | Aggiungi o rimuovi contatti da una lista.(scope: contacts:write) |
| GET/POST | /api/v1/segments | Elenca o crea segmenti (rule tree AudienceRules).(scope: contacts:write) |
| PATCH/DELETE | /api/v1/segments/:id | Aggiorna o elimina un segmento.(scope: contacts:write) |
| POST | /api/v1/segments/preview | Stima i contatti che matchano un segmento.(scope: contacts:read) |
| GET/POST | /api/v1/custom-fields | Elenca o crea campi personalizzati.(scope: contacts:write) |
Eventi e automazioni
| POST | /api/v1/events | Invia un evento (trigger/goal automazioni, conversioni con properties.value): `idempotencyKey` opzionale, con la stessa chiave un retry risponde 200 duplicate.(scope: events:write) |
| GET | /api/v1/automations | Elenca le automazioni con stato ed evento che le innesca (guardalo prima di scrivere su liste/tag).(scope: automations:read) |
| POST | /api/v1/automations | Crea un'automazione (Journey DAG) in bozza.(scope: automations:write) |
| GET | /api/v1/automations/:id | Dettaglio con il DAG pubblicato.(scope: automations:read) |
| GET | /api/v1/automations/:id/stats | Per nodo: passi fatti/saltati/falliti, metriche email (aperture umane, click, click sul contenuto), link piu' cliccati col ruolo, conversioni; `?since=`, `?attribution=`.(scope: automations:read) |
| POST | /api/v1/automations/:id/activate | Attiva un'automazione.(scope: automations:write) |
Template
| GET/POST | /api/v1/templates | Elenca o crea un template di contenuto riusabile (e' cosi' che si ottiene un templateId valido).(scope: templates:read|write) |
| GET/PATCH | /api/v1/templates/:id | Dettaglio col contenuto, oppure modifica parziale (i campi assenti restano).(scope: templates:read|write) |
| DELETE | /api/v1/templates/:id | Elimina un template: 409 se una campagna lo usa ancora.(scope: templates:write) |
Campagne
| GET/POST | /api/v1/campaigns | Elenca (con `?metrics=1` il riassunto dei risultati per riga) o crea una campagna broadcast.(scope: campaigns:write) |
| GET | /api/v1/campaigns/:id | Dettaglio campagna, contenuto incluso.(scope: campaigns:read) |
| GET | /api/v1/campaigns/:id/metrics | Risultati: consegne, aperture umane, click e click sul contenuto, tassi; `?links=1` click per link col ruolo, `?conversions=1|first`, `?timeseries=day|hour`.(scope: campaigns:read) |
| PATCH | /api/v1/campaigns/:id | Modifica una bozza: solo i campi presenti, senza ricreare la campagna.(scope: campaigns:write) |
| POST | /api/v1/campaigns/:id/estimate | Stima i destinatari.(scope: campaigns:write) |
| POST | /api/v1/campaigns/:id/send | Invia o schedula la campagna.(scope: campaigns:write) |
| POST | /api/v1/campaigns/:id/cancel | Annulla una campagna schedulata.(scope: campaigns:write) |
Agent Email (inbox per agenti)
| GET/POST | /api/v1/inboxes | Elenca o crea una agent inbox.(scope: inbox:read|write) |
| GET/PATCH/DELETE | /api/v1/inboxes/:id | Dettaglio, aggiorna o elimina una inbox.(scope: inbox:read|write) |
| POST | /api/v1/inboxes/:id/send | Invia un'email dalla inbox.(scope: inbox:send) |
| POST | /api/v1/inboxes/:id/drafts | Crea una bozza nella inbox.(scope: inbox:write) |
| GET | /api/v1/inboxes/:id/threads | Elenca i thread della inbox.(scope: inbox:read) |
| GET | /api/v1/inboxes/:id/threads/:threadId | Dettaglio thread con messaggi.(scope: inbox:read) |
| POST | /api/v1/inboxes/:id/threads/:threadId/reply | Rispondi a un thread.(scope: inbox:send) |
| GET | /api/v1/inboxes/metrics | Metriche agent email (volumi, consegna, bounce).(scope: inbox:read) |
Webhooks
| GET/POST | /api/v1/webhooks | Elenca o crea un endpoint webhook (secret one-time).(scope: webhooks:read|write) |
| GET/PATCH/DELETE | /api/v1/webhooks/:id | Dettaglio, aggiorna o elimina un webhook.(scope: webhooks:read|write) |
| GET | /api/v1/webhooks/:id/deliveries | Log delle consegne di un webhook.(scope: webhooks:read) |
Allow/Block (regole inbound)
| GET/POST | /api/v1/email-rules | Elenca o crea regole allow/block per le inbox.(scope: inbox:read|write) |
| DELETE | /api/v1/email-rules/:id | Elimina una regola allow/block.(scope: inbox:write) |
UTM e attribuzione
| GET | /api/v1/utm/touches | Touch UTM (con ?format=csv).(scope: utm:read) |
| GET | /api/v1/utm/conversions | Conversioni attribuite (first/last).(scope: utm:read) |
| GET | /api/v1/utm/summary | Riepilogo attribuzione.(scope: utm:read) |
E-commerce
| PUT | /api/v1/commerce/products | Upsert del catalogo prodotti (max 500).(scope: commerce:write) |
| GET | /api/v1/commerce/products | Prodotti del catalogo.(scope: commerce:read) |
| POST | /api/v1/commerce/carts | Upsert di un carrello (abbandono).(scope: commerce:write) |
| POST | /api/v1/commerce/orders | Notifica un ordine pagato (trigger di acquisto e attribuzione).(scope: commerce:write) |
| GET | /api/v1/commerce/orders | Ordini di negozi e API, col messaggio a cui sono attribuiti.(scope: commerce:read) |
| GET | /api/v1/contacts/:id/commerce | Acquisti di un contatto: ordini, speso per valuta, ultimi ordini.(scope: commerce:read) |
Integrazioni e usage
| POST | /api/v1/integrations/posthog/sync | Lancia il sync delle conversioni da PostHog.(scope: integrations:write) |
| GET | /api/v1/usage | Snapshot uso vs piano del workspace. |
Rate limits
Each API key gets 10 requests per second. The count is per key, not per workspace: two integrations in the same workspace have separate budgets, so a runaway one cannot take the others down.
Every response carries the current state:
| Header | Meaning |
|---|---|
RateLimit-Limit | Requests allowed in the window. |
RateLimit-Remaining | How many are left. |
RateLimit-Reset | Seconds until the window resets. |
Past the limit the response is 429 with Retry-After in seconds and a body of
{ "error": "rate_limit_exceeded", "limit": 10, "retryAfter": 1 }. Honour Retry-After and
add exponential backoff with jitter on further attempts.
One call to POST /api/v1/emails/batch counts as one request, whatever
its 100 items contain: it is the intended way to send a lot of email without going near the
limit.
What is not a rate limit
- Plan quota: the number of messages per month is a different thing and answers
402or403, not429. Where overage is enabled, anything past the included allowance is billed on usage. - Outbound throughput to SES: accepted sends go through a queue that pushes roughly 14
messages per second overall. A batch accepted in one second can take more than a second to
actually leave:
202and207mean "accepted", not "already sent".