Public API

HTTP endpoints for contacts, transactional sends, sequences, and forms.

Auth

Every endpoint accepts the brand API key two ways:

  • In the URL: /api/public/contacts/<API_KEY>
  • Bearer header: Authorization: Bearer <API_KEY>

Find the key under Brand settings → API. CORS is open — these endpoints can be called from a browser.

Contacts

Upsert

POST /api/public/contacts/<API_KEY>
{
  "email": "[email protected]",
  "first_name": "Alice",
  "tags": ["signup", "free-trial"]
}

Idempotent by email. Tags are additive — existing tags survive.

Update

PUT /api/public/contacts/<API_KEY>/update
{
  "email": "[email protected]",
  "status": "unsubscribed"
}

Delete

DELETE /api/public/contacts/<API_KEY>/[email protected]

Hard delete. Cascades to events, send history, list memberships.

Move between tags/lists

POST /api/public/contacts/<API_KEY>/move
{
  "email": "[email protected]",
  "add_to": ["paid"],
  "remove_from": ["free-trial"]
}

Transactional

POST /api/public/transactional/<API_KEY>/send
{
  "template_id": "tpl_welcome",
  "to": "[email protected]",
  "variables": { "name": "Alice" }
}

See Transactional API for full details.

Sequences

POST /api/public/sequences/<API_KEY>/enroll
{
  "sequence_id": "seq_xxx",
  "email": "[email protected]"
}

Manually enroll a contact. Returns 200 if enrolled, 409 if already in the sequence.

Forms

POST /api/public/forms/<slug>/submit
{
  "email": "[email protected]",
  "fields": { "company": "Acme", "size": "10-50" }
}

No API key required — forms are public by design.

Rate limits
Per-brand: 100 req/min on writes, 600 req/min on reads. Trips return 429 Too Many Requests with Retry-After.