Rutba CRM

Contacts API

List, search, read and create contacts, read their store orders and add notes through the Rutba CRM REST API.

These endpoints read and create the people and companies in your workspace. They follow the same rules as the screens: duplicates are caught, plan limits apply, and erased or merged contacts are gone. The shared rules for keys, JSON and limits are in REST API.

The contact object

Every contact endpoint returns contacts with these fields:

Field Type Meaning
id string The contact's UUID
name string Full name of the person, or the company's name
company_name string or null Company the person works for
job_title string or null Job title
email string or null Email address, lower-cased
phone string or null Phone in one comparable form, such as +966500000000
status string lead, prospect, customer or inactive
source string manual, website, referral, phone, messaging, social, event or other
country string or null Two-letter country code, such as SA
preferred_locale string or null en, ar, tr or fr
marketing_opt_out boolean true when the contact must not receive marketing
archived boolean true when the contact is archived

The owner, the revision number and the internal history are not part of the API.

List and search contacts

GET /contacts?q=SEARCH&page=1
Parameter Rules
q Optional. Up to 120 characters. Matches words in the name, company name, email and phone
page Optional. A whole number from 1 to 99999. Defaults to 1
curl "https://rutbacrm.com/api/v1/contacts?q=maryam" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
{
  "data": [
    {
      "id": "CONTACT_ID",
      "archived": false,
      "marketing_opt_out": false,
      "name": "Maryam Saleh",
      "company_name": null,
      "job_title": null,
      "email": "maryam@example.com",
      "phone": "+966500000001",
      "preferred_locale": "ar",
      "country": "SA",
      "source": "website",
      "status": "lead"
    }
  ],
  "page": 1,
  "pages": 1,
  "total": 1
}

Results come 25 a page, most recently updated first. The list leaves out archived contacts, and contacts that were merged into another or erased. A q longer than 120 characters or a page that is not a valid number returns 422.

Read one contact

GET /contacts/CONTACT_ID

Returns the contact with two extra fields:

Field Meaning
tags The contact's tag names, alphabetical, up to 20
custom_fields An object of custom field keys and values, when your plan includes Custom fields. Values are strings, or null when empty. A ticked checkbox is "1". Without the feature, or with no fields, this is an empty list []
{
  "data": {
    "id": "CONTACT_ID",
    "archived": false,
    "marketing_opt_out": false,
    "name": "Maryam Saleh",
    "company_name": null,
    "job_title": null,
    "email": "maryam@example.com",
    "phone": "+966500000001",
    "preferred_locale": "ar",
    "country": "SA",
    "source": "website",
    "status": "lead",
    "tags": ["VIP"],
    "custom_fields": {
      "city": "Riyadh"
    }
  }
}

A custom field's key is made from its label when the field is created, so a field labelled "City" has the key city. An archived contact is still returned, with "archived": true. A contact that was erased or merged into another returns 404, as does an ID from another company.

Create a contact

POST /contacts

Needs a Read and write key whose creator is a member, administrator or owner.

Field Required Rules
name Yes Up to 160 characters
email No A valid address, up to 254 characters. Stored lower-cased
phone No 6 to 15 digits, with an optional leading +. Spaces, dashes, brackets and Arabic digits are cleaned up, and a leading 00 becomes +
company_name No Up to 160 characters
job_title No Up to 120 characters
status No lead, prospect, customer or inactive. Defaults to lead
source No One of the sources in the table above. Defaults to manual
country No Two letters. Stored upper-case
preferred_locale No en, ar, tr or fr
confirm_duplicate No true to create the contact even when it may be a duplicate

Other fields are ignored. Contacts created through the API are always people, with no owner. Tags and custom fields cannot be set through the API.

curl -X POST https://rutbacrm.com/api/v1/contacts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name": "Maryam Saleh", "email": "maryam@example.com", "phone": "+966 50 000 0001", "source": "website"}'

A new contact returns 201:

{
  "data": {
    "id": "CONTACT_ID"
  }
}

Possible duplicates

If another contact already has the same email or the same phone, nothing is created and the response is 409, with the IDs of up to five matching contacts:

{
  "message": "Possible duplicate.",
  "matches": ["EXISTING_CONTACT_ID"]
}

Use the existing contact, or send the same request again with "confirm_duplicate": true if it really is a different person.

Validation errors

Invalid fields return 422 with an errors object:

{
  "message": "The Name field is required. (and 1 more error)",
  "errors": {
    "name": ["The Name field is required."],
    "email": ["The Email field must be a valid email address."]
  }
}

When your plan has a contact limit and it is reached, the response is 422 with the error under limit.

Read a contact's orders

GET /contacts/CONTACT_ID/orders

Returns the orders that connected stores sent for this contact. Quote requests are not included.

{
  "data": {
    "orders": [
      {
        "number": "1001",
        "status": "completed",
        "total": "1,250.50 SAR",
        "campaign": "ramadan-sale",
        "placed_at": "2026-11-06T10:00:00.000000Z"
      }
    ],
    "count": 3,
    "totals": {
      "SAR": "3,480.00 SAR"
    }
  }
}
Field Meaning
orders The 10 newest orders, newest first
orders[].number The store's order number, or the store's order ID when it sent no number
orders[].status The status the store sent, lower-cased
orders[].total The total formatted with its currency, for display
orders[].campaign The campaign name, or the campaign source, or null
count How many of the contact's orders count as sales: paid, processing, completed or delivered
totals The sum of those sales for each currency, formatted

Add a note

POST /contacts/CONTACT_ID/notes

Needs a Read and write key whose creator is a member, administrator or owner.

Field Required Rules
body Yes Text up to 5000 characters. Leading and trailing spaces are removed
curl -X POST https://rutbacrm.com/api/v1/contacts/CONTACT_ID/notes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"body": "Asked about delivery to Jeddah."}'
{
  "data": {
    "saved": true
  }
}

The note appears on the contact's page and in its activity, written by the person who created the key. An erased or merged contact returns 404 and takes no note.

Good to know

  • Contacts created through the API do not count as new leads for automations, sequences or the A new lead arrives webhook. That event comes from website forms, stores and messaging channels.
  • The API never overwrites a contact. To change a contact, use the app.
  • Notes are not deduplicated. Sending the same note twice adds it twice.
  • Merging contacts in the app makes the merged one return 404. Look the person up again with GET /contacts?q= to find the contact that was kept.

Last updated 2026-11-08