--- title: Working with Contact Data description: Use persistent and temporary contact data for personalized emails --- ## Contact Data Basics Every contact has: - **email**: Required, unique identifier - **subscribed**: Boolean for subscription status - **data**: JSON object for custom fields ```javascript { "email": "user@example.com", "subscribed": true, "data": { "firstName": "Jane", "plan": "professional", "signupDate": "2024-03-15" } } ``` ## Persistent vs. Temporary Data When sending emails, you can pass data that either saves to the contact or is used only for that email. ### Persistent Data (Default) ```javascript fetch('/v1/send', { method: 'POST', body: JSON.stringify({ to: 'user@example.com', subject: 'Welcome', body: '
Hi {'{{firstName}}'}!
', data: { firstName: 'John' // Saved to contact.data.firstName } }) }); ``` ### Temporary Data (Non-Persistent) ```javascript fetch('/v1/send', { method: 'POST', body: JSON.stringify({ to: 'user@example.com', subject: 'Password Reset', body: 'Your code: {'{{resetCode}}'}
', data: { resetCode: { value: 'ABC123', persistent: false // NOT saved to contact } } }) }); ``` **Use temporary data for**: - Password reset codes - One-time verification tokens - Session-specific information - Temporary discount codes ## Template Variables Use `{'{{fieldName}}'}` to insert contact data into emails. ### Basic Variables ```htmlHello {'{{firstName}}'}!
Your plan: {'{{plan}}'}
``` ### Fallback Values Provide defaults when data might be missing: ```htmlHello {'{{firstName ?? \'there\'}}'}!
Plan: {'{{plan ?? \'Free\'}}'}
``` ### Reserved Fields Two fields are always available: ```htmlContact ID: {'{{plunk_id}}'}
Email: {'{{plunk_email}}'}
``` ## Data Merging Updates merge with existing data: ```javascript // Contact has: { firstName: 'John', plan: 'free' } // Update with: { data: { lastName: 'Doe', plan: 'pro' } } // Result: { firstName: 'John', lastName: 'Doe', plan: 'pro' } ``` ## Best Practices ### Keep Data Flat ```javascript // Good { "firstName": "Jane", "plan": "pro", "mrr": 99 } // Avoid nesting (harder to use in templates) { "user": { "profile": { "name": "Jane" } } } ``` ### Use Consistent Naming Pick a style and stick to it: ```javascript // camelCase (recommended) { "firstName": "Jane", "lastLogin": "2024-03-15" } // or snake_case { "first_name": "Jane", "last_login": "2024-03-15" } ``` ### Store Dates as ISO Strings ```javascript // Good (filterable, sortable) { "signupDate": "2024-03-15T10:30:00Z" } // Avoid { "signupDate": "March 15, 2024" } ``` ## Discovering Available Fields Get all fields across your contacts: ```bash curl -X GET "{{API_URL}}/contacts/fields" \ -H "Authorization: Bearer sk_your_secret_key" ``` Response: ```json { "success": true, "data": { "fields": [ "email", "subscribed", "firstName", "plan", "signupDate" ], "count": 5 } } ``` Get unique values for a field: ```bash curl -X GET "{{API_URL}}/contacts/fields/data.plan/values" \ -H "Authorization: Bearer sk_your_secret_key" ``` Response: ```json { "success": true, "data": { "field": "data.plan", "values": ["free", "professional", "enterprise"], "count": 3 } } ``` ## Next Steps - [Send personalized emails](/guides/templates) - [Create segments](/guides/segments) based on contact data - [Track events](/guides/events) to enrich contact profiles