Contacts
Manage contacts and bulk import via JSON
Contacts are the recipients in your email lists. Each contact belongs to the authenticated user and is isolated from other users' contacts.
Authentication
Read endpoints require an API key with the read or contacts scope; write endpoints require the write or contacts scope. Base URL: https://api.misar.io/mail.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v1/contacts | List contacts (paginated) |
POST | /api/v1/contacts | Create a contact |
DELETE | /api/v1/contacts?id= | Delete a contact |
POST | /api/v1/contacts/import | Bulk import (JSON) |
List contacts
/mail/v1/contactsList contacts with optional filtering and pagination.
Query parameters
pageintegerquerydefault: 1Page number.
limitintegerquerydefault: 20Results per page (max 100).
statusstringqueryFilter: subscribed, unsubscribed, bounced, complained.
searchstringquerySearch by email or name (max 100 characters).
Response fields
successbooleantrue when the request succeeded.
dataArray<Contact>The page of contacts. Each contact includes id, email, phone, first_name, last_name, status, custom_fields, engagement_score, sms_opted_in, created_at, and updated_at.
paginationobjectPagination metadata: page, limit, total, and totalPages.
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"phone": null,
"first_name": "Jane",
"last_name": "Doe",
"status": "subscribed",
"custom_fields": { "plan": "pro" },
"engagement_score": 42,
"sms_opted_in": false,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-20T08:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1234,
"totalPages": 62
}
}Create a contact
/mail/v1/contactsCreate a single contact. Plan limits apply.
Request body
emailstringbodyrequiredMust be a valid email.
firstNamestringbodyContact's first name.
lastNamestringbodyContact's last name.
tagsstring[]bodyUp to 50 tags.
customFieldsobjectbodyCustom key-value data.
statusstringbodysubscribed (default), unsubscribed, bounced, complained.
sourcestringbodyWhere the contact came from (max 255 characters).
Response fields
successbooleantrue when the contact was created.
dataobjectThe created contact, including id and email.
{
"email": "user@example.com",
"firstName": "Jane",
"lastName": "Doe",
"tags": ["customer"],
"customFields": { "plan": "pro", "signup_source": "website" },
"status": "subscribed",
"source": "website"
}{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com"
}
}Errors
403— Contact limit reached for your plan409— Email already exists in your contacts
Delete a contact
/mail/v1/contactsPermanently delete a contact. This also removes them from all segments.
Query parameters
idUUIDqueryrequiredID of the contact to delete.
Response fields
successbooleantrue when the contact was deleted.
curl -X DELETE "https://api.misar.io/mail/v1/contacts?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer msk_YOUR_API_KEY"{ "success": true }Bulk import contacts
/mail/v1/contacts/importBulk import contacts from a JSON body. Send a JSON array of 1 to 5,000 contacts.
Request body
contactsArray<Contact>bodyrequiredContacts to import (1–5,000). Each entry accepts the same fields as a single create (email, firstName, tags, etc.).
updateExistingbooleanbodydefault: falseWhen true, existing contacts matched by email are updated instead of skipped.
Response fields
successbooleantrue when the import completed.
summaryobjectImport counts: imported, updated, skipped, and errors (total error count).
errorsstring[]Human-readable error messages (up to the first 20).
{
"contacts": [
{ "email": "alice@example.com", "firstName": "Alice", "tags": ["newsletter"] },
{ "email": "bob@example.com", "firstName": "Bob" }
],
"updateExisting": true
}{
"success": true,
"summary": {
"imported": 1842,
"updated": 143,
"skipped": 15,
"errors": 1
},
"errors": [
"Row 3 (invalid-email): Invalid email format"
]
}Errors
403— Bulk import not available on Free plan403— Contact limit would be exceeded by this import415— Request body must be JSON (Content-Type: application/json)