Spedito · API

Spedito API

Add contacts, tag them, start automations and react to what happens, from your own code, Zapier or Make.

Authentication

Create a key in Integrations › Developers and send it in every request. Keys start with sp_live_, are shown only once and can be revoked any time. Up to 600 requests a minute per key.

curl https://www.getspedito.com/api/v1/me -H "Authorization: Bearer sp_live_…"

Endpoints

MethodPathWhat it does
GET/meThe account behind the key (use it to test the connection).
POST/contactsAdd a contact, or update it if the email exists. New contacts need "consent": true.
GET/contactsList contacts, newest first. ?email=, ?status=, ?label=, ?since=, ?limit= (max 100), ?cursor=
GET/contacts/{id or email}One contact.
PATCH/contacts/{id or email}Update details (never the subscription).
DELETE/contacts/{id or email}Delete a contact and its history (GDPR erasure).
POST/contacts/{id or email}/unsubscribeUnsubscribe.
POST/contacts/{id or email}/labelsAdd labels: {"labels": ["VIP"]}. Starts "label added" automations.
DELETE/contacts/{id or email}/labels?labels=VIPRemove labels.
GET/labelsLabels with the number of subscribed contacts.
GET/automationsAutomations and their status.
POST/automations/{id}/startPut a subscribed contact into an active automation: {"email": "…"}.
POST/eventsA purchase, an abandoned cart or a booking from your own system (see below).
GET/campaignsSent and scheduled emails with their numbers.
POST/hooksSubscribe a URL to an event (REST hooks for Zapier and Make).
DELETE/hooks/{id}Remove a subscription.

Base URL: https://www.getspedito.com/api/v1. Bodies are JSON (form-encoded works too). Errors return {"error": "code", "message": "…"} with a 4xx status.

Add a contact

curl https://www.getspedito.com/api/v1/contacts \
  -H "Authorization: Bearer sp_live_…" -H "Content-Type: application/json" \
  -d '{"email":"anna@example.com","first_name":"Anna","language":"de","labels":["VIP"],"birthday":"14/06","consent":true}'

Only add people who agreed to receive your emails: consent is required for new contacts and is saved as proof. People who unsubscribed are not subscribed again unless you also send "resubscribe": true because they asked. Automations that start when someone subscribes run unless you send "automations": false.

Purchases, carts and bookings

POST /events
{"type":"purchase","email":"anna@example.com","order_id":"1001","total":49.9,"currency":"EUR"}
{"type":"cart","email":"anna@example.com","cart_id":"c-77","url":"https://shop.example/cart/c-77","total":30,"completed":false}
{"type":"booking","email":"anna@example.com","booking_id":"b-9","name":"Haircut","at":"2026-11-02T10:00:00Z"}

Carts not completed within an hour start the “abandoned cart” automation; the cart link in those emails takes each person to the url you sent.

Webhooks

Spedito sends a POST to your URL when something happens: subscribed unsubscribed opened clicked bounced . Create them in Integrations, or via POST /hooks with {"url": "https://…", "event": "subscribed"}.

POST https://your.app/spedito
X-Spedito-Event: subscribed
X-Spedito-Signature: t=1792150000,v1=5d41402abc4b2a76b9719d911017c592…

{"event":"subscribed","created_at":"2026-10-16T09:30:00Z","data":[{"id":"…","email":"anna@example.com"}]}

Check the signature: compute HMAC-SHA256 of `${t}.${raw body}` with the webhook secret and compare it with v1; reject requests older than 5 minutes. Answer with a 2xx within 10 seconds; failed deliveries are retried with increasing delays. Answer 410 to remove the subscription.

import crypto from 'node:crypto';
function verify(secret, header, body) {
  const { t, v1 } = Object.fromEntries(header.split(',').map(p => p.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const mac = crypto.createHmac('sha256', secret).update(`${t}.${body}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(v1));
}