BROSH CRM — OAuth2 Integration & API

Base URL: app.brosh.io All endpoints use POST
OAuth2 Records CRUD Flexible Find Table-based objects
Authorization: Bearer <access_token>

Overview

BROSH CRM exposes an OAuth2 integration plus a table-based records API. Supported objects are accessed by passing :tableName in the URL.

Authentication: Obtain an access_token via OAuth2 token exchange. For authenticated endpoints, send Authorization: Bearer <access_token>.

Supported Objects

Use these values as :tableName:

Object / tableNameNotes
accountsAccount / company records
activityActivities / tasks / events / campaigns members(implementation-specific)
campaignsMarketing campaigns
contactsPeople / contacts
currencyCurrency data
objectsSystem objects / metadata (implementation-specific)
opportunitiesDeals / opportunities
opportunity_productsLine items linking products to opportunities
paymentsPayments / transactions
productsProduct catalog
projectsProjects
ticketsSupport tickets
timesheetTimesheets
custom_objectCustom objects (table schema varies)

Common Fields (Available on All Objects)

All objects in BROSH CRM include the following standard fields, which can be used in queries, filters, and sorting:

Field NameTypeDescription
idIntegerUnique identifier for the record
nameStringDisplay name or title of the record
created_byIntegerUser ID who created the record
created_dateDateTimeTimestamp when the record was created
last_modified_byIntegerUser ID who last modified the record
last_modified_dateDateTimeTimestamp of the last modification
Field Flexibility: In addition to the common fields listed above, you can use any field available in your object/table schema in the fields, filter.where, and sort parameters. Each object may have additional custom fields specific to your BROSH deployment.

OAuth2 Authentication

BROSH CRM provides three OAuth-related endpoints: token exchange, token refresh, and a "me" call to validate tokens.

Source Parameter: All OAuth2 endpoints require a :source parameter in the URL path. Valid values are:
  • make - For Make.com (formerly Integromat) integrations
  • zapier - For Zapier integrations
  • n8n - For n8n workflow automation
  • custom - For custom integrations
Example: /api/oauth2/token/zapier or /api/oauth2/findRecords/make/contacts
Header
Authorization: Bearer <access_token>
Content-Type
application/json

Exchange Authorization Code → Token

POST /api/oauth2/token/:source

Exchange an OAuth2 authorization code for an access token (and typically a refresh token).

Request (example)

{
 "code": "AUTH_CODE_FROM_BROSH_OAUTH_FLOW",
 "redirect_uri": "https://yourapp.example.com/oauth/callback",
 "client_id": "YOUR_CLIENT_ID",
 "client_secret": "YOUR_CLIENT_SECRET",
 "grant_type": "authorization_code"
}

Response (example)

{
 "access_token": "eyJhbGciOi...",
 "refresh_token": "def50200...",
 "token_type": "Bearer",
 "expires_in": 3600
}

Fields depend on your BROSH OAuth2 configuration; the example matches typical OAuth2 responses.

Refresh Token

POST /api/oauth2/refresh/:source

Use a refresh token to obtain a new access token.

Request (example)

{
 "refresh_token": "def50200...",
 "client_id": "YOUR_CLIENT_ID",
 "client_secret": "YOUR_CLIENT_SECRET",
 "grant_type": "refresh_token"
}

Response (example)

{
 "access_token": "eyJhbGciOi...NEW",
 "refresh_token": "def50200...MAYBE_NEW",
 "token_type": "Bearer",
 "expires_in": 3600
}

Test Token (Me)

POST /api/oauth2/me/:source

Validate an access token and return information about the current identity/session.

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Request

{}

Response (example)

{
 "id": "encoded_account_user_id",
 "userid": 123,
 "name": "oauthuser"
}

Available Tables

POST /api/oauth2/tables/:source

Returns all available tables for the authenticated account. By default this endpoint returns only table names.

Include fields: add ?showFields=true (or ?show_fields=true) to return table field definitions as well.

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Request (table names only)

POST /api/oauth2/tables/zapier

{}

Response (table names only)

{
 "tables": ["accounts", "contacts", "opportunity_products"],
 "total_count": 3
}

Request (with fields)

POST /api/oauth2/tables/zapier?showFields=true

{}

Response (with fields, shortened example)

 { "tables": [ { "name": "opportunity_products",
 "fields": [
 { "name": "id", "orgName": "id", "table": "opportunity_products", "format": "id" },
 { "name": "name", "orgName": "name", "table": "opportunity_products", "format": "name" } ] } ],
 "total_count": 1 }

Get Records (by IDs)

POST /api/oauth2/getRecords/:source/:tableName

Provide an array of record IDs and receive the full records.

Limit Parameter: This endpoint supports an optional limit parameter to control the maximum number of records returned. Valid range: 1 to 10,000. If not specified, a default limit of 10 is applies.

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Request Body Parameters

