Email campaigns

Broadcast announcements and onboarding emails to your partners.

Email campaigns let you broadcast a one-off message — a welcome note, a product announcement, a monthly digest, or a reward bump — to your partner base. You write the campaign once, pick who receives it, preview it, and send. Emails go out through Resend as plain-text messages. Campaigns are managed by workspace admins from /<workspace>/campaigns.

In the dashboard

  1. Open Email Campaigns and click New campaign

    Go to /<workspace>/campaigns. Past campaigns are listed with a draft or sent badge. ClickNew campaign (top right) to open the composer sheet.

  2. Write your campaign

    On the Write your campaign step you can start from one of four templates — Welcome new partners, Product announcement, Monthly update, or New reward announcement — or write your own Subject and Message from scratch. Insert {{partner_name}} anywhere in the body to personalize each email with the recipient's name. Click Continue to save the draft and advance.

  3. Review & send

    On the Review & send step, choose an audience under Send to: Approved partners, Pending applicants, or All partners. The preview panel shows the subject and body with {{partner_name}} filled in with a sample name. Click Send now to send, or Save as draft to keep it for later. On success you'll see a toast with the recipient count.

A sent campaign records how many partners it reached (sentCount) and its send date, both shown on the campaign card.

Via the API / for agents

Campaigns are a two-call flow: first create a draft, then send it. Both calls are scoped to a workspace slug.

Create a draft:

POST /api/workspaces/<slug>/campaigns
Content-Type: application/json

{
  "programId": null,           // optional: limit to one program
  "subject": "Big news for our partners",
  "body": "Hi {{partner_name}}, ...",
  "targetStatus": "approved"   // "approved" | "pending" | null (all)
}

The response includes the new campaign's id. Use it to send:

POST /api/workspaces/<slug>/campaigns/<campaignId>/send

Send response:

{
  "sentCount": 42,
  "campaign": {
    "id": "...",
    "status": "sent",
    "sentCount": 42,
    "sentAt": "2026-07-05T12:00:00.000Z"
  }
}

The send endpoint resolves recipients from the workspace's partners: it filters by programId if set, by targetStatus if set, and — when targetStatus is null (all partners) — excludes any partner whose status is banned. Emails are sent in batches of 50 as plain text via Resend.

Gotchas

Only the first {{partner_name}} is replaced

The send route substitutes {{partner_name}} with a plain string replace, so only the first occurrence in the body is personalized. If you use the token more than once, later occurrences ship literally. Keep it to a single {{partner_name}} near the top. (The dashboard preview replaces all occurrences, so it can look fine while the actual email differs.)

Sending is one-shot and idempotent-ish

A campaign that's already sent returns 409 Already sent — you can't re-send it. If no partners match the filter you get 400 No recipients matched. Individual Resend failures are swallowed silently and simply don't count toward sentCount, so a lower-than-expected count means some deliveries failed.