--- title: Contacts and Data description: Store and manage your audience icon: Users --- ## What are contacts Contacts are people in your email list. Each contact has: - **Email** — Unique identifier - **Subscription status** — Subscribed or unsubscribed - **Custom data** — Any fields you need ## Data structure ```json { "id": "contact_abc123", "email": "user@example.com", "subscribed": true, "data": { "firstName": "Sarah", "plan": "pro", "mrr": 99 } } ``` The `data` field stores custom information as key-value pairs. ## Data types **Strings:** ```json { "firstName": "Sarah", "company": "Acme Inc" } ``` **Numbers:** ```json { "mrr": 99, "loginCount": 15 } ``` Store as numbers for `greaterThan`/`lessThan` comparisons. **Booleans:** ```json { "verified": true, "newsletter": false } ``` **Dates:** ```json { "signupDate": "2024-03-15T10:30:00Z" } ``` Use ISO 8601 format. **Arrays:** ```json { "tags": ["vip", "enterprise"] } ``` **Objects:** ```json { "address": { "city": "San Francisco", "country": "US" } } ``` Access nested fields: `address.country` ## Creating contacts ### Via API ```bash curl -X POST {{API_URL}}/contacts \ -H "Authorization: Bearer sk_your_secret_key" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "subscribed": true, "data": { "firstName": "Sarah", "plan": "pro" } }' ``` ### Automatic upsert If email exists, updates instead of creating duplicate. ```javascript // First call POST /contacts { email: "user@example.com", data: { plan: "free" } } // Second call - updates same contact POST /contacts { email: "user@example.com", data: { mrr: 99 } } // Result: { plan: "free", mrr: 99 } ``` Data merges automatically. ### Via event tracking ```bash curl -X POST {{API_URL}}/v1/track \ -H "Authorization: Bearer pk_your_public_key" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com", "event": "signed_up", "data": { "plan": "pro", "source": "landing" } }' ``` Creates contact if doesn't exist, updates if does. ## Updating contacts ```bash curl -X PATCH {{API_URL}}/contacts/contact_id \ -H "Authorization: Bearer sk_your_secret_key" \ -H "Content-Type: application/json" \ -d '{ "data": { "plan": "premium", "mrr": 199 } }' ``` New fields added, existing fields overwritten, unmentioned fields preserved. ### Remove fields Set to `null`: ```json { "data": { "temporaryToken": null } } ``` ## Subscription status **Subscribed (true):** - Receives marketing emails - Receives transactional emails **Unsubscribed (false):** - Does NOT receive marketing emails - Still receives transactional emails Template type controls this behavior. See [Template Types](/concepts/templates-types). ## Using contact data ### In templates ```html

Hi {{firstName}}!

Your {{plan}} plan renews on {{renewalDate}}.

``` ### In segments Filter by data fields: - `plan equals "premium"` - `mrr greaterThan 100` - `loginCount lessThan 5` ### In workflows ``` [Condition: plan equals "enterprise"] ├─ True → [Send: Enterprise content] └─ False → [Send: Standard content] ``` ## Best practices **Consistent naming** — Use camelCase or snake_case, not both. **Correct types** — Use `99` not `"99"` for numbers. **ISO dates** — `"2024-03-15T10:30:00Z"` for date fields. **Sync critical fields only** — Don't mirror entire database. Only fields used in emails, segments, or workflows. **Update in real-time** — When user data changes, update contact immediately. **Respect unsubscribes** — Never re-subscribe automatically. ## Deleting contacts ```bash curl -X DELETE {{API_URL}}/contacts/contact_id \ -H "Authorization: Bearer sk_your_secret_key" ``` Permanent deletion. Consider unsubscribing instead to preserve history. ## Next steps - [Create segments](/concepts/segments-and-filters) - [Track events](/concepts/events-and-triggers) - [Use templates](/concepts/templates-types)