unsent
unsent.dev
API Reference

Contacts

The Contacts API allows you to manage contacts within contact books for your email campaigns.

Base URL

https://api.unsent.dev/v1/contactBooks/{contactBookId}/contacts

Overview

The Contacts API provides comprehensive endpoints for managing individual contacts within your contact books. You can create, retrieve, update, upsert, and delete contacts, as well as query them using various filters.

Features

Create contacts

Add new contacts with email, name, and custom properties

List & filter contacts

Retrieve contacts with pagination and filters by email or ID

Upsert contacts

Create or update contacts in a single operation

Update contacts

Modify contact information and properties

Search by email/ID

Filter contacts by specific emails or contact IDs

Delete contacts

Remove contacts from your contact books

API Endpoints

List Contacts

GET /contactBooks/{contactBookId}/contacts

Retrieve multiple contacts from a contact book with optional filtering and pagination.

Query Parameters

ParameterTypeRequiredDescription
pagenumberNoPage number for pagination (default: 1)
limitnumberNoNumber of contacts per page (default: 5000)
emailsstringNoComma-separated list of email addresses to filter
idsstringNoComma-separated list of contact IDs to filter

Example Request

# Get all contacts with pagination
curl -X GET "https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts?page=1&limit=50" \
  -H "Authorization: Bearer your-api-key"

# Filter by specific emails
curl -X GET "https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts?emails=john@example.com,jane@example.com" \
  -H "Authorization: Bearer your-api-key"

# Filter by contact IDs
curl -X GET "https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts?ids=contact_1,contact_2" \
  -H "Authorization: Bearer your-api-key"

Response

[
  {
    "id": "cuiwqdj74rygf74",
    "email": "john.doe@example.com",
    "firstName": "John",
    "lastName": "Doe",
    "subscribed": true,
    "properties": {
      "company": "Acme Corp",
      "phone": "+1-555-0123"
    },
    "contactBookId": "book_123",
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
]

Get Single Contact

GET /contactBooks/{contactBookId}/contacts/{contactId}

Retrieve a specific contact by ID.

Path Parameters

ParameterTypeRequiredDescription
contactBookIdstringYesThe contact book ID
contactIdstringYesThe contact ID to retrieve

Example Request

curl -X GET https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts/contact_abc123 \
  -H "Authorization: Bearer your-api-key"

Response

{
  "id": "contact_abc123",
  "email": "john.doe@example.com",
  "firstName": "John",
  "lastName": "Doe",
  "subscribed": true,
  "properties": {
    "company": "Acme Corp",
    "role": "Manager"
  },
  "contactBookId": "cuiwqdj74rygf74",
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-20T14:45:00Z"
}

Create Contact

POST /contactBooks/{contactBookId}/contacts

Add a new contact to a contact book.

Request Body

FieldTypeRequiredDescription
emailstringYesContact's email address
firstNamestringNoContact's first name
lastNamestringNoContact's last name
subscribedbooleanNoSubscription status (default: true)
propertiesobjectNoCustom key-value pairs

Example Request

curl -X POST https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john.doe@example.com",
    "firstName": "John",
    "lastName": "Doe",
    "subscribed": true,
    "properties": {
      "company": "Acme Corp",
      "phone": "+1-555-0123",
      "source": "newsletter_signup"
    }
  }'

Response

{
  "contactId": "contact_new123"
}

Update Contact

PATCH /contactBooks/{contactBookId}/contacts/{contactId}

Update an existing contact's information. Only the provided fields will be updated.

Request Body

FieldTypeRequiredDescription
firstNamestringNoUpdated first name
lastNamestringNoUpdated last name
subscribedbooleanNoUpdated subscription status
propertiesobjectNoUpdated custom properties

Note: Email addresses cannot be updated via PATCH. Use the upsert endpoint instead.

Example Request

curl -X PATCH https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts/contact_abc123 \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Johnathan",
    "subscribed": false,
    "properties": {
      "last_purchase": "2024-01-15",
      "tier": "premium"
    }
  }'

Response

{
  "contactId": "contact_abc123"
}

Upsert Contact

PUT /contactBooks/{contactBookId}/contacts/{contactId}

Create a new contact or update an existing one based on the email address. This is useful when you're not sure if the contact already exists.

Request Body

FieldTypeRequiredDescription
emailstringYesContact's email address
firstNamestringNoContact's first name
lastNamestringNoContact's last name
subscribedbooleanNoSubscription status
propertiesobjectNoCustom key-value pairs

Example Request

curl -X PUT https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts/any_id \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane.smith@example.com",
    "firstName": "Jane",
    "lastName": "Smith",
    "subscribed": true,
    "properties": {
      "source": "website_signup",
      "plan": "premium"
    }
  }'

