API Reference - Getting Started
Link: https://support.brilliantdirectories.com/support/solutions/articles/12000108046
Brilliant Directories API Reference
Last updated May 2026
Introduction
The Brilliant Directories API gives you programmatic access to your directory website's data. You can create, read, update, and delete members, leads, posts, reviews, widgets, and more using standard HTTP requests.
The API follows REST conventions. All requests and responses use JSON. Dates are formatted as YYYYMMDDHHmmss (e.g. 20240115143000) unless noted otherwise.
Base URL
Replace yourdomain.com with your actual Brilliant Directories website domain in every request:
https://www.yourdomain.com/api/v2/
Request Format
Send POST and PUT request bodies as application/x-www-form-urlencoded (standard HTML form encoding). DELETE request bodies follow the same format. GET parameters are sent as query string parameters.
Authentication
Every request must include a valid API key in the X-Api-Key HTTP header. API keys are created and managed in your website's Admin Panel under Developer Hub → Generate API Key.
Verify API Key
Check whether an API key is valid and retrieve the associated website URL and key name.
Example Request
curl -X GET "https://www.yourdomain.com/api/v2/token/verify" \ -H "X-Api-Key: your-api-key-here"
Example Response
{
"status": "success",
"message": {
"website": "https://www.yourdomain.com",
"key": "My API Key Name"
}
}Rate Limiting
The API enforces rate limiting to prevent abuse. The default limit is 100 requests per 60 seconds. This limit can be adjusted in your website's Admin Panel settings (maximum 1,000 requests per minute).
When you exceed the rate limit, the API returns a 429 Too Many Requests response. Wait for the time window to reset before retrying.
Rate Limit Response
{
"status": "error",
"message": "Too many API requests per minute"
}Errors
All error responses follow the same structure: a status field set to "error" and a message field describing the problem.
Error Response Format
{
"status": "error",
"message": "Description of the error"
}HTTP Status Codes
| Status | Meaning |
|---|---|
200 | Success — request processed normally |
400 | Bad Request — missing or invalid parameters (e.g. required field not provided) |
401 | Unauthorized — API key missing, invalid, or disabled |
403 | Forbidden — API key does not have permission to access this endpoint (API Permissions feature) |
405 | Method Not Allowed — wrong HTTP method used for this endpoint |
429 | Too Many Requests — rate limit exceeded |
Pagination
All list endpoints return paginated results. By default, 25 records are returned per page. The maximum is 100 per page.
Pagination Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | string | (none) | Cursor token from a previous response's next_page or prev_page field. Omit on the first request to start at page 1. |
limit | integer | 25 | Number of records per page (max 100) |
Pagination Response Fields
| Field | Type | Description |
|---|---|---|
total | integer | Total number of records matching the query |
current_page | integer | Current page number |
total_pages | integer | Total number of pages |
next_page | string | Cursor token for the next page. Pass as the page parameter to retrieve the next page. Empty string on the last page. |
prev_page | string | Cursor token for the previous page. Pass as the page parameter to go back. Omitted on the first page. |
message | array | Array of resource objects for the current page |
Example Paginated Response
{
"status": "success",
"total": 156,
"current_page": 2,
"total_pages": 7,
"next_page": "MypfKjI1",
"prev_page": "MSpfKjI1",
"message": [ ... ]
}Pagination Flow
First request — omit the page parameter to start at page 1:
curl -X GET "https://www.yourdomain.com/api/v2/user/get?limit=25" \ -H "X-Api-Key: your-api-key-here"
Subsequent requests — pass the next_page token from the previous response:
curl -X GET "https://www.yourdomain.com/api/v2/user/get?page=MipfKjI1" \ -H "X-Api-Key: your-api-key-here"
Filtering and Sorting
All list endpoints support filtering by any field, sorting by any column, counting, and grouping using query string parameters.
Filter Parameters
| Parameter | Type | Description |
|---|---|---|
property | string or array | Field name to filter on. Pass multiple filters as property[] |
property_value | string or array | Value to match against. Use property_value[] for multiple filters. Required for most operators; not required for is null, is not null, is set, is not set |
property_logic | string or array | SQL comparison operator. Defaults to =. See the operator reference below. Use property_logic[] for multiple filters |
property_operator | string or array | Clause glue between filters: AND (default) or OR. Tag any clause with property_operator[N]=OR to add it to the OR bucket. For backwards compatibility, when property_logic is absent, property_operator falls back to carrying the comparison operator |
Filter Operator Reference
The full set of supported comparison operators for property_logic:
| Operator | Aliases | Description |
|---|---|---|
= | eq, equals | Equal (default) |
!= | <>, ne, neq, not_equals | Not equal |
> | gt | Greater than |
>= | gte | Greater than or equal |
< | lt | Less than |
<= | lte | Less than or equal |
like | — | SQL LIKE; requires % or _ wildcard in value |
not like | not_like | SQL NOT LIKE; requires wildcard in value |
in | — | SQL IN; property_value must be a comma-separated list (EG 1,3,4,5) |
not in | not_in | SQL NOT IN; comma-separated value |
is null | is_null | Field is SQL NULL; property_value not required |
is not null | is_not_null | Field is NOT NULL; property_value not required |
is set | is_set | Field is present AND not empty string (UX-populated check, distinct from SQL-literal is null) |
is not set | is_not_set | Field is NULL OR empty string |
between | — | SQL BETWEEN; value must be exactly two comma-separated values (low,high) |
starts with | starts_with | String starts with the value (server-side LIKE 'value%'; bypasses URL encoding issues with %). CSV expands to OR across alternatives |
not starts with | not_starts_with | String does not start with the value; CSV uses AND-of-NOT |
ends with | ends_with | String ends with the value; CSV expands to OR |
not ends with | not_ends_with | String does not end with the value |
contains | — | String contains the value (server-side LIKE '%value%'); CSV expands to OR |
not contains | not_contains | String does not contain the value |
since days | since_days | Date column is within the last N days (server timezone). Numeric value 1 to 3650 |
until days | until_days | Date column is older than N days |
since date | since_date | Date column is on or after a given date. Value format: YYYY-MM-DD |
until date | until_date | Date column is on or before a given date |
between dates | between_dates | Date column falls within a date range. Value: two YYYY-MM-DD dates, comma-separated |
year eq | year_eq | Date column's year matches; CSV-friendly (EG 2024,2025) |
not year eq | not_year_eq | Date column's year does not match |
month eq | month_eq | Date column's month matches (1 to 12); CSV-friendly |
not month eq | not_month_eq | Date column's month does not match |
day eq | day_eq | Date column's day-of-month matches (1 to 31); CSV-friendly |
not day eq | not_day_eq | Date column's day-of-month does not match |
length eq | length_eq | String column's length equals N (integer 0 to 65535) |
length lt | length_lt | String column's length is less than N |
length gt | length_gt | String column's length is greater than N |
length between | length_between | String column's length is within [low,high]. Value: two integers, comma-separated |
<, <=, and <> from URL query strings before PHP can read them. If your filter uses these operators, use the word-form aliases (lt, lte, ne) or pre-encode them as HTML entities (%26lt%3B, %26lt%3B%3D, %26lt%3B%26gt%3B). Operators !=, >, and >= are not affected.property_logic contains a value that is not in the operator table above (and is not a recognized alias), the request returns {"status": "error", "message": "Invalid filter parameters"} with HTTP 400. The platform no longer silently treats unknown operators as =.year eq, month eq, day eq) and length operators apply a SQL function to the column, which defeats indexes. On large tables, combine them with another indexed filter for acceptable performance.Sort Parameters
| Parameter | Type | Description |
|---|---|---|
order_column | string | Column name to sort by. Pass a comma-separated list to sort by multiple columns (EG last_name,first_name) |
order_type | string | ASC (default), DESC, or RAND for random ordering. For multi-column sort, pass a comma-separated list of directions matching order_column position (EG ASC,DESC), or a single direction to apply to all columns |
seed | integer | Optional. When order_type=RAND, the seed makes the random order deterministic so the same seed reproduces the same ordering. Omit for true random |
order_type=RAND requires a full table sort in memory and does not use indexes. Avoid on tables larger than a few thousand rows without a tight pre-filter.Filter Example — Exact Match
# Get all active users (active = 2) curl -X GET "https://www.yourdomain.com/api/v2/user/get?property=active&property_value=2" \ -H "X-Api-Key: your-api-key-here"
Filter Example — LIKE Search
# Find users whose company name contains "Tech" curl -X GET "https://www.yourdomain.com/api/v2/user/get?property=company&property_value=%25Tech%25&property_logic=like" \ -H "X-Api-Key: your-api-key-here"
Filter Example — Contains (no URL encoding needed)
Use contains for substring matching without having to URL-encode the % wildcards (which some WAFs strip):
curl -X GET "https://www.yourdomain.com/api/v2/user/get?property=email&property_value=fitness&property_logic=contains" \ -H "X-Api-Key: your-api-key-here"
Filter Example — IN List
# Get users whose subscription is one of [1, 3, 5] curl -X GET "https://www.yourdomain.com/api/v2/user/get?property=subscription_id&property_value=1,3,5&property_logic=in" \ -H "X-Api-Key: your-api-key-here"
Filter Example — Recent Records (since_days)
# Users who signed up in the last 30 days curl -X GET "https://www.yourdomain.com/api/v2/user/get?property=signup_date&property_value=30&property_logic=since_days" \ -H "X-Api-Key: your-api-key-here"
Filter Example — IS NOT NULL
# Users with a verified flag set (verified IS NOT NULL) curl -X GET "https://www.yourdomain.com/api/v2/user/get?property=verified&property_logic=is_not_null" \ -H "X-Api-Key: your-api-key-here"
Filter Example — Multiple Filters (AND, default)
# Get active users in California curl -X GET "https://www.yourdomain.com/api/v2/user/get?property[]=active&property_value[]=2&property[]=state_code&property_value[]=CA" \ -H "X-Api-Key: your-api-key-here"
Filter Example — Multiple Filters (OR)
Tag each OR-bucket clause with property_operator[N]=OR. Untagged clauses default to AND. The composer emits (AND-bucket) AND (OR-bucket) when both buckets contain clauses.
# Users in California OR Texas curl -X GET "https://www.yourdomain.com/api/v2/user/get?property[]=state_code&property_value[]=CA&property_operator[]=OR&property[]=state_code&property_value[]=TX&property_operator[]=OR" \ -H "X-Api-Key: your-api-key-here"
Sort Example — Multi-Column
# Sort by last_name ASC, then first_name DESC curl -X GET "https://www.yourdomain.com/api/v2/user/get?order_column=last_name,first_name&order_type=ASC,DESC" \ -H "X-Api-Key: your-api-key-here"
Sort Example — Random with Seed
# Random order, reproducible with seed=42 curl -X GET "https://www.yourdomain.com/api/v2/user/get?order_type=RAND&seed=42" \ -H "X-Api-Key: your-api-key-here"
Counting and Grouping
Both the /count endpoint and the group_by parameter are available on every model that exposes a /get endpoint.
Count Endpoint
Returns just the count of records matching a filter, without fetching the records themselves. Useful when you only need a total. All the filter parameters from /get work the same way here. Pagination and sort parameters (page, limit, order_column, order_type) are silently ignored.
Example Request
# How many active users are there? curl -X GET "https://www.yourdomain.com/api/v2/user/count?property=active&property_value=2" \ -H "X-Api-Key: your-api-key-here"
Example Response
{
"status": "success",
"total": 1247
}Group By
Pass group_by on the /get endpoint to aggregate records by one or more columns. The response shape depends on the number of grouping columns.
Single-Column Group By
Returns a map of {value: count}:
curl -X GET "https://www.yourdomain.com/api/v2/user/get?group_by=active" \ -H "X-Api-Key: your-api-key-here"
{
"status": "success",
"groups": {
"1": 12,
"2": 1247,
"3": 33
}
}Multi-Column Group By
Pass a comma-separated list of columns. Returns an array of {col1: v, col2: v, count: N} rows:
curl -X GET "https://www.yourdomain.com/api/v2/user/get?group_by=active,profession_id" \ -H "X-Api-Key: your-api-key-here"
{
"status": "success",
"groups": [
{ "active": "2", "profession_id": "1", "count": 412 },
{ "active": "2", "profession_id": "7", "count": 198 },
{ "active": "3", "profession_id": "1", "count": 12 }
]
}Updating Records
The generic PUT /api/v2/{model}/update endpoint takes the record's primary key plus any subset of fields to change.
Clearing Field Values
By default, empty values in update requests are silently ignored. This prevents accidental data loss when a form submits with empty fields, but it also means there is no way to clear a previously set value just by passing an empty string. To explicitly clear one or more base-column fields, pass them in the __clear_fields parameter as a comma-separated list.
| Parameter | Type | Description |
|---|---|---|
__clear_fields | string | Comma-separated list of base-column field names to clear to empty string. Whitespace around names is trimmed; duplicates are deduped. Unknown fields are silently skipped. The primary key cannot be cleared and is silently rejected |
Example — Clear two fields
# Clear phone_number and last_name on user 42 curl -X PUT "https://www.yourdomain.com/api/v2/user/update" \ -H "X-Api-Key: your-api-key-here" \ -d "user_id=42" \ -d "phone_number=" \ -d "last_name=" \ -d "__clear_fields=phone_number,last_name"
Combining clear with set
When a field appears in __clear_fields AND has a non-empty value in the body, the non-empty value wins. The field is only cleared when the body value is empty.
# last_name is cleared, but first_name is set to "Jane" curl -X PUT "https://www.yourdomain.com/api/v2/user/update" \ -H "X-Api-Key: your-api-key-here" \ -d "user_id=42" \ -d "first_name=Jane" \ -d "last_name=" \ -d "__clear_fields=first_name,last_name"
__clear_fields behave exactly as before. Empty values are still silently dropped, so callers that depend on the legacy behavior are not affected.NOT NULL constraint without a default value can fail at the database layer. Check the column type before relying on __clear_fields for non-string base columns. Strings and TEXT columns are safe; integers, datetimes, and ENUMs may reject empty string.The Fields Endpoint
Each resource exposes a /fields endpoint that returns the list of writable fields for that resource. This is useful for discovering available fields dynamically without consulting the documentation.
Example Request
curl -X GET "https://www.yourdomain.com/api/v2/user/fields" \ -H "X-Api-Key: your-api-key-here"
Example Response
[
{ "key": "first_name", "label": "first_name", "required": 0 },
{ "key": "last_name", "label": "last_name", "required": 0 },
{ "key": "email", "label": "email", "required": 0 },
...
]For post types (data_posts and users_portfolio_groups), pass a form_name parameter to retrieve the custom fields specific to that post type:
curl -X GET "https://www.yourdomain.com/api/v2/data_posts/fields?form_name=my-listings-form" \ -H "X-Api-Key: your-api-key-here"
