Creates a new contact. If a contact with the same email already exists in the workspace the record is upserted — fields provided in the request are updated and the existing contact is returned.
Requires editor role or higher.
Parameters
Email address. At least one of email or phone is required. Used for deduplication.
Phone number in international format (e.g. +4917612345678). At least one of email or phone is required.
Your own identifier for this contact (e.g. a CRM or user ID). Must be unique within the workspace.
First name. Max 100 characters.
Last name. Max 100 characters.
How the contact was added. One of: API, IMPORT, LANDING_PAGE, MANUAL.
Array of string labels. Used for campaign segmentation.
Arbitrary key-value pairs for additional attributes.
Request
curl -sS -X POST "https://api.arowana.app/v1/contacts" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "jana@example.com",
"phone": "+4917612345678",
"first_name": "Jana",
"last_name": "Müller",
"source": "API",
"tags": ["vip", "germany"],
"custom_fields": { "loyalty_tier": "gold" }
}'
Response
201 Created
200 OK — upsert
400 Bad Request
{
"id": "c_a1b2c3d4",
"external_id": null,
"email": "jana@example.com",
"phone": "+4917612345678",
"first_name": "Jana",
"last_name": "Müller",
"status": "ACTIVE",
"source": "API",
"tags": ["vip", "germany"],
"custom_fields": { "loyalty_tier": "gold" },
"created_at": "2026-03-28T09:00:00Z",
"updated_at": "2026-03-28T09:00:00Z"
}
Returned when a contact with the same email already exists. The record is updated with the provided fields.{
"id": "c_existing123",
"email": "jana@example.com",
"first_name": "Jana",
"last_name": "Müller",
"status": "ACTIVE",
"source": "API",
"tags": ["vip", "germany"],
"custom_fields": { "loyalty_tier": "gold" },
"created_at": "2026-01-10T08:00:00Z",
"updated_at": "2026-03-28T09:05:00Z"
}
{ "error": "validation_error", "message": "At least one of email or phone is required." }