Skip to content

Search contacts

GET
/contacts/search
curl --request GET \
--url 'https://contacts.work.optidata.cloud/api/contacts/search?query=ana&type=person&page=1&page_size=15' \
--header 'Authorization: Bearer <token>'

Finds the caller’s contacts matching query and returns them ranked by how well they matched, one page at a time.

The term is compared, case- and accent-insensitively, against:

  • each contact’s e-mail addresses and phone numbers — an exact value ranks highest, then a value that starts with the term, then a value that contains it. A phone number matches however it is formatted;
  • the contact’s name;
  • the name of the organization a person works for, so searching a company name also finds the people who work there.

Close misspellings still match, ranked below real matches. Each result carries its relevance in score (higher is better); ties are broken by name.

Results are paginated without a total count: keep requesting the next page while next_page_url is not null. The page links omit the other query parameters, so build the next request yourself — same query, type and page_size, with page incremented.

query
required
string
>= 1 characters <= 255 characters

The search term.

type

What a contact represents. person and organization are the everyday kinds; the others identify mail-platform entries kept in the address book (distribution_list, group, resource) and secondary addresses that point to another contact (alias).

string
Allowed values: person organization distribution_list group resource alias

Only return contacts of this type.

page
integer
default: 1 >= 1

Page number, starting at 1.

page_size
integer
default: 15 >= 1 <= 100

Number of contacts per page.

One page of matching contacts, best match first.

Media typeapplication/json

One page of search results. There is no total count.

object
current_page
required
integer
current_page_url
string format: uri
data
required
Array

A contact returned by search, with its relevance.

object
id
required

Contact id.

integer
type
required

What a contact represents. person and organization are the everyday kinds; the others identify mail-platform entries kept in the address book (distribution_list, group, resource) and secondary addresses that point to another contact (alias).

string
Allowed values: person organization distribution_list group resource alias
name
required

Display name — a person’s full name or an organization’s name.

string | null
avatar_url

URL of the contact’s picture, when one was set.

string | null
job_title

A person’s job title. Always null for an organization.

string | null
birthdate

Birth date, at midnight UTC.

string | null format: date-time
website
string | null
notes

Free-form notes.

string | null
custom_fields

Additional user-defined fields, as name/value pairs.

object | null
address

Postal address, as a single line of text.

string | null
identification_number

A tax or company registration number.

string | null
scope
required

Who a contact belongs to. user is a personal address-book entry; company is an entry shared across the company.

string
Allowed values: user company
cuid

Identifier of the company the contact was created in.

string
created_by_id
required

Numeric id of the user who owns the contact — always the caller.

integer
created_by_uuid
required

UUID of the user who owns the contact — always the caller.

string format: uuid
zimbra_id

Id of the matching entry in the mail platform’s address book, when the contact was imported from it.

string | null
app_id

Id of the Optiwork module that added the contact automatically (for example, Calendar when you invite someone new), or null when it was added by hand or imported.

integer | null
app_action

What, in that module, caused the contact to be added.

string | null
canonical_contact_id

For an alias, the id of the contact it points to.

integer | null
created_at
required
string format: date-time
updated_at
required
string format: date-time
deleted_at

Always null — contacts in the trash are not returned.

string | null format: date-time
emails
required

E-mail addresses, the primary one first.

Array<object>

One e-mail address or phone number of a contact.

object
id
required
integer
type
required
string
Allowed values: email phone
value
required

The address or number, as entered.

string
value_normalized

The value in canonical form — a lower-cased e-mail address, or an E.164 phone number. null when a phone number could not be parsed.

string | null
is_primary
required

Whether this is the contact’s preferred address or number of its kind.

boolean
scope

Who a contact belongs to. user is a personal address-book entry; company is an entry shared across the company.

string
Allowed values: user company
owner_uuid

UUID of the owner for a personal (user) contact; null for a company-wide one.

string | null format: uuid
contactable_id

Id of the contact this method belongs to.

integer
contactable_type

Internal type tag of the owning record. Not meaningful to API clients.

string
value_fts

Internal search index of the value. Not meaningful to API clients.

string | null
created_at
string format: date-time
updated_at
string format: date-time
phones
required

Phone numbers, the primary one first.

Array<object>

One e-mail address or phone number of a contact.

object
id
required
integer
type
required
string
Allowed values: email phone
value
required

The address or number, as entered.

string
value_normalized

The value in canonical form — a lower-cased e-mail address, or an E.164 phone number. null when a phone number could not be parsed.

string | null
is_primary
required

Whether this is the contact’s preferred address or number of its kind.

boolean
scope

Who a contact belongs to. user is a personal address-book entry; company is an entry shared across the company.

string
Allowed values: user company
owner_uuid

UUID of the owner for a personal (user) contact; null for a company-wide one.

string | null format: uuid
contactable_id

Id of the contact this method belongs to.

integer
contactable_type

Internal type tag of the owning record. Not meaningful to API clients.

string
value_fts

Internal search index of the value. Not meaningful to API clients.

string | null
created_at
string format: date-time
updated_at
string format: date-time
companies
required

