A valid request URL is required to generate request examples{
"status": "success",
"data": {
"contacts": [
{
"id": 12345678,
"group_id": 1,
"CreatedAt": "2022-10-13T15:50:34.643724Z",
"UpdatedAt": "2022-10-13T15:55:12.853724Z",
"lastchange": "2022-10-13T15:50:24.163Z",
"firstname": "John",
"surname": "Doe",
"married_name": "Smith",
"gender": "F",
"birthdate": "1955-07-06T00:00:00Z",
"age_category": 0,
"birthdept": "string",
"birthcity": "string",
"birthcountry": "string",
"mail": "user@example.com",
"phone": "string",
"mobile": "string",
"address": {
"housenumber": 1,
"street": "rue de la paix",
"postalcode": 75000,
"citycode": 75101,
"city": "Paris",
"state": "Ile-de-France",
"country": "France",
"addition": "Résidence de la paix",
"infos": "Porte de gauche",
"building": "Bâtiment A",
"floor": 2,
"door": "A",
"pollingstation": "BV-06",
"id": 1001,
"score": 0.965753,
"latitude": 48,
"longitude": 2,
"location": "48.0000002.000000",
"invalid": null
},
"tags": [
{
"name": "tag1",
"color": "red"
}
],
"actions_ids": [
1,
2
],
"formdatas": [
{
"form_id": 1001,
"form_ref_id": 2001,
"data": "Oui",
"id": 3001,
"created_at": "2022-10-13T15:50:24.163Z",
"updated_at": "2022-10-13T15:50:24.163Z",
"date": "2022-10-13T15:50:24.163Z",
"group_id": 1,
"contact_id": 12345678
}
],
"customfields": [
{
"form_id": 1001,
"form_ref_id": 2001,
"data": "Oui",
"id": 3001,
"created_at": "2022-10-13T15:50:24.163Z",
"updated_at": "2022-10-13T15:50:24.163Z",
"date": "2022-10-13T15:50:24.163Z",
"group_id": 1,
"contact_id": 12345678
}
],
"notes": {
"id": 1234,
"created_at": "2024-09-12T08:06:47.957Z",
"updated_at": "2024-09-12T08:06:47.957Z",
"data": "John Doe asked for information about the next event.",
"contact_id": 12345678,
"group_id": 1,
"user_id": 456,
"pinned": true
},
"interactions": [
{
"id": 0,
"created_at": "2024-09-12T08:06:47.957Z",
"updated_at": "2024-09-12T08:06:47.957Z",
"type": "letter",
"sub_type": "incoming",
"title": "Send a request for information",
"comments": "John Doe asked for information about the next event.",
"contact_id": 12345678,
"group_id": 1,
"user_id": 456,
"only_super_admin": false,
"files": [
{
"id": 5001,
"created": "2024-09-12T08:06:47.957Z",
"owner_id": 456,
"group_id": 1,
"subject": "The letter sent by John Doe",
"url": "string",
"folder": "string",
"mime": "image/jpeg",
"name": "string",
"is_interaction": true
}
]
}
]
}
]
}
}Search contacts using a flexible query language. Filter by any combination of contact info, address, tags, financial activity (transactions, donations, memberships), email campaign engagement, and custom fields.
Each condition uses an ope (operator). Here is what they mean in plain language:
| What you want to say | ope value |
|---|---|
| equals | eql |
| does not equal | not_eql |
| has a value / is filled in | ext |
| has no value / is empty | not_ext |
| is before / at most | lte |
| is after / at least | gte |
| is between two values | range — use with from and to |
| contains the text | contains |
| does not contain the text | not_contains |
| starts with | start_with |
| does not start with | not_start_with |
| equals (case-sensitive, exact match) | eql:strictdata |
| matches any of a list | any_of |
| matches none of a list | none_of |
| matches all of a list | all_of |
Dates accept relative values:
"now","now-30d","now-1y", etc.
A query is a tree of groups. Each group is either:
$all — ALL conditions inside must match (AND logic)$at_least_one — AT LEAST ONE condition must match (OR logic)Groups can be nested one level deep. Think of it as:
query ($all = the outer AND)
├── group A ($all — all of these must match)
│ ├── city equals "Paris"
│ └── mobile has a value
└── group B ($at_least_one — at least one must match)
├── tag equals "volunteer"
└── tag equals "donor"
Plain English: “City is Paris AND has a mobile number AND (tagged volunteer OR tagged donor)”
Translated to JSON:
{
"data": {
"advanced_search": {
"per_page": 100,
"query": {
"$all": [
{
"$all": [
{ "$condition": { "attr": "address.city", "ope": "eql", "value": "Paris" } },
{ "$condition": { "attr": "mobile", "ope": "ext" } }
]
},
{
"$at_least_one": [
{ "$condition": { "attr": "tags.name", "ope": "eql", "value": "volunteer" } },
{ "$condition": { "attr": "tags.name", "ope": "eql", "value": "donor" } }
]
}
]
}
}
}
}
Single condition? You still need the two-level nesting. The minimum shape is always:
{ "$all": [ { "$all": [ { "$condition": { ... } } ] } ] }
Contacts whose membership started on or before today and ends on or after today.
{
"data": {
"advanced_search": {
"per_page": 100,
"query": {
"$all": [{
"$all": [
{ "$condition": { "attr": "memberships.start_date", "ope": "lte", "value": "now" } },
{ "$condition": { "attr": "memberships.end_date", "ope": "gte", "value": "now" } }
]
}]
}
}
}
}
Contacts whose cumulative donation amount is at least €100. Amount values are always passed as strings in euros.
{
"data": {
"advanced_search": {
"per_page": 100,
"query": {
"$all": [{
"$all": [
{ "$condition": { "attr": "donations.sum_amount", "ope": "gte", "value": "100" } }
]
}]
}
}
}
}
Has a delivered email for campaign 42, but no open timestamp.
{
"data": {
"advanced_search": {
"per_page": 100,
"query": {
"$all": [{
"$all": [
{ "$condition": { "attr": "emails.campaign_id", "ope": "eql", "value": "42" } },
{ "$condition": { "attr": "emails.delivered_at", "ope": "ext" } },
{ "$condition": { "attr": "emails.opened_at", "ope": "not_ext" } }
]
}]
}
}
}
}
Combining two nested field groups — each is an independent AND.
{
"data": {
"advanced_search": {
"per_page": 100,
"query": {
"$all": [
{
"$all": [
{ "$condition": { "attr": "memberships.period", "ope": "eql", "value": "2024" } }
]
},
{
"$all": [
{ "$condition": { "attr": "donations.count_amount", "ope": "gte", "value": "1" } }
]
}
]
}
}
}
}
An OR group for cities combined with an AND group for the mobile requirement.
{
"data": {
"advanced_search": {
"per_page": 100,
"query": {
"$all": [
{
"$at_least_one": [
{ "$condition": { "attr": "address.city", "ope": "eql", "value": "Paris" } },
{ "$condition": { "attr": "address.city", "ope": "eql", "value": "Lyon" } }
]
},
{
"$all": [
{ "$condition": { "attr": "mobile", "ope": "ext" } }
]
}
]
}
}
}
}
Use GET /forms/{type} to find your form_id, then GET /forms/{formId} for form_ref_ids.
{
"data": {
"advanced_search": {
"per_page": 100,
"query": {
"$all": [{
"$all": [{
"$condition": {
"attr": "form",
"form_id": 4530,
"form_ref_ids": [7486],
"ope": "eql",
"value": "consent_email"
}
}]
}]
}
}
}
}
| Attribute | Meaning | Operators |
|---|---|---|
firstname | First name | eql, not_eql, ext, not_ext, start_with, not_start_with |
surname | Last name | eql, not_eql, ext, not_ext, start_with, not_start_with |
married_name | Married name | eql, not_eql, ext, not_ext, start_with, not_start_with |
gender | Gender (M, F, O) | eql, not_eql, ext, not_ext |
birthdate | Date of birth | eql, ext, not_ext, range, lte, gte, period |
age_cat | Age category (0–6) | eql, not_eql, ext, not_ext |
birthcity | City of birth | eql, not_eql, ext, not_ext |
birthcountry | Country of birth | eql, not_eql, ext, not_ext |
nationality | Nationality | eql, not_eql, ext, not_ext |
mail | Email address | eql:strictdata, not_eql:strictdata, ext, not_ext, start_with, not_start_with |
phone | Landline | eql, not_eql, ext, not_ext, start_with, not_start_with |
mobile | Mobile number | eql, not_eql, ext, not_ext, contains, start_with, not_start_with |
tags.name | Tag name | eql, not_eql, any_of, none_of, all_of, ext, not_ext |
black_list | Blocked from all communication | eql, not_eql |
lastchange | Last modification date | eql, ext, not_ext, range, lte, gte |
user_id | ID of last user who edited the contact | eql, not_eql, ext, not_ext |
user_contact_id | ID of the linked Qomon user | ext, not_ext |
action_ids | IDs of linked actions | eql, not_eql |
| Attribute | Meaning | Operators |
|---|---|---|
address.city | City | eql, not_eql, ext, not_ext, start_with, not_start_with |
address.postalcode | Postal code | eql, not_eql, ext, not_ext, start_with, not_start_with |
address.country | Country | eql, not_eql, ext, not_ext |
address.street | Street name | eql, not_eql, ext, not_ext, start_with, not_start_with |
address.housenumber | House number | eql, not_eql, ext, not_ext |
address.building | Building | eql, not_eql, ext, not_ext |
address.floor | Floor | eql, not_eql, ext, not_ext |
address.door | Door | eql, not_eql, ext, not_ext |
address.addition | Address complement | eql, not_eql, ext, not_ext |
address.pollingstation | Polling station | eql, not_eql, any_of, none_of, ext, not_ext |
address.invalid | Address flagged as invalid | eql, not_eql, ext, not_ext, start_with, not_start_with |
These fields match contacts who have at least one matching record.
transactions.amount gte "50"returns contacts with at least one transaction ≥ €50, not contacts whose total is ≥ €50 (usesum_amountfor that).Amount fields (
*.amount,*.sum_amount) are in euros — always pass as strings:"value": "50"not"value": 50.sum_amountis the total across all records for the contact;count_amountis the number of records.
Transactions (transactions.*)
| Attribute | Meaning | Operators |
|---|---|---|
transactions.created_at | Record creation date | lte, gte, range |
transactions.date | Transaction execution date | eql, not_eql, lte, gte, range |
transactions.amount | Amount of one transaction (€) | eql, not_eql, lte, gte, range |
transactions.sum_amount | Total amount across all transactions (€) | eql, not_eql, lte, gte, range |
transactions.count_amount | Number of transactions | eql, not_eql, lte, gte, range |
transactions.code_campaign | Campaign code | ext, not_ext, eql, not_eql, contains, not_contains, start_with, not_start_with |
transactions.payment_method_kind | Payment method | eql, not_eql |
transactions.status_id | Transaction status ID | eql, not_eql |
Donations (donations.*)
| Attribute | Meaning | Operators |
|---|---|---|
donations.created_at | Record creation date | eql, not_eql, lte, gte, range |
donations.transaction_date | Donation operation date | eql, not_eql, lte, gte, range |
donations.amount | Amount of one donation (€) | eql, not_eql, lte, gte, range |
donations.sum_amount | Total donated (€) | eql, not_eql, lte, gte, range |
donations.count_amount | Number of donations | eql, not_eql, lte, gte, range |
donations.donation_price_id | Donation type/tier ID | eql, not_eql |
Memberships (memberships.*)
| Attribute | Meaning | Operators |
|---|---|---|
memberships.created_at | Record creation date | eql, not_eql, lte, gte, range |
memberships.start_date | Membership start date | eql, not_eql, lte, gte, range |
memberships.end_date | Membership end date | eql, not_eql, lte, gte, range |
memberships.transaction_date | Membership operation date | eql, not_eql, lte, gte, range |
memberships.period | Active year — e.g. "2024" means active that calendar year | eql, not_eql, lte, gte, range |
memberships.multiple_in_period | Had more than one membership in a given year | eql (value = year string e.g. "2024") |
memberships.membership_price_id | Membership type/tier ID | eql, not_eql |
These match contacts who have at least one email record where that field is set. A contact with no email history at all will not match
extornot_ext.
| Attribute | Meaning | Operators |
|---|---|---|
emails.created_at | Email record date | ext, not_ext, lte, gte, range |
emails.type | Email type | ext, not_ext, eql, not_eql |
emails.sender | Sender address | ext, not_ext, eql, not_eql |
emails.subject | Email subject line | ext, not_ext, contains, not_contains, start_with, not_start_with |
emails.user_id | ID of Qomon user who sent the campaign | ext, not_ext, eql, not_eql |
emails.campaign_id | Campaign ID | ext, not_ext, eql, not_eql |
emails.campaign_name | Campaign name | ext, not_ext, contains, not_contains, start_with, not_start_with |
emails.campaign_goal | Campaign goal | ext, not_ext, eql, not_eql |
emails.campaign_is_successful | Campaign marked successful | ext, not_ext, eql, not_eql |
emails.campaign_performance_rating | Campaign performance score (0–100) | ext, not_ext, lte, gte, range |
emails.template_id | Template ID | ext, not_ext, eql, not_eql |
emails.template_name | Template name | ext, not_ext, contains, not_contains, start_with, not_start_with |
emails.delivered_at | Email delivered date | ext, not_ext, lte, gte, range |
emails.opened_at | Email opened date | ext, not_ext, lte, gte, range |
emails.clicked_at | Email clicked date | ext, not_ext, lte, gte, range |
emails.bounced_at | Email bounced date | ext, not_ext, lte, gte, range |
emails.unsubscribed_at | Unsubscribed date | ext, not_ext, lte, gte, range |
emails.blacklisted_at | Blacklisted date | ext, not_ext, lte, gte, range |
emails.abuse_report_at | Abuse report date | ext, not_ext, lte, gte, range |
emails.clicked_urls | A URL that was clicked | ext, not_ext, eql, not_eql, contains, start_with |
sanctions.validity is a virtual computed field — it does not store a date, it tells you whether a sanction is currently active:
"ongoing" — sanction has started and has not yet ended"ended" — sanction end date is in the past| Attribute | Meaning | Operators |
|---|---|---|
sanctions.created_at | Sanction creation date | eql, not_eql, lte, gte, range |
sanctions.start_date | Sanction start date | eql, not_eql, lte, gte, range |
sanctions.end_date | Sanction end date | eql, not_eql, ext, not_ext, lte, gte, range |
sanctions.status | Sanction status | eql, not_eql, contains, not_contains |
sanctions.validity | "ongoing" or "ended" | eql |
These two attributes use a different condition shape — you must also provide:
form_id — the ID of the form (find it via GET /forms/{type})form_ref_ids — array of answer option IDs to match (find them via GET /forms/{formId})| Attribute | What it searches | Operators |
|---|---|---|
custom_fields | Custom fields attached to contacts | ext, not_ext, eql, not_eql, contains, not_contains, lte, gte, range |
form | Survey, consent, level of support, presence, or task form answers | ext, not_ext, eql, not_eql, contains, not_contains, lte, gte, range |
ext/not_extonly check whether the contact has filled in the givenform_id—form_ref_idsis ignored.eqlwithout avaluechecks that all listedform_ref_idsare present on the contact.eqlwith avaluechecks that they are present AND thatvaluematches the stored answer.
| Parameter | Where | Description |
|---|---|---|
per_page | advanced_search | Contacts per page — required, 1–1000 |
page | advanced_search | Page number (default: 0) |
sort_attr | advanced_search | Sort by: surname, firstname, birthdate, gender, lastchange, mail, married_name, city |
sort_asc | advanced_search | true = ascending order (default: false) |
include_interactions | advanced_search | true = include each contact’s interaction history in the response |
A valid request URL is required to generate request examples{
"status": "success",
"data": {
"contacts": [
{
"id": 12345678,
"group_id": 1,
"CreatedAt": "2022-10-13T15:50:34.643724Z",
"UpdatedAt": "2022-10-13T15:55:12.853724Z",
"lastchange": "2022-10-13T15:50:24.163Z",
"firstname": "John",
"surname": "Doe",
"married_name": "Smith",
"gender": "F",
"birthdate": "1955-07-06T00:00:00Z",
"age_category": 0,
"birthdept": "string",
"birthcity": "string",
"birthcountry": "string",
"mail": "user@example.com",
"phone": "string",
"mobile": "string",
"address": {
"housenumber": 1,
"street": "rue de la paix",
"postalcode": 75000,
"citycode": 75101,
"city": "Paris",
"state": "Ile-de-France",
"country": "France",
"addition": "Résidence de la paix",
"infos": "Porte de gauche",
"building": "Bâtiment A",
"floor": 2,
"door": "A",
"pollingstation": "BV-06",
"id": 1001,
"score": 0.965753,
"latitude": 48,
"longitude": 2,
"location": "48.0000002.000000",
"invalid": null
},
"tags": [
{
"name": "tag1",
"color": "red"
}
],
"actions_ids": [
1,
2
],
"formdatas": [
{
"form_id": 1001,
"form_ref_id": 2001,
"data": "Oui",
"id": 3001,
"created_at": "2022-10-13T15:50:24.163Z",
"updated_at": "2022-10-13T15:50:24.163Z",
"date": "2022-10-13T15:50:24.163Z",
"group_id": 1,
"contact_id": 12345678
}
],
"customfields": [
{
"form_id": 1001,
"form_ref_id": 2001,
"data": "Oui",
"id": 3001,
"created_at": "2022-10-13T15:50:24.163Z",
"updated_at": "2022-10-13T15:50:24.163Z",
"date": "2022-10-13T15:50:24.163Z",
"group_id": 1,
"contact_id": 12345678
}
],
"notes": {
"id": 1234,
"created_at": "2024-09-12T08:06:47.957Z",
"updated_at": "2024-09-12T08:06:47.957Z",
"data": "John Doe asked for information about the next event.",
"contact_id": 12345678,
"group_id": 1,
"user_id": 456,
"pinned": true
},
"interactions": [
{
"id": 0,
"created_at": "2024-09-12T08:06:47.957Z",
"updated_at": "2024-09-12T08:06:47.957Z",
"type": "letter",
"sub_type": "incoming",
"title": "Send a request for information",
"comments": "John Doe asked for information about the next event.",
"contact_id": 12345678,
"group_id": 1,
"user_id": 456,
"only_super_admin": false,
"files": [
{
"id": 5001,
"created": "2024-09-12T08:06:47.957Z",
"owner_id": 456,
"group_id": 1,
"subject": "The letter sent by John Doe",
"url": "string",
"folder": "string",
"mime": "image/jpeg",
"name": "string",
"is_interaction": true
}
]
}
]
}
]
}
}Documentation Index
Fetch the complete documentation index at: https://api.qomon.com/llms.txt
Use this file to discover all available pages before exploring further.
Was this page helpful?