Contacts

Contacts represent individual subscribers. Contacts belong to a project and can be members of multiple lists.

Unsubscribe URLs

All contact responses include an unsubscribe_urls hash mapping list IDs to unsubscribe URLs. When fetching contacts from a specific list endpoint, use the unsubscribe_url field (singular) for that list. Include these URLs in your email templates to provide recipients with unsubscribe functionality.

GET /api/v1/projects/:project_id/contacts

Retrieve all contacts for a project. Results are paginated.

Parameters

Name Type Required Description
project_id integer Yes The project ID
page integer No Page number (default: 1)
per_page integer No Items per page (default: 25)

Success response (200)

client.contacts(project_id: 1, page: 1)
# => {
#   "data" => [
#     {
#       "id" => 1,
#       "project_id" => 1,
#       "email" => "user@example.com",
#       "first_name" => "John",
#       "last_name" => "Doe",
#       "full_name" => "John Doe",
#       "unsubscribed_at" => nil,
#       "active" => true,
#       "lists_count" => 2,
#       "unsubscribe_urls" => {
#         1 => "https://emaillist.dev/unsubscribe/abc123token...",
#         2 => "https://emaillist.dev/unsubscribe/def456token..."
#       },
#       "created_at" => "2024-01-01T00:00:00Z",
#       "updated_at" => "2024-01-01T00:00:00Z"
#     }
#   ],
#   "meta" => {
#     "page" => 1,
#     "per_page" => 25,
#     "total" => 100,
#     "total_pages" => 4
#   }
# }
GET /api/v1/projects/:project_id/contacts/:id

Retrieve a specific contact by ID.

Parameters

Name Type Required Description
project_id integer Yes The project ID
id integer Yes The contact ID

Success response (200)

client.contact(project_id: 1, id: 1)
POST /api/v1/projects/:project_id/contacts

Create a new contact in a project.

Parameters

Name Type Required Description
project_id integer Yes The project ID

Request body

client.create_contact(
  project_id: 1,
  email: 'user@example.com',
  first_name: 'John',
  last_name: 'Doe'
)

Success response (201)

{
  "data" => {
    "id" => 1,
    "project_id" => 1,
    "email" => "user@example.com",
    "first_name" => "John",
    "last_name" => "Doe",
    "full_name" => "John Doe",
    "unsubscribed_at" => nil,
    "active" => true,
    "lists_count" => 0,
    "unsubscribe_urls" => {},
    "created_at" => "2024-01-01T00:00:00Z",
    "updated_at" => "2024-01-01T00:00:00Z"
  }
}

Error responses

Status: 422 - validation_error

{
  "error" => {
    "code" => "validation_error",
    "message" => "Validation failed",
    "details" => {
      "email" => ["can't be blank", "is invalid"]
    }
  }
}
PATCH /api/v1/projects/:project_id/contacts/:id

Update an existing contact.

Parameters

Name Type Required Description
project_id integer Yes The project ID
id integer Yes The contact ID

Request body

client.update_contact(
  project_id: 1,
  id: 1,
  email: 'newemail@example.com',
  first_name: 'Jane'
)

Success response (200)

{
  "data" => {
    "id" => 1,
    "project_id" => 1,
    "email" => "newemail@example.com",
    "first_name" => "Jane",
    "last_name" => "Doe",
    "full_name" => "Jane Doe",
    "unsubscribed_at" => nil,
    "active" => true,
    "lists_count" => 2,
    "unsubscribe_urls" => {
      1 => "https://emaillist.dev/unsubscribe/abc123token...",
      2 => "https://emaillist.dev/unsubscribe/def456token..."
    },
    "created_at" => "2024-01-01T00:00:00Z",
    "updated_at" => "2024-01-02T00:00:00Z"
  }
}
POST /api/v1/projects/:project_id/contacts/upsert

Create or update a contact by email. If a contact with the given email exists, it will be updated (returns 200 OK). Otherwise, a new contact will be created (returns 201 Created). This is useful for syncing contacts without needing to check if they exist first.

Parameters

Name Type Required Description
project_id integer Yes The project ID

Request body

client.upsert_contact(
  project_id: 1,
  email: 'user@example.com',
  first_name: 'John',
  last_name: 'Doe'
)

Success response (201)

# Returns 201 Created for new contacts, 200 OK for updates
client.upsert_contact(
  project_id: 1,
  email: 'user@example.com',
  first_name: 'John',
  last_name: 'Doe'
)
# => {
#   "data" => {
#     "id" => 1,
#     "project_id" => 1,
#     "email" => "user@example.com",
#     "first_name" => "John",
#     "last_name" => "Doe",
#     "full_name" => "John Doe",
#     "unsubscribed_at" => nil,
#     "active" => true,
#     "lists_count" => 0,
#     "unsubscribe_urls" => {},
#     "created_at" => "2024-01-01T00:00:00Z",
#     "updated_at" => "2024-01-01T00:00:00Z"
#   }
# }

Error responses

Status: 422 - validation_error

{
  "error" => {
    "code" => "validation_error",
    "message" => "Email is required"
  }
}
DELETE /api/v1/projects/:project_id/contacts/:id

Delete a contact. This will also remove the contact from all lists.

Parameters

Name Type Required Description
project_id integer Yes The project ID
id integer Yes The contact ID

Success response (204)

# No content