Contacts: Create, Import & Status
Manage email contacts with status, tags, and custom fields
Contacts are the recipients of your emails. Create them individually, bulk-import from CSV, manage their status, and track bounces/complaints.
Create a Contact
Create a single contact.
cURL
curl -X POST https://api.tratto.email/v1/contacts \
-H "Authorization: Bearer tratto_live_..." \
-H "Content-Type: application/json" \
-d '{
"email":"[email protected]",
"firstName":"Alice",
"lastName":"Smith",
"status":"subscribed",
"tags":["vip","newsletter"],
"customFields":{"plan":"pro","signupDate":"2025-01-01"}
}'Response: creation returns the id only.
{
"data": {
"id": "cont_abc123"
}
}The field is customFields, not metadata. Unknown fields are dropped
silently — send metadata and you get a 201, no error, and none of your
data stored. Read the contact back once to confirm what actually landed.
List Contacts
Retrieve all contacts with optional filtering.
cURL
curl "https://api.tratto.email/v1/contacts?status=subscribed&limit=50" \
-H "Authorization: Bearer tratto_live_..."Query Parameters:
q: Email prefix search, case-insensitive. Combinable withstatusonly — withaudienceIdortagit returns 422status: Filter by status (subscribed,unsubscribed,bounced,complained)audienceId: Only contacts in that audiencetag: Only contacts carrying that taglimit: Max results per page (default 50, max 100)after: Cursor for pagination
Response:
{
"data": [
{
"id": "cont_abc123",
"email": "[email protected]",
"firstName": "Alice",
"lastName": "Smith",
"status": "subscribed",
"trackingOptOut": false,
"tags": ["vip"],
"customFields": { "plan": "pro" },
"createdAt": "2025-06-30T12:00:00Z"
}
],
"pagination": {
"hasMore": true,
"nextCursor": "Y3Vyc29yOnZhbHVl",
"total": 1284
}
}pagination.total is the count of contacts matching the filters, not just the
page. trackingOptOut reports whether the recipient asked not to be tracked —
see Privacy.
Update a Contact
Update a contact's details (status, tags, custom fields).
cURL
curl -X PATCH https://api.tratto.email/v1/contacts/cont_abc123 \
-H "Authorization: Bearer tratto_live_..." \
-H "Content-Type: application/json" \
-d '{
"status":"unsubscribed",
"tags":["unsubscribed"],
"customFields":{"unsubscribedAt":"2025-06-30T12:00:00Z"}
}'customFields replaces the whole object — it is not merged field by field.
Contact Status Values
| Status | Meaning |
|---|---|
subscribed | Active contact, can receive emails |
unsubscribed | Contact opted out (manually or via unsubscribe link) |
bounced | Email hard-bounced (invalid address) |
complained | Contact marked as spam |
Auto-updates:
- When an email bounces → status becomes
bounced - When a contact clicks unsubscribe → status becomes
unsubscribed - When an email is complained → status becomes
complained
bounced and complained are one-way. A contact the system suppressed
cannot be moved to any other status through the API — including
unsubscribed. PATCH returns 403 FORBIDDEN, with a message explaining
why: re-sending to a hard-bounced or complaining address damages the delivery
reputation shared by every account on the sending pool.
Re-sending the contact's current status is accepted as a no-op, so a form that PATCHes every field on save keeps working.
Tags
Use tags to organize contacts into logical groups:
vip: High-value customersnewsletter: Newsletter subscribersbeta: Beta program memberschurned: At-risk customers
Tagging use cases:
- Segment campaigns by tag
- Filter contacts for specific flows
- Track cohorts
Custom Fields
customFields is a free-form JSON object for your own properties:
{
"customFields": {
"plan": "pro",
"signupDate": "2025-01-01",
"lastPurchase": "2025-06-15",
"accountValue": 599.99
}
}Use custom fields to:
- Store your own properties on a contact
- Filter audiences by custom-field conditions
- Personalize email content with variables
There is no metadata field. A metadata object in a create or update
request is discarded without an error, so the request looks successful and the
data is simply gone. The Node SDK calls it customFields, the Python SDK
custom_fields.
Unsubscribe a Contact
There is no delete endpoint. A contact is deactivated by moving it to the
unsubscribed status, which keeps the record so it stays suppressed. A deleted
contact could be re-imported and mailed again by mistake.
cURL
curl -X PATCH https://api.tratto.email/v1/contacts/cont_abc123 \
-H "Authorization: Bearer tratto_live_..." \
-H "Content-Type: application/json" \
-d '{"status":"unsubscribed"}'Response:
{
"data": {
"id": "cont_abc123"
}
}Next Steps
Edit this page on GitHub
Last updated on