The request body should be an array of record IDs (numbers). You can also pass objects with an id property, or a mix of both.

Query Parameters

ParameterTypeDescription
limit number Maximum number of records to return. Valid range: 1 to 10,000. Defaults to 10.

Request (example - array of IDs)

[101, 102, 205]

Request (example - array of objects)

[{"id": 101}, {"id": 102}, {"id": 205}]

Request with limit query parameter

POST /api/oauth2/getRecords/zapier/contacts?limit=100

[101, 102, 205]

Response (example)

[
 { 
 "id": 101, 
 "name": "Acme Ltd",
 "created_by": 5,
 "created_date": "2025-01-15T10:30:00Z",
 "last_modified_by": 5,
 "last_modified_date": "2025-01-20T14:22:00Z"
 },
 { 
 "id": 102, 
 "name": "Globex",
 "created_by": 3,
 "created_date": "2025-01-10T09:15:00Z",
 "last_modified_by": 7,
 "last_modified_date": "2025-01-18T16:45:00Z"
 }
]
Note: Request/response shapes may vary by table schema. IDs are typically numeric.

Find Records (filter / fields / sort / paging)

POST /api/oauth2/findRecords/:source/:tableName

A powerful flexible querying endpoint supporting: selecting specific fields, filtering with advanced operators, text search, multi-field sorting, and pagination.

Field Usage: You can query, filter, and sort by any field available in your object/table. This includes the standard fields (id, name, created_by, created_date, last_modified_by, last_modified_date) as well as any custom fields specific to your table schema.

Request Body

Field Type Description
fields string[] List of columns to return. If omitted/empty, returns * (all fields).
filter object Filtering object with multiple options (see below).
filter.id string|number Exact match by ID.
filter.where object Field conditions. Supports simple values for equality (e.g., {"status":"Open"}) or operator objects for advanced queries (see examples below).
filter.search string Text search applied to the name field with pattern matching support (use % for wildcards).
sort {field:string, direction:"ASC"|"DESC"}[] Array of sort clauses. Invalid directions default to ASC. Supports multi-field sorting.
page_size number|string Number of records per page. Defaults to 50 if missing.
page number|string Page number for pagination. Defaults to 1 if missing.

Query Parameters

Parameter Type Description
limit number Optional. Maximum number of records to return. Valid range: 1 to 10,000. Defaults to 10. Can override pagination settings.
Advanced Filtering with Operators: The filter.where field supports multiple operators for complex queries:
  • = - Equality (default)
  • >, <, >=, <= - Comparison operators
  • != - Not equal
  • LIKE - Pattern matching (use % wildcards)
  • IN - Match any value in array
  • NOT IN - Exclude values in array
Use operator syntax: {"field": {"operator": ">=", "value": 100}}

Example 1: Simple equality filter with search

{
 "fields": ["id", "name", "email", "phone"],
 "filter": {
 "search": "john"
 },
 "sort": [
 { "field": "name", "direction": "ASC" }
 ],
 "page_size": 25,
 "page": 1
}

Example 2: Multiple equality conditions

{
 "filter": {
 "where": {
 "status": "Open",
 "assigned_to": 17
 }
 },
 "sort": [
 { "field": "updated_at", "direction": "DESC" }
 ],
 "page_size": 50,
 "page": 2
}

Example 3: Using comparison operators

{
 "fields": ["id", "name", "amount", "deal_date"],
 "filter": {
 "where": {
 "amount": {
 "operator": ">=",
 "value": 10000
 },
 "deal_date": {
 "operator": ">",
 "value": "2025-01-01"
 }
 }
 },
 "sort": [
 { "field": "amount", "direction": "DESC" }
 ],
 "page_size": 100
}

Example 4: Using IN operator for multiple values

{
 "fields": ["id", "name", "status", "priority"],
 "filter": {
 "where": {
 "status": {
 "operator": "IN",
 "value": ["Open", "In Progress", "Pending"]
 },
 "priority": {
 "operator": "!=",
 "value": "Low"
 }
 }
 },
 "sort": [
 { "field": "priority", "direction": "ASC" },
 { "field": "created_date", "direction": "DESC" }
 ]
}

Example 5: Using LIKE operator for pattern matching

{
 "fields": ["id", "name", "email"],
 "filter": {
 "where": {
 "email": {
 "operator": "LIKE",
 "value": "%@company.com"
 }
 }
 },
 "page_size": 50
}

Example 6: Common fields filter with NOT IN

{
 "fields": ["id", "name", "created_by", "created_date", "last_modified_date"],
 "filter": {
 "where": {
 "created_by": {
 "operator": "NOT IN",
 "value": [1, 2, 3]
 }
 }
 },
 "sort": [
 { "field": "last_modified_date", "direction": "DESC" }
 ],
 "page_size": 20,
 "page": 1
}

