Skip to main content

Create Contact

Add a new contact to your organization. Campaigns, automations and analytics all resolve to contacts, so this is what everything else targets.

Endpoint

POST /contacts

Returns: 201 Created

Headers

HeaderValueRequired
AuthorizationBearer <your-api-key>Yes
Content-Typeapplication/jsonYes

Body Parameters

ParameterTypeRequiredDescription
emailstringConditionalContact's email address.
phone_numberstringConditionalPhone number in E.164 format (e.g., +966512345678).
external_idstringConditionalYour own identifier for this person. Max 255 characters, unique within your organization.
first_namestringNoFirst name. Max 100 characters.
last_namestringNoLast name. Max 100 characters.
propertiesobjectNoCustom property key-value pairs. Keys must match your organization's custom property schema.
list_idsstring[]NoArray of list IDs to add the contact to upon creation.
At Least One Identifier

You must provide at least one of email, phone_number or external_id. You may provide any combination.

Using external_id

external_id is the identifier you already use for this person — a user ID from your own database. It outranks email and phone_number everywhere in Arsel, which makes it the right key for two jobs:

  • Migrating from another platform. Set it during import and every later event resolves to the same contact deterministically, even for people whose email you don't have.
  • People whose contact details change. An email or phone can be edited; external_id stays put, so history stays attached to the right person.

Reusing an external_id that another contact already holds returns 409. To find whether you have already imported someone, filter for it on List contacts rather than searching by email.

Custom Properties

Custom properties let you store additional data on contacts. Define your property schema in the Arsel Dashboard under Contacts > Properties before sending values.

{
"properties": {
"company": "Acme Inc",
"age": 30,
"is_vip": true,
"birthdate": "1995-06-15"
}
}

Response

{
"id": "01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a",
"email": "john.doe@example.com",
"phone_number": "+201234567890",
"external_id": "user_10294",
"first_name": "John",
"last_name": "Doe",
"source": "api",
"properties": {
"company": "Acme Inc"
},
"is_suppressed": false,
"created_at": "2026-03-08T12:00:00.000Z",
"updated_at": "2026-03-08T12:00:00.000Z"
}
FieldTypeDescription
idstringUnique contact ID (UUIDv7)
emailstring | nullContact email address
phone_numberstring | nullContact phone number
external_idstring | nullYour own identifier for this person
first_namestring | nullFirst name
last_namestring | nullLast name
sourcestringHow the contact was created: api, manual, import, transactional
propertiesobjectCustom property values
is_suppressedbooleantrue if the contact has unsubscribed, bounced, been blocked by email validation, or been manually suppressed
created_atstringISO 8601 timestamp
updated_atstringISO 8601 timestamp
tip

Contacts created via the API have their source set to api automatically.


Examples

Basic Contact

curl -X POST "https://api.arsel.sa/v1/contacts" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"email": "john.doe@example.com",
"first_name": "John",
"last_name": "Doe"
}'

With Custom Properties and Lists

curl -X POST "https://api.arsel.sa/v1/contacts" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"email": "sara@example.com",
"phone_number": "+966512345678",
"first_name": "Sara",
"last_name": "Ahmed",
"properties": {
"company": "Acme Inc",
"job_title": "Marketing Manager",
"city": "Riyadh"
},
"list_ids": ["01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a"]
}'

Error Responses

{
"status_code": 422,
"name": "validation_error",
"message": "At least one of email or phone_number must be provided"
}