Integrate SuprSend into your backend: build a template and workflow, identify users from your code, trigger notifications, and confirm delivery in logs.
This guide takes you from a new SuprSend account to a notification sent from your own code. By the end, you’ll have built a template and a workflow in SuprSend, and added two calls to your backend: one that identifies a user, and one that triggers the workflow. You’ll then confirm in logs whether the notification was sent.Everything in this guide runs in your Sandbox workspace and uses the email channel. Because it’s a sandbox, an email vendor is already connected — there’s nothing to set up before you send.
This guide assumes you’ve read Core concepts. It uses template, user,
workflow, and logs without redefining them.
Create your SuprSend account.Three workspaces are created automatically — Sandbox, Staging, and Production. Switch
between them from the top navigation bar. Stay in Sandbox for this guide: it already has an
email vendor connected, so there’s nothing to configure before you send.
Go to Developers → API Keys and
copy your Workspace Key and Workspace Secret — that’s what the code in this guide uses by
default. If you are generating an API Key instead, it’s on the same page and is shown only
once, so copy it before closing the dialog.Store them as environment variables:
.env
SUPRSEND_WORKSPACE_KEY=your_workspace_keySUPRSEND_WORKSPACE_SECRET=your_workspace_secret# Only if you're calling the REST API instead of using an SDKSUPRSEND_API_KEY=your_api_key
One email template with a single variable, order_id, and a workflow that sends it.
Dashboard Agent
Dashboard
Open Agent with Cmd+/ and paste:
Create a workflow named "Order Shipped Notification" with a Workflow API triggerand a single channel email delivery node.For that email, create a template named "Order Shipped" with one variable, order_id.Subject: Your order has shippedBody: Order #{{order_id}} is on its way.Add {"order_id": "ORD-1234"} to the Input Payload.Commit both the template and the workflow live, then tell me both slugs.
Agent builds the template first, then the workflow that uses it, and commits both.
Agent building and committing both, then reporting the slugs
The committed template
The committed workflow
Create the template
Editing always works on a draft. Until you commit, a workflow triggering this template sends
the previous live version — or fails, if there is no live version.
Go to Templates and click + New Template.
Enter a Name — Order Shipped. The slug order-shipped is auto-generated from the
name and can’t be changed later. Click Create.
Create Template modal
Select Email as the channel, then choose Plain text only from the editor dropdown —
the quickest way to see your content render.
Choosing the plain text editor
The subject can be edited by clicking edit icon on top right of template editor. Set the
Subject to Your order has shipped and click Save.
Email Settings, where the subject is edited
Write the body: Order #{{order_id}} is on its way. — {{order_id}} is a placeholder, and
its value arrives in the payload you send when you trigger the workflow, in a later step.
Body with the order_id variable
Open the Variables panel — the {} icon in the far-left sidebar — click the edit icon
next to Input Payload, enter {"order_id": "ORD-1234"}, and click
Update Input Payload.
Input Payload, the sample data your preview renders with
The preview updates to Order #ORD-1234 is on its way.
Click Commit in the top right.
Plain text editor with the input payload set and the preview rendering
Create the workflowTwo nodes: a trigger that starts the workflow, and a delivery node that sends the email.
Go to Workflows and click + New Workflow.
Enter a Name — Order Shipped Notification — and pick a Notification Category, for
example Transactional. The slug order-shipped-notification is auto-generated from the
name. Click Create to open the workflow in draft.
Create Workflow modal
Open the Trigger node. Its Type is API — the trigger type you call from your
backend, naming the workflow and its recipients in the request. Workflow API is selected by
default when you make the workflow from dashboard manually. The panel also shows the
Workflow Slug you’ll use in your code.
Trigger node, with the workflow slug you'll call from your backend
Add a Single Channel delivery node, select Email, choose the order-shipped
template, and click Save.
Email delivery node using the order-shipped template
Click Commit in the top right to make the workflow live.
Only live templates appear in the delivery node. If order-shipped isn’t listed, it hasn’t
been committed yet.
You now have a live template, order-shipped, and a live workflow, order-shipped-notification.
Delays, batching, branches, and multi-channel routing are all added as extra nodes — see
Design workflow. For ready-made examples, browse the sample library from
Workflows → New Workflow → Use Sample Workflow.
Two calls go into your backend. The first tells SuprSend who your user is and how to reach them. The
second runs the workflow you just built.
AI editor
Write it yourself
One prompt writes both calls into your codebase. Paste it into Claude Code, Cursor, Windsurf, or
any other AI editor you use.
Recommended: connect your editor to SuprSend first. Your agent can then confirm the
workflow exists and check the user was created, instead of taking your word for it. The prompt
works without it.
Connect your editor to SuprSend (optional)
Get a Service Token from Account Settings → Service Tokens.
It’s shown only once, and it’s account-wide — it belongs in your editor’s configuration, not
in your application code or your .env file. Requires Node.js 18+.Claude Code — run in your terminal, not inside a claude session:
claude mcp add suprsend \ --scope user \ --env SUPRSEND_SERVICE_TOKEN=your_service_token \ -- npx -y suprsend start-mcp-server
Cursor — add to ~/.cursor/mcp.json, creating the file if it doesn’t exist:
Windsurf — add the same block to ~/.codeium/windsurf/mcp_config.json, without the
mcpServers wrapper, then click Refresh.Confirm it worked by asking your editor to list your SuprSend workflows. Full setup:
MCP server.
No codebase yet? Use the cURL example in the next tab — it runs both calls from your terminal
with nothing to install.
Copy the integration prompt
Integrate SuprSend into this codebase.Already built — do not re-create these: a live workflow "order-shipped-notification"in the Sandbox workspace that takes one data field, order_id, and the emailtemplate behind it.My SuprSend credentials belong in my environment — SUPRSEND_WORKSPACE_KEY andSUPRSEND_WORKSPACE_SECRET for the SDKs, SUPRSEND_API_KEY for the REST API. Theguide had me put them there, but confirm with me rather than assuming.If the SuprSend MCP server is connected, use it. My workspace is "sandbox" — passthat on every MCP call, because it otherwise defaults to staging. Use it to lookup exact SDK method names and payload shapes in the SuprSend docs instead ofwriting them from memory, to list the live workflows and confirm"order-shipped-notification" is there, and to fetch the user back from SuprSendafter you sync it. Use MCP to check your work, never to do the work — the syncand the trigger must run from this codebase's own code.If it isn't connected, carry on without it and tell me so.1. Work out what language this codebase is written in and install the matching SuprSend backend SDK — Node.js, Python, Java or Go. For any other language, call the REST API instead. Then tell me which credential that path needs — the workspace key and secret for an SDK, the API key for REST — and ask me to confirm it's actually set in my environment and not still a placeholder, before you write any code.2. Read both credentials from the environment in one shared place.3. Find where user records live in this codebase. Take one existing record and sync it to SuprSend: that record's own ID as distinct_id, plus an email address. Ask me which email to use, and tell me to pick an inbox I can actually open — any address works, but a fake one means I'll only see the send in the dashboard logs. If this codebase has no user records at all, tell me that and ask me before creating one — ask me for the email address to put on it, same rule.4. Trigger "order-shipped-notification" for that distinct_id, with data {"order_id": "ORD-1234"}. Sync the user before triggering, and name recipients by distinct_id only.5. Keep all SuprSend code in new files. In existing files, add only the single line that calls it — where this codebase already creates or updates a user record, and at whatever point here makes sense to notify someone. If neither has an obvious home, call it from a new file of its own and say so.6. Run both calls once and show me SuprSend's actual response to each. If you could not run them, say so plainly — do not tell me it worked.Read credentials from the environment, never hardcode them. Never put a SuprSendservice token in application code. Do not invent workflow slugs, SDK methodnames, or user properties.Finish with one line per file you created and per existing file you edited, thentell me to check the dashboard: Users for the profile, then Logs → Requests →Workflow executions → Messages for the send.
Your editor writes the same two calls shown in the next tab. Read the diff before you run it.
Install the SDK and create the client once. Both calls below reuse it.
import suprsend.Suprsend;Suprsend suprClient = new Suprsend( System.getenv("SUPRSEND_WORKSPACE_KEY"), System.getenv("SUPRSEND_WORKSPACE_SECRET"));
// go get github.com/suprsend/suprsend-goimport "github.com/suprsend/suprsend-go"suprClient, err := suprsend.NewClient( os.Getenv("SUPRSEND_WORKSPACE_KEY"), os.Getenv("SUPRSEND_WORKSPACE_SECRET"),)
# No client to initialise. Every request uses your API key:# Authorization: Bearer $SUPRSEND_API_KEY
Identify a userCall this wherever your app creates or updates a user record. distinct_id is SuprSend’s name for
the user identifier — pass whatever ID that record already has. You don’t create a new one.To try it now, run it once for a user that already exists. Use an email address you can actually
open, or you’ll only see the send in the dashboard logs.
const user = supr_client.user.get_instance("user_1a2b3c");user.add_email("you@example.com");const res = await user.save();console.log(res);
user = supr_client.user.get_instance("user_1a2b3c")user.add_email("you@example.com")res = user.save()print(res)
Subscriber user = suprClient.user.getInstance("user_1a2b3c");user.addEmail("you@example.com");JSONObject res = user.save();System.out.println(res);
user := suprClient.Users.GetInstance("user_1a2b3c")user.AddEmail("you@example.com")res, err := user.Save()
JSONObject body = new JSONObject() .put("workflow", "order-shipped-notification") .put("recipients", new JSONArray() .put(new JSONObject().put("distinct_id", "user_1a2b3c"))) .put("data", new JSONObject().put("order_id", "ORD-1234"));WorkflowTriggerRequest wf = new WorkflowTriggerRequest(body);JSONObject res = suprClient.workflows.trigger(wf);
The call names the user by distinct_id only — SuprSend already has their email from the previous
step. The keys in data fill your template’s variables, so order_id here becomes {{order_id}}
there.
Sandbox already has a user created from your registered email. You’re making your own anyway — the
point of this step is your code creating the profile, not the profile existing.
Open Logs in the dashboard. Under Requests you’ll
see both of your calls — user_update for the user you created, and workflow for the trigger.
Open the workflow execution to watch it run node by node, and to see the email reach the recipient.
Now check that inbox. The email is there, sent by code you wrote.
Sandbox is a trial workspace: it expires 28 days after signup and has capped usage. Everything you
built here — the template, the workflow, and the two calls in your backend — works the same in
Staging and Production once you connect your own vendor.
The slug in your trigger call doesn’t match a live workflow. Either it’s a typo, or the workflow is
still a draft. Open it and check the badge reads Live — if it doesn’t, commit it.
Request failed: authentication error
You’re using the wrong credential for the path you’re on. Backend SDKs take the Workspace Key and
Secret. The REST API takes an API Key as Authorization: Bearer. A Service Token works for
neither — it’s for the CLI and MCP server only.
The send succeeded but no email arrived at all
Sandbox only delivers to verified channels — a short list you control at
Developers → Verified Channels,
up to 5 per channel type. If the recipient’s address isn’t on that list, nothing arrives.
Nothing arrived, but the workflow shows Completed
A completed execution means every node ran, not that a message was delivered. A channel only sends
when all four are true:
The template has live content for that channel
The user has an identity for it — an email address, in this case
The user hasn’t opted out
A vendor is connected
The workflow execution log names which one failed. The most common cause here is a user synced
without an email address, so check the profile under Users first.
The email arrived with a blank where the variable should be
The key in your trigger’s data doesn’t match the variable in your template. data must contain
order_id for {{order_id}} to resolve. Open the message in Logs → Messages and use
Message preview to see exactly what rendered.