Send your first campaign

Make a template, choose an audience, run the pre-send checks, test it and send or schedule.

Embed
Preview of the card
<a href="https://hermeticor.com/guides/first-campaign"><img src="https://hermeticor.com/guides/_api/public/orgs/5fcd8b3c-a27c-4688-972f-de710125592f/spaces/9a3da731-ded5-4536-b84f-8c9a61420ff4/pages/ec48489e-67f3-4051-968b-d7f7f6109be3/social-card.svg?v=3e7ae33eec8b" alt="Send your first campaign" width="600" height="315"></a>

What you need first

  • A healthy connection and a verified sender (see Connect a sending provider).

  • A postal address on the workspace (set in the Quickstart). Marketing email needs one in its footer.

  • People with marketing consent, on a list or in a segment.

  • A key with templates:write, campaigns:write and campaigns:send.

1. Make a template

curl -s -X POST "$BASE/v1/templates" \
  -H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: tpl-update-nov" \
  -d '{"name":"Product update: November","kind":"blocks",
       "version":{"subject":"{{ profile.first_name | default: \"Hi\" }}, what is new in November","preheader":"Three things.",
         "body":{"kind":"blocks","doc":{"blocks":[
           {"type":"text","html":"<h1>What is new</h1><p>...</p>"},
           {"type":"button","label":"Read more","href":"https://example.com/changelog"},
           {"type":"text","html":"<p><a href=\"{{ unsubscribe_url }}\">Unsubscribe</a></p>"}]}}}}'

Check how it renders for one person:

curl -s -X POST "$BASE/v1/templates/<templateId>/render" \
  -H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
  -d '{"profile":{"first_name":"Dana"}}'

2. Create the campaign

curl -s -X POST "$BASE/v1/campaigns" \
  -H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: camp-update-nov" \
  -d '{"name":"Product update: November","channel":"email","purpose":"marketing",
       "audience":{"includeListIds":["<listId>"]},"templateId":"<templateId>",
       "route":{"connectionId":"<connectionId>"},"tracking":{"opens":true,"clicks":true},
       "utm":{"source":"acme","medium":"email","campaign":"update-2026-11"}}'

Use includeSegmentIds to send to a segment. Always give a route.

3. Run the checks

curl -s "$BASE/v1/campaigns/<campaignId>/checklist" -H "Authorization: Bearer $HERMETICA_API_KEY"
curl -s "$BASE/v1/campaigns/<campaignId>/content-check" -H "Authorization: Bearer $HERMETICA_API_KEY"
curl -s -X POST "$BASE/v1/campaigns/<campaignId>/recipient-estimations" \
  -H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" -d '{}'
curl -s "$BASE/v1/campaigns/<campaignId>/recipient-estimations/latest" -H "Authorization: Bearer $HERMETICA_API_KEY"

The estimate shows how many people will get it, and how many are left out as suppressed, without consent or blocklisted.

4. Send a test

curl -s -X POST "$BASE/v1/seed-lists" \
  -H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
  -d '{"name":"Internal seeds","emails":["you@example.com"]}'
curl -s -X POST "$BASE/v1/campaigns/<campaignId>/test-send" \
  -H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
  -d '{"seedListId":"<seedListId>"}'

Test sends skip quiet hours, so they arrive at once, even at night.

5. Get it approved (optional)

A teammate can review the campaign before it goes out. Submit it, and someone else approves or rejects it with a comment. The person who submitted cannot approve their own campaign, and approving needs the campaigns:approve scope.

curl -s -X POST "$BASE/v1/campaigns/<campaignId>/approval/submit" -H "Authorization: Bearer $HERMETICA_API_KEY"
curl -s -X POST "$BASE/v1/campaigns/<campaignId>/approval/approve" \
  -H "Authorization: Bearer $REVIEWER_API_KEY" -H "Content-Type: application/json" -d '{"comment":"Looks good"}'

A pending or rejected campaign cannot be scheduled. Editing an approved campaign sends it back to unapproved, so the reviewer always signed off on what is sent. To require approval for every campaign, set {"campaignApprovalRequired":true} with PATCH /v1/content-settings.

6. Send or schedule

curl -s -X POST "$BASE/v1/campaigns/<campaignId>/schedule" \
  -H "Authorization: Bearer $HERMETICA_API_KEY" -H "Content-Type: application/json" \
  -d '{"schedule":{"at":"2026-11-04T15:00:00Z","tz":"America/New_York"}}'

Or send now with POST /v1/campaigns/<campaignId>/send-now. POST .../unschedule stops it before it starts.

7. Read the results

GET /v1/campaigns/<campaignId>/report gives deliveries, opens, clicks and unsubscribes. /recipients lists each person and status.

For an A/B subject test, set variants with PUT /v1/campaigns/<id>/variants/a and /b, then PATCH the campaign with {"abTest":{"testPercent":50,"metric":"clicks","waitHours":4,"auto":true}}.

Next: Build a welcome journey.

Updated