Skip to content

Developers

Four recipes that match the API

Create a subscriber, import a list, save a campaign draft, and check a webhook signature. Every path below is a real route. The key’s project is applied for you — do not send a different one.

Create a subscriber

One person, with an email or a phone. Status is stored as active. Tags, groups and consent are not part of this call.

curl -X POST https://api.connect.carriercrow.com/subscribers \
  -H "content-type: application/json" \
  -H "x-api-key: $CCC_API_KEY" \
  -d '{"email":"ada@example.com","firstName":"Ada","lastName":"Lovelace"}'

Import subscribers

One request with every row in data. The UI’s chunked upload is a different call; this is the shape an API key uses. Each row needs an email or a phone.

curl -X POST https://api.connect.carriercrow.com/subscriber-imports \
  -H "content-type: application/json" \
  -H "x-api-key: $CCC_API_KEY" \
  -d '{"data":[{"email":"ada@example.com","firstName":"Ada"},{"email":"grace@example.com","tags":["launch"]}]}'

Create a campaign draft

Leave status off and the API stores a draft. Nothing in this request sends the campaign. templateId, when you send one, has to belong to the same project.

curl -X POST https://api.connect.carriercrow.com/campaigns \
  -H "content-type: application/json" \
  -H "x-api-key: $CCC_API_KEY" \
  -d '{"name":"October note","type":"standard","subject":"A short note","templateId":"TEMPLATE_ID"}'

Verify a webhook signature

When the channel has a secret, the request carries X-CarrierCrow-Signature. Recompute HMAC-SHA256 over the raw body bytes, prefix sha256=, and compare in constant time. Re-encoding the JSON will not match.

import { createHmac, timingSafeEqual } from 'node:crypto'

export const verifyCarrierCrowSignature = (rawBody, header, secret) => {
  const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')
  const a = Buffer.from(expected)
  const b = Buffer.from(String(header || ''))
  return a.length === b.length && timingSafeEqual(a, b)
}