Your audience, in one place.
Custom fields, segments, consent. Pay for sends, not contacts.
Every contact
Everything about a contact, on one screen.
Identity, fields, topics, activity. One screen.
CSV import
Map columns. Existing contacts are skipped.
Activity trail
Every change, logged per contact.
Deliverability
Mailable or suppressed, with the reason.
Ada Lovelace
ada@example.com
Fields
Topics
Activity
- Subscribed to Product updates2d
- Added to segment “Beta”5d
- Imported from CSV3w
Custom fields
Store any attribute, your way.
Text, number, boolean, date. Reference as {{ key }}.
Four types
Set a default when a contact has no value.
Safe to rename
Keys migrate. Deletes strip cleanly.
Company
company
Text—Plan
plan
TextfreeSeats
seats
Number1Signup date
signup_date
Date—Beta access
beta_access
BooleanfalseSegmentation
Static lists and dynamic segments.
A hand-picked list, or a filter that stays live.
Dynamic
Membership recalculates. No re-tagging.
Operators
is, contains, greater than, is-set — per type.
Everyone subscribed
Built in. Always current.
Personalization
Personalize with every field.
{{first_name}}, {{email}}, or any custom field. Per recipient at send.
Any field
Subject or body. Built-in and custom.
Caught before send
Missing values return 422. Never a raw token.
Fallbacks keep sends clean when a value is missing.
Subscription status
Consent, tracked at every level.
Global, per-topic, per-list. Transactional still goes.
Topics
Recipients choose on a hosted page.
Opt-outs
Honored automatically. Nothing to wire up.
Email preferences
Choose what Acme sends you, or unsubscribe from everything.
Topics
Stops every marketing email regardless of topic.
Suppressions
A reputation backstop, on by default.
Hard bounce or complaint? That address is skipped. Forever, until you say otherwise.
Automatic
Bounces and complaints suppress for you.
Reasons
Bounce, complaint, unsubscribe, manual, API.
Developer-first
Manage your audience with code.
Create, update, unsubscribe, remove. One REST API.
Kept in sync
Email is the unique key.
curl -X POST 'https://www.unitpost.com/contacts' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'User-Agent: my-app/1.0' \
-H 'Content-Type: application/json' \
-d '{
"email": "customer@example.com",
"first_name": "Ada",
"last_name": "Lovelace"
}'Reach the right people
A segment for every send
A list you curate, or a cohort that updates itself.
Newsletter list
A static list. Add or remove by hand, signup, or CSV.
Active paid users
plan is “pro”. Membership updates as they upgrade or churn.
Recent signups
signup_date on or after a date. Always the latest cohort.
Region targeting
Match a country or city field. Send the right copy.
Everyone subscribed
Built-in segment of everyone still opted in to marketing.
Topic subscribers
“Product updates” or “Promotions”. Send only to who wants it.
Beta cohort
A boolean field. A segment. Early access behind consent.
Win-back
Dormant accounts. Opt-outs and suppressions keep it clean.
Questions
Common questions
How do I add or update a contact from my app?
POST /api/v1/contacts with an email plus optional first_name, last_name, unsubscribed, and a custom_fields map; PATCH /api/v1/contacts/{id} updates one. Email is the unique key per workspace, and the path accepts either the con_ id or the email address, so you can sync from your own database without storing our ids. Writes need the contacts:write scope, reads contacts:read.
What's the difference between a static and a dynamic segment?
A static segment is a list you curate — you add and remove contacts explicitly. A dynamic segment is a saved filter that is re-evaluated live every time it's read or sent to, so membership follows your data with no re-tagging. Because dynamic membership is computed, the add-member and remove-member endpoints return 409 for one; you change who's in it by editing the filter.
Is there a limit on how many contacts I can store?
Every paid plan has no contact cap and you're billed on emails sent, not list size — so an unengaged list costs you nothing to keep. The free plan stores up to 10,000 contacts. A segment filter is capped at 25 conditions in total, which is a query-complexity limit rather than a limit on your audience.
Can I store custom attributes on a contact?
Yes. Register a field once with POST /api/v1/contact-fields as text, number, boolean, or date with an optional workspace default, then set per-contact values in the contact's custom_fields map. Values must be scalars so they're safe to interpolate as {{ key }} in a subject or body and to use as segment-filter inputs. Renaming a field key migrates the value on every contact.
Does Unitpost handle unsubscribes and bounces for me?
Yes, at three levels. Every contact has a global marketing opt-out, per-topic preferences they manage on a hosted page, and per-list opt-out in the data model. Hard bounces and spam complaints suppress an address automatically, with the reason recorded. Suppressed addresses are skipped on every future send — even addresses that were never contacts, which you can add yourself over the API.
Are segment filters case-sensitive?
Yes — eq, contains, starts_with, and ends_with all compare exactly, so "Premium" does not match "premium". This is deliberate: custom fields live in a JSON column whose string filters can't express case-insensitive matching, and making built-in columns behave differently would mean the builder preview, the dashboard count, and the actual send could disagree. Normalize values on write if you need loose matching.
Bring your list and start sending
Contacts, fields, segments, opt-outs. 5,000 emails a month free. No credit card.