Contacts API
Relevant source files
The following files were used as context for generating this wiki page:
The Contacts API is a core component of the Send Again platform, responsible for managing recipient data within specific workspaces. It provides programmatic and user-interface driven methods to create, retrieve, update, and delete contact information, including custom metadata fields.
Beyond basic CRUD operations, the system integrates with a suppression mechanism to handle unsubscribes automatically, ensuring compliance and maintaining high deliverability rates.
API Architecture and Endpoints
The Contacts API is implemented using Next.js Route Handlers. It supports two primary authentication methods: Supabase JWT for authenticated web sessions and Bearer API keys for programmatic access. API keys can be restricted with specific scopes such as contacts.read and contacts.write.
Sources: src/lib/openapi.ts:13-25, src/app/api/contacts/route.ts:11-16
Endpoint Summary
| Method | Path | Scope Required | Description |
|---|---|---|---|
GET | /api/contacts | contacts.read | Lists all contacts in a workspace. |
POST | /api/contacts | contacts.write | Upserts multiple contacts; filters against unsubscribes. |
DELETE | /api/contacts | contacts.write | Deletes all contacts in a workspace. |
GET | /api/contacts/{email} | contacts.read | Retrieves a single contact by email. |
PUT | /api/contacts/{email} | contacts.write | Updates custom fields for a specific contact. |
DELETE | /api/contacts/{email} | contacts.write | Removes a single contact from the workspace. |
Sources: src/lib/openapi.ts:145-247, src/app/api/contacts/route.ts
Data Models
Contacts are defined by a unique email address per workspace and an arbitrary set of metadata stored as key-value pairs (fields).
This diagram shows the relationship between a Contact and the suppression list (ContactUnsubscribe).
Contact Object Structure
| Field | Type | Description |
|---|---|---|
email | string | The recipient's email address (unique identifier). |
fields | object | Arbitrary metadata (e.g., name, company). All values are stored as strings. |
Sources: src/lib/openapi.ts:32-41, src/lib/db.ts:250-253
Logic and Data Flow
Upsert and Suppression Flow
When contacts are imported via POST /api/contacts, the system performs a suppression check. Any contact found in the contact_unsubscribes table for that workspace is filtered out before the remaining contacts are persisted to the database.
The workflow for adding or updating contacts, highlighting the automatic suppression of unsubscribed users.
Sources: src/app/api/contacts/route.ts:33-66, src/lib/db.ts:404-436
Unsubscribe Processing
The unsubscribe system handles recipient requests via a dedicated route. When a user unsubscribes, the system:
- Marks the email as unsubscribed in the
contact_unsubscribestable. - Permanently deletes the contact record from the
contactstable for that workspace.
Sources: src/app/api/unsubscribe/route.ts:98-144, src/lib/db.ts:384-402
Implementation Details
Database Operations
The system utilizes a Supabase client to interact with the underlying PostgreSQL database. Key functions in src/lib/db.ts include:
getContacts(workspaceId): Fetches contacts in pages of 1000 to prevent response truncation.upsertContacts(workspaceId, contacts): Performs a bulk upsert with conflict resolution on theworkspace_id, emailconstraint.getUnsubscribedEmailSet(workspaceId, emails): Efficiently checks a batch of emails against the suppression list.
Sources: src/lib/db.ts:259-299, src/lib/db.ts:314-332, src/lib/db.ts:404-436
CSV Import Logic
The frontend implements a robust CSV parser to facilitate bulk contact management. It handles various delimiters (,, ;, \t), manages quoted values, and allows users to map CSV columns to specific contact fields.
Sources: src/app/app/page.tsx:547-669, src/app/app/page.tsx:1091-1188
Conclusion
The Contacts API provides a flexible and secure foundation for managing recipient data. By integrating automatic suppression checks and providing granular API scopes, it ensures that developers can build campaign workflows that are both efficient and compliant with recipient preferences.