Response

{
  "contactId": "contact_xyz789"
}

Delete Contact

DELETE /contactBooks/{contactBookId}/contacts/{contactId}

Permanently remove a contact from a contact book.

Path Parameters

ParameterTypeRequiredDescription
contactBookIdstringYesThe contact book ID
contactIdstringYesThe contact ID to delete

Example Request

curl -X DELETE https://api.unsent.dev/v1/contactBooks/cuiwqdj74rygf74/contacts/contact_abc123 \
  -H "Authorization: Bearer your-api-key"

Response

{
  "success": true
}

Interactive API Reference

Data Model

Contact Object

{
  id: string;                           // Unique contact identifier
  email: string;                        // Contact's email address
  firstName?: string | null;            // Contact's first name
  lastName?: string | null;             // Contact's last name
  subscribed: boolean;                  // Subscription status (default: true)
  properties: Record<string, string>;   // Custom properties
  contactBookId: string;                // Parent contact book ID
  createdAt: string;                    // ISO 8601 timestamp
  updatedAt: string;                    // ISO 8601 timestamp
}

Custom Properties

Custom properties allow you to store additional information about contacts. All property values must be strings.

{
  "properties": {
    "company": "Acme Corp",
    "phone": "+1-555-0123",
    "country": "United States",
    "signup_date": "2024-01-01",
    "customer_tier": "premium",
    "purchase_count": "15",
    "referral_source": "google_ads"
  }
}

Filtering & Pagination

Pagination

Use page and limit parameters to paginate through large contact lists:

# First page with 100 contacts
GET /contactBooks/{id}/contacts?page=1&limit=100

# Second page
GET /contactBooks/{id}/contacts?page=2&limit=100

Filtering by Email

Retrieve specific contacts by email addresses:

GET /contactBooks/{id}/contacts?emails=user1@example.com,user2@example.com

Filtering by ID

Retrieve specific contacts by their IDs:

GET /contactBooks/{id}/contacts?ids=contact_1,contact_2,contact_3

Combining Filters

You can combine pagination with filters:

GET /contactBooks/{id}/contacts?emails=user@example.com&page=1&limit=10

Subscription Management

Opt-in Status

  • subscribed: true - Contact can receive emails (default)
  • subscribed: false - Contact will not receive emails

Unsubscribing Contacts

curl -X PATCH https://api.unsent.dev/v1/contactBooks/{contactBookId}/contacts/{contactId} \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"subscribed": false}'

Common Use Cases

Newsletter Subscribers

{
  "email": "subscriber@example.com",
  "firstName": "Jane",
  "subscribed": true,
  "properties": {
    "source": "website_form",
    "interests": "technology,business",
    "signup_date": "2024-01-15"
  }
}

E-commerce Customers

{
  "email": "customer@example.com",
  "firstName": "John",
  "lastName": "Doe",
  "subscribed": true,
  "properties": {
    "customer_id": "CUST_12345",
    "tier": "premium",
    "last_purchase": "2024-01-10",
    "total_orders": "15",
    "lifetime_value": "2500"
  }
}

Event Attendees

{
  "email": "attendee@example.com",
  "firstName": "Sarah",
  "subscribed": true,
  "properties": {
    "event_id": "EVENT_2024",
    "ticket_type": "VIP",
    "dietary_restrictions": "vegetarian",
    "checked_in": "true"
  }
}

SaaS Users

{
  "email": "user@startup.com",
  "firstName": "Alex",
  "lastName": "Johnson",
  "subscribed": true,
  "properties": {
    "user_id": "usr_abc123",
    "plan": "pro",
    "signup_date": "2024-01-01",
    "trial_ends": "2024-01-15",
    "feature_usage": "high"
  }
}

Best Practices

  1. Validate email addresses before adding contacts to ensure data quality
  2. Use meaningful property names for consistency across your contact base
  3. Implement proper error handling for duplicate emails and validation errors
  4. Use upsert operations when you're unsure if a contact exists
  5. Respect privacy regulations (GDPR, CCPA, etc.) and obtain proper consent
  6. Regularly clean contact data to remove bounced or invalid emails
  7. Use pagination when retrieving large contact lists to improve performance
  8. Store timestamps as strings in custom properties for consistency

Error Handling

Common Errors

Status CodeErrorDescription
400Bad RequestInvalid email format or missing required fields
404Not FoundContact or contact book not found
409ConflictContact with this email already exists (POST only)
500Internal Server ErrorServer-side error occurred

Example Error Response

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Contact not found"
  }
}

Rate Limits

  • Contact operations: 500 requests per minute
  • Bulk contact retrieval: 100 requests per minute
  • Contact book ID must belong to your team