CSV and file import
Self-serve uploads with type inference, per-row error reports and duplicate detection — including related files that join onto a parent record.
How it works
The first fortnight is data, domains and consent. After that, the day-to-day is composing, segmenting and sending — and most of it never needs a developer again.
Start with whatever you already have. A CSV goes through a guided import that infers each column's type, suggests which one identifies the person, and shows you a dry run before a single profile is written. An API or webhook connection is registered once, with a signed secret you can rotate. A scheduled pull — from Salesforce or another REST source — runs on its own.
What matters here: mappings are versioned and previewed. Nothing writes into your customer data until you've seen what it would do.
SPF, DKIM and DMARC records are generated for each domain you send from, and verification status is visible in the portal. This is usually the longest step, because it depends on your DNS — and it's the step that decides whether you land in an inbox or a spam folder.
What matters here: do it before you build anything. Everything else is faster than DNS propagation.
Every permission signal you already hold is written into the ledger with its source. From then on, the live consent state is derived rather than edited — and inbound connectors can only ever revoke. If a customer unsubscribes, the record is immediate, permanent and readable back out by your other systems.
What matters here: imports can't re-subscribe people. That's a feature, and it's the one that keeps you out of trouble.
Define a theme — palette, fonts, button style — or extract one from an email you already like. Save your standard footer as the workspace default so it's inserted into every new email automatically. Upload your logos and imagery to the media library.
What matters here: themes apply when an email is created, never retroactively. Changing your brand next year won't rewrite last year's campaigns.
Compose in the block builder, or paste HTML if you'd rather. Add merge fields from profile traits or the triggering event. Preview it, send a test to yourself, then activate. Every save creates a version, so you can see what changed.
What matters here: only active templates can be resolved by a live rule, so a half-finished draft can't reach a customer.
For a campaign, build a segment from traits, consent and event history, and preview the count. For a journey, register the event you want to react to and write a rule against it — with filters, a delay or a payload-relative schedule, and a cancel condition where one applies.
What matters here: the event vocabulary is open. If your system can describe it, you can trigger on it, with no change on our side.
Sends are queued and processed on separate marketing and transactional lanes. Delivery, bounce, complaint, open and click events flow back into the same event stream your segments read from. Reporting is exportable, and a daily job reconciles what we recorded against what the providers report.
What matters here: engagement data isn't a separate silo — today's opens are tomorrow's segment.
Integrations
Self-serve uploads with type inference, per-row error reports and duplicate detection — including related files that join onto a parent record.
Push events and profiles over HTTPS with a scoped API key, or point a signed webhook at us. Ready-made recipes cover the common shapes.
A declarative HTTP pull connector polls your endpoint on a schedule and maps the response into canonical profiles and events.
Authenticated server-to-server integration for pulling contact data, with communication preferences mapped conservatively — a default-true flag is treated as unknown, never as consent.
First-party integration with the wider Ornex suite: CRM events become journeys, and unsubscribes flow back so both systems agree.
The one way out: a cursor-based feed of consent changes any downstream system can poll to stay in step with what customers have chosen.
Architecture
A NestJS API and a Next.js portal over PostgreSQL, with AWS doing the sending and the queueing. Workers are separate from the API tier, so throughput scales without touching request latency.
AWS eu-west-2 (London) for compute, database, queues and media.
Amazon SES v2 for email; AWS End User Messaging for SMS, with UK numbers in E.164.
SQS lanes for marketing, transactional and ingestion traffic, each with a dead-letter queue. Ingestion is FIFO so per-record ordering holds.
PostgreSQL with additive, nullable-safe migrations; media and imports in private S3 buckets, media served through CloudFront.
A 30-minute walkthrough: connect a sample list, build one journey, and look at what the consent ledger records. No slideware.