Response (example)

[
 { 
 "id": 501, 
 "name": "Contact Name",
 "created_by": 5,
 "created_date": "2025-01-15T10:30:00Z",
 "last_modified_date": "2025-01-21T09:15:00Z"
 },
 { 
 "id": 498, 
 "name": "Another Contact",
 "created_by": 5,
 "created_date": "2025-01-12T14:20:00Z",
 "last_modified_date": "2025-01-20T16:45:00Z"
 }
]

Create Records

POST /api/oauth2/create/:source/:tableName

Create one or more records in the specified table.

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Request Body

The request body must be an array of record objects to create.

Request (example)

[
 { "name": "New Account", "phone": "+1-555-0100" },
 { "name": "Another Account", "phone": "+1-555-0200" }
]

Response (example)

{
 "id": 901,
 "affectedRows": 2,
 "insertId": 901
}
Note: Only arrays are accepted. Each object in the array represents a record to create.

Update Records

POST /api/oauth2/update/:source/:tableName

Update one or more records by ID.

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Request Body

The request body must be an array of record objects to update. Each object must include an id field.

Request (example)

[
 { "id": 101, "phone": "+1-555-9999", "status": "Active" },
 { "id": 102, "status": "Inactive" }
]

Response (example)

{
 "id": 0,
 "affectedRows": 2,
 "changedRows": 2
}
Note: Your schema determines which fields are writable.

Delete Records

POST /api/oauth2/delete/:source/:tableName

Delete one or more records by ID.

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Request Body

The request body must be an array of objects with id fields to delete.

Request (example)

[
 {"id": 101},
 {"id": 102}
]

Response (example)

{
 "id": 0,
 "affectedRows": 2
}
Recycle Bin: Deleted records are moved to a recycle bin and retained for 30 days before permanent deletion.

Send Email

POST /api/oauth2/sendEmail/:source

Send messages/sms/emails using templates and settings. Supports bulk email sending with recipient list, optional email templates, and sender configuration.

Headers

Authorization: Bearer <access_token>
Content-Type: application/json

Request Body

Field Type Description
rows object[] Required. Array of recipient contacts. Each contact should contain email address and mobile phone and other recipient details.
fromEmailSet number Required.ID of the message/email/sms settings record to use (email_settings table). Use 1 as the default id. When provided, settings will be loaded from the database.
templateid number Optional. ID of the email template to use (templates table). If provided, template will be loaded from the database.
task object Optional. Task object to associate with the email campaign. If omitted, task will be created from template name.
task.name string Task name/title.

Request (example - with template ID)

{
 "templateid": 5,
 "fromEmailSet": 2,
 "rows": [
 { "email": "contact1@example.com", "name": "John Doe" },
 { "email": "contact2@example.com", "name": "Jane Smith" }
 ]
}

Request (example - with inline template)

{
 "fromEmailSet": 1,
 "rows": [
 { "email": "recipient@example.com", "name": "Recipient Name" }
 ],
 "template": {
 "name": "Welcome Email",
 "body": "<h1>Welcome!</h1><p>Thank you for signing up.</p>"
 },
 "task": {
 "name": "Welcome Email Campaign"
 }
}

Response (example)

{
 "affectedRows": 1
}
Template Resolution: If templateid is provided but template data is incomplete, the system will fetch the full template from the database. Provide either a templateid or complete template object (with name and body).
Authorization: Emails from @brosh.io or @zaapit.com domains require admin or superadmin role. For other domains, the authenticated user can send emails.
Required Fields: The request must include:
  • rows array (non-empty)
  • fromEmailSet (numeric ID referencing email_settings table)
  • Either templateid or complete template object with name and body
Missing any of these will result in a 400 Bad Request error.

Errors & Notes

Common HTTP statuses

StatusMeaning
200Success (some implementations may still return ok:false in body on logical errors)
400Bad request (missing/invalid parameters)
401Unauthorized (missing/invalid/expired token)
403Forbidden (token valid but insufficient permissions)
404Unknown endpoint or invalid tableName
500Server error
Best practice: Use valid field names (letters, numbers, underscore), and prefer explicit fields selection to minimize payload size.

Example cURL - Find Records

curl -X POST "https://app.brosh.io/api/oauth2/findRecords/zapier/contacts" \
 -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
 "fields":["id","name","email","created_date","last_modified_date"],
 "filter":{"search":"john"},
 "sort":[{"field":"last_modified_date","direction":"DESC"}],
 "page_size":25,
 "page":1
 }'

Example cURL - Get Records with Limit

curl -X POST "https://app.brosh.io/api/oauth2/getRecords/zapier/contacts?limit=100" \
 -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
 -H "Content-Type: application/json" \
 -d '[101,102,205]'
We use cookies to personalize content, ads and to analyze our traffic. Our Cookie Policy Accept