Three ways to add subscribers
Yaplet supports bulk CSV uploads, a REST API, and manual single-contact entry. All three paths use the same deduplication logic: if an email address already exists, Yaplet updates that record rather than creating a duplicate.
Option 1 — Upload a CSV file
Go to Newsletter → Subscribers and click Add subscriber. That opens the import page with Import from CSV/TXT selected as the default tab. There is no template file to download — the page shows two inline CSV examples (Template Example 1 and Template Example 2) you can copy and edit.
- Prepare your file with at least an
emailcolumn. The email column header is detected automatically (case-insensitive). A name column is also auto-detected from headers containingname,firstname, orlastname— if bothfirstnameandlastnameare present, they are concatenated into a single name. - Add any custom field tags as additional columns. Only custom field columns require an exact tag match — unknown columns are ignored.
- Upload the file. The import button updates to show the parsed row count — that count is the only validation feedback before submitting.
- Toggle Send verification email on if you want each imported contact to confirm their subscription before receiving campaigns. Leave it off to import them as Verified immediately (after a background email-format check).
- Click Import. Imports time out at two minutes — split files larger than a few thousand rows.
Any row whose email already exists in your list is merged: name and custom-field values are updated, group memberships are added, and the subscriber's existing state is preserved. An existing Unsubscribed contact will not be re-activated by a reimport.
Yaplet screens addresses as it imports, for free. Any row that's a duplicate, invalid in format, on a disposable or temporary domain, or a system/role address (like no-reply@, postmaster@, or abuse@) is dropped before it's inserted. You get a List cleaned summary with a per-reason breakdown — for example "Skipped 42 addresses that can't be delivered to: 30 invalid, 5 disposable, 7 system/no-reply." The same gate runs on the bulk-upsert API, which returns the skipped counts in its response.
What Yaplet can't check is whether a real mailbox actually exists behind a valid-looking address. Importing an unconfirmed, purchased, or stale list causes bounces and spam complaints — and high rates will automatically pause your sending (see Monitor your email deliverability). If a large share of a list turns out unusable, Yaplet flags it and suggests verifying it first with a service like ZeroBounce, Kickbox, or MillionVerifier. Only import lists you own and have permission to email.
Yaplet keeps the list clean after import, too: a background check removes contacts whose domain no longer accepts mail, and notifies you that the undeliverable addresses were removed.
Option 2 — Bulk upsert via API
Send an authenticated POST request to /api/newsletter/contacts/bulk-upsert. Authenticate with your workspace API key in the Y-API-Key header.
POST /api/newsletter/contacts/bulk-upsert
Y-API-Key: your-workspace-api-key
Content-Type: application/json
{
"contacts": [
{
"email": "[email protected]",
"name": "Jane Smith",
"state": "VERIFIED",
"fields": { "plan": "pro", "country": "US" },
"group_add": ["group-uuid-here"],
"group_remove": ["other-group-uuid"]
}
]
}
Fields on each contact object:
| Field | Type | Required | Notes |
|---|---|---|---|
email |
string | Yes | Used as the unique key with your org ID. Existing contacts are updated. |
name |
string | No | For new contacts only, defaults to the part of the email before the @ if omitted. Existing contacts keep their current name when no name is sent. |
state |
string | No | Accepted values: VERIFIED, UNVERIFIED, REMOVED. Any other value is silently dropped. VERIFIED is only honored when promoting an existing REMOVED contact back; for brand-new contacts, omit this field and let the background check decide. |
verification_id |
UUID | No | The verification email variant to send. New contacts land in NEW first; the background check then transitions them to Unverified (with this email sent) or Verified based on the verification toggle and email-format validity. |
fields |
object | No | Key-value object keyed by your custom field tags. Types are validated against the field definition. |
group_add |
UUID[] | No | Array of group IDs to add the contact to. |
group_remove |
UUID[] | No | Array of group IDs to remove the contact from. |
created_at |
ISO string | No | Override the contact's creation timestamp (useful when migrating from another platform). |
A successful response returns { "success": true, "results": [...] } with the upserted contact records. Errors:
- 401 — missing or invalid
Y-API-Key. - 400 — contact limit exceeded for your plan. This is the only condition that produces a 400.
Invalid state values and unknown custom-field tags do not raise an error — they are silently filtered out before the upsert. To detect drops, compare results.length in the response against the size of the contacts array you sent.
Existing contacts are matched on (email, org_id): name, fields, and group memberships are updated; the existing state is preserved unless you explicitly send a new state value.
Option 3 — Add a subscriber manually
For a single contact, click Add subscriber on the Subscribers page to open the import page, then switch to the Add Single Subscriber tab. Fill in the email address, an optional name, any custom field values, and the groups to add them to. Click Save.
Subscriber states after import
Every imported row first lands in New. A background job then checks the email format and transitions the contact based on the Send verification email toggle you chose at import time:
| State | Meaning |
|---|---|
| New | Transient state right after import. The background check picks the row up within seconds and moves it to one of the states below. |
| Verified | Receives campaigns. Set when verification was off at import and the email format is valid, or after a subscriber clicks the opt-in confirmation link. |
| Unverified | Verification was on at import and the email format is valid. A confirmation email is sent; the contact will not receive campaigns until they click the link. |
| Unsubscribed | Opted out. Reimporting will not re-activate them. |
| Bounced | Hard bounce recorded by the email provider. Reimporting will not re-activate them. |
| Complained | The recipient marked a message as spam (reported via SES or Hyvor webhooks). Reimporting will not re-activate them. |
| Removed | Manually removed from the list, or auto-removed because the background check rejected the email format as invalid. |
Once subscribers are in your list, each one carries an Engagement score shown as a column on the Subscribers table — it rises automatically as they interact (+1 per open, +3 per link click, accumulating over time), and higher-scoring subscribers are sent first in each campaign.
What's next
With subscribers in your list, organize them into dynamic segments or static groups to target specific audiences in your campaigns.