API Reference - Getting Started

Link: https://support.brilliantdirectories.com/support/solutions/articles/12000108046

← Back to API Reference

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:

Copy
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.

API keys are shown only once at the time of creation. Store them securely — there is no way to retrieve a key after closing the creation dialog.

Verify API Key

GET /api/v2/token/verify

Check whether an API key is valid and retrieve the associated website URL and key name.

Example Request

Copy
curl -X GET "https://www.yourdomain.com/api/v2/token/verify" \
  -H "X-Api-Key: your-api-key-here"

Example Response

Copy
{
  "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

Copy
{
  "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

Copy
{
  "status": "error",
  "message": "Description of the error"
}

HTTP Status Codes

StatusMeaning
200Success — request processed normally
400Bad Request — missing or invalid parameters (e.g. required field not provided)
401Unauthorized — API key missing, invalid, or disabled
403Forbidden — API key does not have permission to access this endpoint (API Permissions feature)
405Method Not Allowed — wrong HTTP method used for this endpoint
429Too 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

ParameterTypeDefaultDescription
pagestring(none)Cursor token from a previous response's next_page or prev_page field. Omit on the first request to start at page 1.
limitinteger25Number of records per page (max 100)

Pagination Response Fields

FieldTypeDescription
totalintegerTotal number of records matching the query
current_pageintegerCurrent page number
total_pagesintegerTotal number of pages
next_pagestringCursor token for the next page. Pass as the page parameter to retrieve the next page. Empty string on the last page.
prev_pagestringCursor token for the previous page. Pass as the page parameter to go back. Omitted on the first page.
messagearrayArray of resource objects for the current page

Example Paginated Response

Copy
{
  "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:

Copy
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:

Copy
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

ParameterTypeDescription
propertystring or arrayField name to filter on. Pass multiple filters as property[]
property_valuestring or arrayValue 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_logicstring or arraySQL comparison operator. Defaults to =. See the operator reference below. Use property_logic[] for multiple filters
property_operatorstring or arrayClause 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:

OperatorAliasesDescription
=eq, equalsEqual (default)
!=<>, ne, neq, not_equalsNot equal
>gtGreater than
>=gteGreater than or equal
<ltLess than
<=lteLess than or equal
likeSQL LIKE; requires % or _ wildcard in value
not likenot_likeSQL NOT LIKE; requires wildcard in value
inSQL IN; property_value must be a comma-separated list (EG 1,3,4,5)
not innot_inSQL NOT IN; comma-separated value
is nullis_nullField is SQL NULL; property_value not required
is not nullis_not_nullField is NOT NULL; property_value not required
is setis_setField is present AND not empty string (UX-populated check, distinct from SQL-literal is null)
is not setis_not_setField is NULL OR empty string
betweenSQL BETWEEN; value must be exactly two comma-separated values (low,high)
starts withstarts_withString starts with the value (server-side LIKE 'value%'; bypasses URL encoding issues with %). CSV expands to OR across alternatives
not starts withnot_starts_withString does not start with the value; CSV uses AND-of-NOT
ends withends_withString ends with the value; CSV expands to OR
not ends withnot_ends_withString does not end with the value
containsString contains the value (server-side LIKE '%value%'); CSV expands to OR
not containsnot_containsString does not contain the value
since dayssince_daysDate column is within the last N days (server timezone). Numeric value 1 to 3650
until daysuntil_daysDate column is older than N days
since datesince_dateDate column is on or after a given date. Value format: YYYY-MM-DD
until dateuntil_dateDate column is on or before a given date
between datesbetween_datesDate column falls within a date range. Value: two YYYY-MM-DD dates, comma-separated
year eqyear_eqDate column's year matches; CSV-friendly (EG 2024,2025)
not year eqnot_year_eqDate column's year does not match
month eqmonth_eqDate column's month matches (1 to 12); CSV-friendly
not month eqnot_month_eqDate column's month does not match
day eqday_eqDate column's day-of-month matches (1 to 31); CSV-friendly
not day eqnot_day_eqDate column's day-of-month does not match
length eqlength_eqString column's length equals N (integer 0 to 65535)
length ltlength_ltString column's length is less than N
length gtlength_gtString column's length is greater than N
length betweenlength_betweenString column's length is within [low,high]. Value: two integers, comma-separated
URL parameter caveat (ModSecurity): Some BD sites are protected by ModSecurity rules that strip raw <, <=, 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.
Unrecognized operators return an error. If 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 =.
Performance note: Calendar-bucket operators (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

ParameterTypeDescription
order_columnstringColumn name to sort by. Pass a comma-separated list to sort by multiple columns (EG last_name,first_name)
order_typestringASC (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
seedintegerOptional. When order_type=RAND, the seed makes the random order deterministic so the same seed reproduces the same ordering. Omit for true random
Performance note: 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

Copy
# 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

Copy
# 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):

Copy
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

Copy
# 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)

Copy
# 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

Copy
# 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)

Copy
# 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.

Copy
# 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

Copy
# 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

Copy
# 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

GET /api/v2/{model}/count

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

Copy
# 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

Copy
{
  "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}:

Copy
curl -X GET "https://www.yourdomain.com/api/v2/user/get?group_by=active" \
  -H "X-Api-Key: your-api-key-here"
Copy
{
  "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:

Copy
curl -X GET "https://www.yourdomain.com/api/v2/user/get?group_by=active,profession_id" \
  -H "X-Api-Key: your-api-key-here"
Copy
{
  "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.

ParameterTypeDescription
__clear_fieldsstringComma-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

Copy
# 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.

Copy
# 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"
Backwards compatibility: Requests that don't use __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 columns: Clearing a database column that has a 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.

GET /api/v2/{model}/fields

Example Request

Copy
curl -X GET "https://www.yourdomain.com/api/v2/user/fields" \
  -H "X-Api-Key: your-api-key-here"

Example Response

Copy
[
  { "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:

Copy
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"