The organizations a person works for. Always empty for an organization.

Array

An employer of a person contact.

object
id
required

Contact id.

integer
type
required

What a contact represents. person and organization are the everyday kinds; the others identify mail-platform entries kept in the address book (distribution_list, group, resource) and secondary addresses that point to another contact (alias).

string
Allowed values: person organization distribution_list group resource alias
name
required

Display name — a person’s full name or an organization’s name.

string | null
avatar_url

URL of the contact’s picture, when one was set.

string | null
job_title

A person’s job title. Always null for an organization.

string | null
birthdate

Birth date, at midnight UTC.

string | null format: date-time
website
string | null
notes

Free-form notes.

string | null
custom_fields

Additional user-defined fields, as name/value pairs.

object | null
address

Postal address, as a single line of text.

string | null
identification_number

A tax or company registration number.

string | null
scope
required

Who a contact belongs to. user is a personal address-book entry; company is an entry shared across the company.

string
Allowed values: user company
cuid

Identifier of the company the contact was created in.

string
created_by_id
required

Numeric id of the user who owns the contact — always the caller.

integer
created_by_uuid
required

UUID of the user who owns the contact — always the caller.

string format: uuid
zimbra_id

Id of the matching entry in the mail platform’s address book, when the contact was imported from it.

string | null
app_id

Id of the Optiwork module that added the contact automatically (for example, Calendar when you invite someone new), or null when it was added by hand or imported.

integer | null
app_action

What, in that module, caused the contact to be added.

string | null
canonical_contact_id

For an alias, the id of the contact it points to.

integer | null
created_at
required
string format: date-time
updated_at
required
string format: date-time
deleted_at

Always null — contacts in the trash are not returned.

string | null format: date-time
pivot

The link between the person and this organization.

object
contact_id

Id of the person.

integer
related_contact_id

Id of the organization.

integer
relation_type
string
score
required

How well the contact matched the term, from 20 (a close misspelling) to 100 (an exact e-mail address or phone number). Higher is better.

integer
first_page_url
string format: uri
from

Position of the first result on this page, or null when the page is empty.

integer | null
next_page_url
required

Set while more results are available; null on the last page. Carries only page — repeat your other parameters.

string | null format: uri
path
string format: uri
per_page
required

The page size in effect. Echoed as a string when you passed page_size.

integer | string
prev_page_url
string | null format: uri
to

Position of the last result on this page, or null when the page is empty.

integer | null
Examples

First page with more results available

{
"current_page": 1,
"current_page_url": "https://contacts.work.optidata.cloud/api/contacts/search?page=1",
"data": [
{
"id": 33901,
"type": "person",
"name": "Ana Souza",
"avatar_url": null,
"job_title": "Account Manager",
"birthdate": null,
"website": null,
"notes": null,
"cuid": "7f3c2a10-5b8e-4d21-9c6a-0e4f1b2d3c4a",
"created_by_id": 5,
"created_by_uuid": "2d9e8f70-1a3b-4c5d-8e9f-a0b1c2d3e4f5",
"created_at": "2026-10-15T20:31:01.000000Z",
"updated_at": "2026-10-15T20:31:01.000000Z",
"deleted_at": null,
"custom_fields": null,
"address": null,
"identification_number": null,
"zimbra_id": null,
"app_id": null,
"canonical_contact_id": null,
"scope": "user",
"app_action": null,
"score": 80,
"emails": [
{
"id": 1627,
"contactable_type": "App\\Models\\Contacts\\Contact",
"contactable_id": 33901,
"type": "email",
"value": "ana.souza@example.com",
"is_primary": true,
"created_at": "2026-10-15T20:31:01.000000Z",
"updated_at": "2026-10-15T20:31:01.000000Z",
"value_normalized": "ana.souza@example.com",
"scope": "user",
"owner_uuid": "2d9e8f70-1a3b-4c5d-8e9f-a0b1c2d3e4f5",
"value_fts": "'ana.souza@example.com':1"
}
],
"phones": [],
"companies": []
}
],
"first_page_url": "https://contacts.work.optidata.cloud/api/contacts/search?page=1",
"from": 1,
"next_page_url": "https://contacts.work.optidata.cloud/api/contacts/search?page=2",
"path": "https://contacts.work.optidata.cloud/api/contacts/search",
"per_page": 1,
"prev_page_url": null,
"to": 1
}

No authentication key was sent.

Media typeapplication/json

Authentication failures use an error key rather than message.

object
error
required
string
Examples
Examplemissing

No bearer token sent

{
"error": "JWT passport exception: Missing bearer token in request"
}

The authentication key is expired or not recognised. Get a fresh one and retry.

Media typeapplication/json

Authentication failures use an error key rather than message.

object
error
required
string
Examples
Exampleexpired
{
"error": "JWT passport expired: Passport expired"
}

The query string failed validation.

Media typeapplication/json
object
message
required

The first validation message.

string
errors
required

Validation messages keyed by field name.

object
key
additional properties
Array<string>
Examples

Search term missing

{
"message": "The search query field is required.",
"errors": {
"query": [
"The search query field is required."
]
}
}