Notix
Use cases

A welcome that arrives while the sign-up page is still open.

Two ways to do it, and most products want both. The first welcome is one call from your sign-up handler through the transactional email API, with an idempotency key so a retry never sends twice. The sequence that follows is a journey: your code creates the new user as a contact, the journey enrols them and sends the next emails with waits in between. Imported lists start with double opt-in, so nobody who did not ask hears from you.

The flow

Welcome now, sequence later.

One send from the handler, then a contact in a book. Everything after that is configured, not coded.

  1. Send the welcome from the handler.

    Once the account row exists, call POST /v1/emails with your welcome template and an idempotency key of welcome-{userId}. Store the returned emailId on the user so support can see what happened to it.

  2. Create the contact.

    Add the user to your onboarding contact book with POST /v1/contactBooks/{bookId}/contacts. A contact created subscribed enrols into every journey on that book whose trigger is “contact added”, at step 0, immediately.

  3. Let the journey run.

    The journey sends its first step, waits the days you set, and sends the next. An unsubscribe ends it. A hard bounce suppresses the address. You watch both through webhooks, and your code does nothing more.

Code

The single welcome.

curl, or the TypeScript and Python SDKs. The samples use a template with two variables; inline html and text work the same way.

curl
# From your sign-up handler, once the account row exists. The idempotency
# key names the account, so a retried handler cannot welcome it twice.
curl -X POST https://app.usenotix.dev/api/v1/emails \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Idempotency-Key: welcome-usr_123" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Ada at Acme <ada@acme.com>",
    "to": "user@example.com",
    "subject": "Welcome to Acme",
    "templateId": "tpl_welcome",
    "variables": { "firstName": "Chidi", "dashboardUrl": "https://acme.com/app" }
  }'

# 200 { "emailId": "eml_abc123" }

The sequence.

Create the contact and the journey takes over. The enrol call is for journeys with an “API” trigger, such as a win-back you start from your own logic.

curl
# 1. Create the contact in the book the journey listens to. Created
#    subscribed, it enrols into every "contact added" journey on the book.
curl -X POST https://app.usenotix.dev/api/v1/contactBooks/$BOOK_ID/contacts \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "user@example.com", "firstName": "Chidi",
        "properties": { "plan": "free" } }'

# 200 { "contactId": "ctc_abc123" }

# 2. Or enrol an existing contact into one specific journey yourself.
#    Exactly one of contactId or email; 409 if it already has a run.
curl -X POST https://app.usenotix.dev/api/v1/journeys/$JOURNEY_ID/enroll \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactId": "ctc_abc123" }'

# 201 { "id": "run_...", "status": "ACTIVE", "currentStep": 0, ... }
Imported lists

Double opt-in first.

A list you did not collect yourself should not get a welcome until each person confirms. Turn double opt-in on for the contact book, in the dashboard or with doubleOptInEnabled: true on POST /v1/contactBooks, and set doubleOptInFrom and doubleOptInSubject so the confirmation email is yours. Each new contact is created pending, receives the confirmation, and enrols into the journey only after the click. Contacts who never click never hear from you, and never count against your reputation.

Rules

What Notix does, and what stays yours.

The first five are what the send, contact and journey APIs do on their own; the last is a convention your welcome should keep.

RuleEnforced byNotes
One welcome per account, even on retryNotixPass an idempotency key of welcome-{userId}. A retried sign-up handler with the same key returns the original response instead of a second email.
A subscribed contact enrols the moment it is createdNotixCreating a contact in a book enrols it into every journey on that book whose trigger is "contact added". Updating an existing contact does not re-enrol it.
Double opt-in comes before the sequenceNotixWith double opt-in on, a new contact is created pending and receives the confirmation email first. The journey enrols it only after the click. Enrolling a pending contact by API answers 400.
Unsubscribe stops the sequence, not the receiptNotixA journey or campaign email to a contact who has unsubscribed is refused at send time. A transactional send from your own handler still goes out; unsubscribing is a marketing preference, not a block.
Suppressed addresses get nothing from either pathNotixAn address that hard bounced or complained is dropped before the send. The transactional call still answers 200 with an id, and the email's status reads SUPPRESSED.
Nothing secret in the welcomeYour appNo password, temporary or otherwise, and no link that signs the reader in for days. If the account needs confirming, use a one-time code or a short-lived link, and send the welcome after.

The contact, contact book and journey endpoints, and the enrol response, are in the docs.

Example

What the user receives.

From a person, about one thing to do next, with a way to reply.

The welcome

From: Ada at Acme <ada@acme.com>
Subject: Welcome to Acme

Hi Chidi, your Acme account is ready. The fastest way to see it work is to send your first invoice; it takes about two minutes. Reply to this email if anything is unclear; a person reads it.

Leave out

A password, temporary or not. A link that signs the reader in for a week. Five things to do, when one will do. A no-reply address on the one email a new customer is most likely to answer.

Design notes

Five habits for a welcome that lands.

Send it from the handler, not the queue.

The welcome should arrive while the sign-up page is still open. One call with an idempotency key from the same request that created the account is faster than a job, and just as safe on retry.

Let the sequence be a journey.

Day-two and day-seven emails belong in a journey with waits between steps, edited in the dashboard, not in cron jobs that read your users table. Your code creates the contact; the journey does the rest.

Import with double opt-in on.

A list you did not collect yourself starts pending. The confirmation email goes first, the sequence starts on the click, and nobody who never asked hears from you.

Keep the welcome transactional.

The one-off welcome from your handler goes out even to a contact who later unsubscribes from marketing. That is correct: they signed up. The journey emails are the ones an unsubscribe stops.

Watch the first bounce.

A welcome that bounces means a mistyped address at sign-up. Listen for email.bounced on a webhook and ask for a correction while the person is still around.

FAQ

Questions, answered.

How do I send a welcome email through an API?
One call to POST /api/v1/emails from your sign-up handler, with a template or inline HTML and an Idempotency-Key header of welcome-{userId}. The response carries an emailId. For a sequence, create the new user as a contact in a contact book instead; a contact created subscribed enrols into every journey on that book whose trigger is "contact added", and the journey sends the steps with waits between them.
Can I run a welcome sequence, not just one email?
Yes, with a journey. Build the steps in the dashboard: an email, a wait of a few days, another email. Set the trigger to "contact added" on a contact book, then create each new user as a contact in that book from your code. Journeys with an "API" trigger are started by POST /api/v1/journeys/{id}/enroll with a contactId or an email instead.
What does double opt-in change?
With double opt-in on for the book, a new contact is created pending and gets the confirmation email first. It enrols into the journey only after the confirmation click, and an enrol call for a pending contact answers 400. Enable it on the book with doubleOptInEnabled, and set doubleOptInFrom and doubleOptInSubject to brand the confirmation.
What happens if the user unsubscribes?
Journey and campaign emails to that contact are refused at send time. A transactional welcome sent from your own handler is not affected, because unsubscribing is a marketing preference rather than a block. An address that has hard bounced or complained is on the suppression list and receives nothing from either path.
Does a retry of my sign-up handler send two welcomes?
Not with an idempotency key. A second request with the same key and body within 24 hours returns the original response and creates no email. Use the account id in the key, such as welcome-usr_123, so the key is stable across retries.
Can the welcome be an SMS?
The email API sends email. For phones, the verification API sends a one-time code by SMS in Nigeria and Kenya, and the SMS endpoint sends a message from an approved sender ID, prepaid from your wallet. A welcome sequence by SMS is not something journeys do today.

Welcome your next sign-up in one call.

One send with an idempotency key, a journey for the rest, and the free plan's 5,000 emails a month to test with. No card.