For SaaS and fintech
Receipts from your code. Onboarding from a sentence.
Transactional email through a Resend-compatible API. Journeys that start when your product sends an event. Broadcasts you say out loud. One domain, one consent model, one log for all of it.

What should we send today?
Say it in a sentence. Linnet writes the email, picks who gets it, and sets the time.
# Your app tells Linnet what happened. curl https://app.linnet.run/v1/events \ -H "Authorization: Bearer $LINNET_API_KEY" \ -d '{"id":"signup-user_123", "name":"user.signed_up", "contact_id":"user_123", "properties":{"plan":"trial"}}' # The journey you approved in chat starts.
// Your app tells Linnet what happened. await fetch("https://app.linnet.run/v1/events", { method: "POST", headers: { Authorization: `Bearer ${process.env.LINNET_API_KEY}` }, body: JSON.stringify({ id: "signup-user_123", name: "user.signed_up", contact_id: "user_123", properties: { plan: "trial" } }) }); // The journey you approved in chat starts.
Same product, two doors. Chat for the people, API and MCP for your code and your AI. An event never grants email permission.
What a product sends
Your code sends the receipts. You say the rest.
Transactional email is a request. Everything else is a sentence that comes back as a card.
Moving from Resend or SES
Change two settings. Keep your code.
Bring your audience with it. Contacts are not a line on the bill. Weighing it up? Resend alternatives, honestly compared, or let us move you by hand, free.
Two settings
# .env RESEND_API_KEY=lnt_live_… RESEND_BASE_URL=https://app.linnet.run # Your code, unchanged await resend.emails.send({ from: "billing@northstar.app", to: user.email, subject: "Your receipt", html });
Same request shape, same response shape. Batch and cancel work the same way.
Bring your audience
curl https://app.linnet.run/v1/contact-imports \
-H "Authorization: Bearer $LINNET_API_KEY" \
-d '{"source_key":"product",
"contacts":[{"source_object_id":"user_123",
"email":"ada@northstar.app",
"consent":{"purpose":"marketing",
"status":"granted"}}]}'
Or upload the export from Resend, Mailchimp, or a CSV. Rows are reconciled one by one, consent included.
Start journeys from events
curl https://app.linnet.run/v1/events \
-H "Authorization: Bearer $LINNET_API_KEY" \
-d '{"id":"trial-day7-user_123",
"name":"trial.day_7_no_project",
"contact_id":"user_123"}'
Send events by user id. The journey you approved in chat picks them up. An event never grants email permission.
Start
Send your first real email today.
Connect your domain, change two settings, say the first sentence.


