Skip to main content

Audience

Everything Arsel sends targets a contact. Transactional sends can address a raw email or phone number, but campaigns, automations and analytics all resolve to contacts — so the shape of your audience determines what you can do with the rest of the platform.

There are four pieces: contacts, the identifiers that resolve them, the groupings you send to (lists, tags and segments), and the custom properties you personalize with.

Contacts and identifiers​

A contact needs at least one of three identifiers, and you may set any combination:

IdentifierWhat it is
emailEmail address
phone_numberE.164 format, e.g. +966512345678
external_idYour own user ID from your own database. Max 255 characters, unique per organization.

Prefer external_id​

external_id outranks email and phone_number everywhere in Arsel, and that ranking is the whole reason to set it:

  • Contact details change; user IDs do not. Someone updates their email address, and without an external_id you now have either a broken match or a duplicate contact. With one, their entire history stays attached.
  • Events resolve deterministically. Every event carrying an external_id lands on the right contact, including for people whose email you have never collected.
  • It makes migration survivable. Set it during import from your previous platform and every subsequent write lines up.

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

curl -X POST "https://api.arsel.sa/v1/contacts" \
-H "Authorization: Bearer $ARSEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_id": "user_8821",
"email": "customer@example.com",
"phone_number": "+966512345678",
"first_name": "Sara",
"properties": { "lifetime_value": 2400, "is_vip": true },
"list_ids": ["0192a1b2-c3d4-7e5f-9000-abcdef123456"]
}'

Lists vs tags​

Both group contacts by hand, and campaigns accept either — list_ids, tag_ids, or both. The difference is intent, not mechanics.

ListsTags
Model it asWhere someone subscribed — "Newsletter", "Product updates"An attribute someone has — "VIP", "churned", "webinar-attendee"
Typical countA handfulMany
MembershipA contact can be on severalA contact can carry several
Set at creationYes, via list_ids on Create ContactNo — apply afterwards via Tag Contacts

If you find yourself creating a list called "VIP", you want a tag. If you find yourself tagging everyone who signed up through one form, you want a list.

Segments​

Lists and tags are memberships you maintain. A segment is a rule: the contacts that currently match a filter — "opened three emails in the last 90 days", "on the pro plan and subscribed to SMS". Membership is dynamic: it follows the rules as contacts change.

Create one through the API or in the dashboard under Audience > Segments, wait for its status to become ready, then pass its id in a campaign's segment_ids. To see who is in it, call GET /contacts?segment_id=.

Custom properties​

Custom properties store your own data on contacts and are what {{variable}} merge tags read from in campaigns.

Properties are schema-first: define the property before writing values to it. Create a property with a field_key (lowercase letters, digits and underscores, starting with a letter), a human-readable display_name, and a data_type of string, number, boolean or date.

{
"field_key": "lifetime_value",
"display_name": "Lifetime Value",
"data_type": "number",
"fallback_value": "0"
}

Two things to get right the first time, because neither can be changed afterwards:

  • field_key is immutable. Renaming means creating a new property and migrating values.
  • data_type is immutable. A property created as string cannot later become number.

Set a fallback_value on anything you merge into a subject line or message body — it is what renders for contacts with no value, and the alternative is a blank space where a name should be.

Reserved keys

id, email and unsubscribed collide with built-in contact columns and are rejected. Everything else is yours — custom properties live in their own contact.properties namespace.

A workable order of operations​

  1. Define your custom properties — before importing, so values land rather than being rejected.
  2. Create the lists people will subscribe to.
  3. Import or create contacts with external_id set, properties filled, and list_ids attached.
  4. Apply tags for attributes that change over time.
  5. Send events as people act, which keeps behavioural history attached to the same contacts.

Reference​

ContactsCreate, list, update, delete
ListsCreate, list, update, delete, list members
TagsCreate, list, update, delete, tag and untag contacts
SegmentsCreate, list, update, delete, and the filter reference
PropertiesDefine and manage the custom property schema