Skip to main content

CallRail - Accounts & Companies

๐Ÿ“– Overviewโ€‹

CallRail organizes tracking data in a hierarchical structure: Accounts โ†’ Companies โ†’ Trackers โ†’ Calls. Accounts represent the highest level (e.g., agency), while Companies represent individual clients or business units. This module manages account and company listings, CRUD operations, and webhook configurations for real-time event synchronization.

Source Files:

  • Controllers: external/Integrations/Callrail/Controllers/accounts.js, companies.js
  • Providers: external/Integrations/Callrail/Providers/accounts-api.js, companies-api.js
  • Routes: external/Integrations/Callrail/Routes/accounts.js, companies.js

External APIs:

  • CallRail API v3 - /accounts, /companies, /webhooks

๐Ÿ—„๏ธ Collections Usedโ€‹

integrations.callrail.keyโ€‹

  • Operations: Read
  • Usage: Retrieve API key for authentication
  • See Authentication for full schema

analytics.callrail.userconfigโ€‹

  • Operations: Read
  • Usage: Get configured account/company IDs
  • See Authentication for full schema

๐Ÿ”„ Data Flowโ€‹

Account Listing Flowโ€‹

sequenceDiagram
participant Client as DashClicks Frontend
participant Controller as Accounts Controller
participant Provider as Accounts API Provider
participant CallRail as CallRail API v3
participant KeysDB as MongoDB (keys)

Client->>Controller: GET /v1/e/callrail/accounts?page=1&per_page=10
Controller->>KeysDB: Find API key for account
KeysDB-->>Controller: Return api_key

Controller->>Provider: getAccounts(api_key, params)
Provider->>CallRail: GET /v3/a/accounts.json
CallRail-->>Provider: Account list with pagination

Provider-->>Controller: Formatted account data
Controller-->>Client: {accounts: [...], total_pages, total_records}

Company Listing Flowโ€‹

sequenceDiagram
participant Client as DashClicks Frontend
participant Controller as Companies Controller
participant Provider as Companies API Provider
participant CallRail as CallRail API v3
participant KeysDB as MongoDB (keys)

Client->>Controller: GET /v1/e/callrail/companies?account_id=470306151
Controller->>KeysDB: Find API key for account
KeysDB-->>Controller: Return api_key

Controller->>Provider: getCompanies(api_key, accountId, params)
Provider->>CallRail: GET /v3/a/470306151/companies.json
CallRail-->>Provider: Company list with pagination

Provider-->>Controller: Formatted company data
Controller-->>Client: {companies: [...], total_pages, total_records}

Webhook Creation Flowโ€‹

sequenceDiagram
participant Client as DashClicks Frontend
participant Controller as Companies Controller
participant Provider as Companies API Provider
participant CallRail as CallRail API v3
participant KeysDB as MongoDB (keys)

Client->>Controller: POST /v1/e/callrail/companies/webhook
Controller->>KeysDB: Find API key for account
KeysDB-->>Controller: Return api_key

Controller->>Provider: addWebhook(api_key, accountId, companyId, url)
Provider->>CallRail: POST /v3/a/{account}/companies/{company}/webhooks.json
CallRail-->>Provider: Webhook created

Provider-->>Controller: Webhook details
Controller-->>Client: {success: true, data: webhook}

๐Ÿ”ง Business Logic & Functionsโ€‹


Account Functionsโ€‹

getAccounts(req, res, next)โ€‹

Purpose: Retrieve paginated list of CallRail accounts

Source: Controllers/accounts.js

External API: GET https://api.callrail.com/v3/a/accounts.json

Authentication: Bearer token (API key)

Parameters:

  • req.query.page (Number, optional) - Page number (default: 1)
  • req.query.per_page (Number, optional) - Results per page (default: 10, max: 250)
  • req.query.sort (String, optional) - Sort field (e.g., "name", "-created_at")
  • req.auth.account_id (ObjectId) - DashClicks account ID

Returns: JSON response with accounts array

{
"success": true,
"message": "SUCCESS",
"data": {
"accounts": [
{
"id": "470306151",
"name": "Acme Agency",
"companies_count": 12,
"outbound_recording_enabled": true,
"hipaa_account": false
}
],
"page": 1,
"per_page": 10,
"total_pages": 1,
"total_records": 1
}
}

Business Logic Flow:

  1. Validate Account Access

    • Call checkAccountAccess(req) to verify account permissions
  2. Retrieve API Key

    • Query callrail.key collection for account's API key
    • Exclude soft-deleted keys
    • Return error if no key found
  3. Build Query Parameters

    • Extract page, per_page, sort from query string
    • Apply defaults (page: 1, per_page: 10)
  4. Call CallRail API

    • Provider makes GET request to /v3/a/accounts.json
    • Pass pagination and sorting parameters
  5. Format Response

    • Extract accounts array and pagination metadata
    • Return formatted data

Request Example:

GET /v1/e/callrail/accounts?page=1&per_page=10&sort=name
Authorization: Bearer {jwt_token}

Success Response:

{
"success": true,
"message": "SUCCESS",
"data": {
"accounts": [
{
"id": "470306151",
"name": "Acme Agency",
"companies_count": 12,
"outbound_recording_enabled": true,
"hipaa_account": false
}
],
"page": 1,
"per_page": 10,
"total_pages": 1,
"total_records": 1
}
}

Error Response (No API Key):

{
"success": false,
"errno": 400,
"message": "API key not found. Please add your CallRail API key first."
}

Error Handling:

  • Invalid Account: Returns 400 with INVALID_ACCOUNT_ID
  • No API Key: Returns 400 with descriptive message
  • CallRail API Error: Propagated to error middleware
  • 401 Unauthorized: Token invalidation handled by main error handler

Example Usage:

// Fetch first page of accounts
const response = await fetch('/v1/e/callrail/accounts?page=1&per_page=10', {
headers: { Authorization: `Bearer ${token}` },
});

const { accounts, total_records } = await response.json();

Side Effects:

  • โ„น๏ธ Database Read: Queries API key
  • โ„น๏ธ External API Call: CallRail API usage

Company Functionsโ€‹

getCompanies(req, res, next)โ€‹

Purpose: Retrieve paginated list of companies for a CallRail account

Source: Controllers/companies.js

External API: GET https://api.callrail.com/v3/a/{account_id}/companies.json

Authentication: Bearer token (API key)

Parameters:

  • req.query.account_id (String, required) - CallRail account ID
  • req.query.page (Number, optional) - Page number (default: 1)
  • req.query.per_page (Number, optional) - Results per page (default: 10, max: 250)
  • req.query.sort (String, optional) - Sort field
  • req.query.disabled (Boolean, optional) - Include disabled companies
  • req.query.search (String, optional) - Search by company name
  • req.auth.account_id (ObjectId) - DashClicks account ID

Returns: JSON response with companies array

{
"success": true,
"message": "SUCCESS",
"data": {
"companies": [
{
"id": "com_abc123",
"name": "Acme Corp",
"status": "active",
"time_zone": "America/New_York",
"created_at": "2023-01-15T10:00:00Z",
"disabled_at": null,
"dni_active": true,
"script_url": "https://cdn.callrail.com/companies/123456/abc123/12/swap.js"
}
],
"page": 1,
"per_page": 10,
"total_pages": 2,
"total_records": 15
}
}

Business Logic Flow:

  1. Validate Account Access

    • Verify account permissions
  2. Retrieve API Key

    • Query database for CallRail API key
    • Return error if not found
  3. Validate Required Fields

    • Check that account_id query parameter provided
    • Return 400 if missing
  4. Build Query Parameters

    • Extract page, per_page, sort, disabled, search
    • Apply defaults
  5. Call CallRail API

    • Provider makes GET request to /v3/a/{account_id}/companies.json
    • Pass all query parameters
  6. Format Response

    • Extract companies array and pagination metadata
    • Return formatted data

Request Example:

GET /v1/e/callrail/companies?account_id=470306151&page=1&per_page=10&search=Acme
Authorization: Bearer {jwt_token}

Success Response:

{
"success": true,
"message": "SUCCESS",
"data": {
"companies": [
{
"id": "com_abc123",
"name": "Acme Corp",
"status": "active",
"time_zone": "America/New_York",
"created_at": "2023-01-15T10:00:00Z",
"disabled_at": null,
"dni_active": true,
"script_url": "https://cdn.callrail.com/companies/123456/abc123/12/swap.js",
"callscore_enabled": false,
"lead_scoring_enabled": true,
"swap_exclude_jquery": false,
"swap_ppc_override": false,
"swap_landing_override": false
}
],
"page": 1,
"per_page": 10,
"total_pages": 1,
"total_records": 1
}
}

Error Response (Missing account_id):

{
"success": false,
"errno": 400,
"message": "Callrail account id is required."
}

Error Handling:

  • Invalid Account: Returns 400 with INVALID_ACCOUNT_ID
  • No API Key: Returns 400 with descriptive message
  • Missing account_id: Returns 400 with specific message
  • CallRail API Error: Propagated to error middleware

Example Usage:

// Search for companies by name
const response = await fetch('/v1/e/callrail/companies?account_id=470306151&search=Acme&page=1', {
headers: { Authorization: `Bearer ${token}` },
});

const { companies } = await response.json();

Side Effects:

  • โ„น๏ธ Database Read: Queries API key
  • โ„น๏ธ External API Call: CallRail API usage

addWebhook(req, res, next)โ€‹

Purpose: Create a webhook for real-time call event notifications

Source: Controllers/companies.js

External API: POST https://api.callrail.com/v3/a/{account_id}/companies/{company_id}/webhooks.json

Authentication: Bearer token (API key)

Parameters:

  • req.body.account_id (String, required) - CallRail account ID
  • req.body.company_id (String, required) - CallRail company ID
  • req.body.webhook_url (String, required) - Webhook destination URL
  • req.auth.account_id (ObjectId) - DashClicks account ID

Returns: JSON response with webhook details

{
"success": true,
"message": "SUCCESS",
"data": {
"id": "web_12345",
"account_id": "470306151",
"company_id": "com_abc123",
"url": "https://dashclicks.com/api/webhooks/callrail",
"status": "enabled",
"events": ["call.completed", "call.received"],
"created_at": "2023-10-01T12:00:00Z"
}
}

Business Logic Flow:

  1. Validate Account Access

    • Verify account permissions
  2. Retrieve API Key

    • Query database for CallRail API key
  3. Validate Required Fields

    • Check account_id, company_id, webhook_url provided
    • Return 400 if any missing
  4. Call CallRail API

    • Provider makes POST request to webhooks endpoint
    • Pass webhook_url and event configuration
  5. Return Webhook Details

    • Include webhook ID, status, events subscribed

Request Example:

POST /v1/e/callrail/companies/webhook
Authorization: Bearer {jwt_token}
Content-Type: application/json

{
"account_id": "470306151",
"company_id": "com_abc123",
"webhook_url": "https://dashclicks.com/api/webhooks/callrail"
}

Success Response:

{
"success": true,
"message": "SUCCESS",
"data": {
"id": "web_12345",
"account_id": "470306151",
"company_id": "com_abc123",
"url": "https://dashclicks.com/api/webhooks/callrail",
"status": "enabled",
"events": ["call.completed", "call.received"],
"created_at": "2023-10-01T12:00:00Z"
}
}

Error Response (Missing Fields):

{
"success": false,
"errno": 400,
"message": "Callrail account id, company id and webhook url are required."
}

Webhook Events:

  • call.completed - Call has ended
  • call.received - New call received
  • form.submission - Form submitted (if DNI enabled)

Error Handling:

  • Invalid Account: Returns 400 with INVALID_ACCOUNT_ID
  • No API Key: Returns 400 with descriptive message
  • Missing Fields: Returns 400 with specific message
  • Duplicate Webhook: CallRail returns error if webhook exists
  • Invalid URL: CallRail validates webhook URL format

Example Usage:

// Create webhook for company
await fetch('/v1/e/callrail/companies/webhook', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
account_id: '470306151',
company_id: 'com_abc123',
webhook_url: 'https://dashclicks.com/api/webhooks/callrail',
}),
});

Side Effects:

  • โš ๏ธ Webhook Creation: Creates webhook in CallRail system
  • โš ๏ธ External API Call: Modifies CallRail configuration
  • โ„น๏ธ Real-time Events: Enables push notifications for calls

updateWebhook(req, res, next)โ€‹

Purpose: Update webhook configuration (enable/disable, change URL)

Source: Controllers/companies.js

External API: PUT https://api.callrail.com/v3/a/{account_id}/companies/{company_id}/webhooks/{webhook_id}.json

Authentication: Bearer token (API key)

Parameters:

  • req.body.account_id (String, required) - CallRail account ID
  • req.body.company_id (String, required) - CallRail company ID
  • req.body.webhook_id (String, required) - Webhook ID to update
  • req.body.webhook_url (String, optional) - New webhook URL
  • req.body.status (String, optional) - "enabled" or "disabled"
  • req.auth.account_id (ObjectId) - DashClicks account ID

Returns: JSON response with updated webhook

{
"success": true,
"message": "SUCCESS",
"data": {
"id": "web_12345",
"account_id": "470306151",
"company_id": "com_abc123",
"url": "https://dashclicks.com/api/webhooks/callrail-v2",
"status": "enabled",
"events": ["call.completed", "call.received"],
"updated_at": "2023-10-05T14:30:00Z"
}
}

Business Logic Flow:

  1. Validate Account Access

    • Verify account permissions
  2. Retrieve API Key

    • Query database for CallRail API key
  3. Validate Required Fields

    • Check account_id, company_id, webhook_id provided
    • At least one of webhook_url or status must be provided
  4. Call CallRail API

    • Provider makes PUT request to webhook endpoint
    • Pass updated fields
  5. Return Updated Webhook

Request Example:

PUT /v1/e/callrail/companies/webhook
Authorization: Bearer {jwt_token}
Content-Type: application/json

{
"account_id": "470306151",
"company_id": "com_abc123",
"webhook_id": "web_12345",
"status": "disabled"
}

Success Response:

{
"success": true,
"message": "SUCCESS",
"data": {
"id": "web_12345",
"status": "disabled",
"updated_at": "2023-10-05T14:30:00Z"
}
}

Error Response (Missing Fields):

{
"success": false,
"errno": 400,
"message": "Callrail account id, company id, webhook id and webhook url or status are required."
}

Error Handling:

  • Invalid Account: Returns 400 with INVALID_ACCOUNT_ID
  • No API Key: Returns 400 with descriptive message
  • Missing Fields: Returns 400 with specific message
  • Invalid Webhook ID: CallRail returns 404 error
  • Invalid Status: CallRail returns validation error

Example Usage:

// Disable webhook
await fetch('/v1/e/callrail/companies/webhook', {
method: 'PUT',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
account_id: '470306151',
company_id: 'com_abc123',
webhook_id: 'web_12345',
status: 'disabled',
}),
});

Side Effects:

  • โš ๏ธ Webhook Update: Modifies webhook configuration
  • โš ๏ธ Event Flow: Disabling stops real-time notifications
  • โ„น๏ธ External API Call: Updates CallRail configuration

Provider Functionsโ€‹

getAccounts(apiKey, params)โ€‹

Purpose: Call CallRail API to retrieve accounts

Source: Providers/accounts-api.js

External API: GET https://api.callrail.com/v3/a/accounts.json

Parameters:

  • apiKey (String) - CallRail API key
  • params (Object) - Query parameters (page, per_page, sort)

Returns: Promise<Object> - API response data

HTTP Request:

GET /v3/a/accounts.json?page=1&per_page=10
Host: api.callrail.com
Authorization: Bearer {api_key}

Example Usage:

const accounts = await accountsApi.getAccounts(apiKey, {
page: 1,
per_page: 10,
sort: 'name',
});

Side Effects:

  • โ„น๏ธ External API Call: CallRail API request

getCompanies(apiKey, accountId, params)โ€‹

Purpose: Call CallRail API to retrieve companies

Source: Providers/companies-api.js

External API: GET https://api.callrail.com/v3/a/{account_id}/companies.json

Parameters:

  • apiKey (String) - CallRail API key
  • accountId (String) - CallRail account ID
  • params (Object) - Query parameters

Returns: Promise<Object> - API response data

HTTP Request:

GET /v3/a/470306151/companies.json?page=1&per_page=10&search=Acme
Host: api.callrail.com
Authorization: Bearer {api_key}

Example Usage:

const companies = await companiesApi.getCompanies(apiKey, '470306151', {
page: 1,
per_page: 10,
search: 'Acme',
});

Side Effects:

  • โ„น๏ธ External API Call: CallRail API request

addWebhook(apiKey, accountId, companyId, webhookUrl)โ€‹

Purpose: Call CallRail API to create webhook

Source: Providers/companies-api.js

External API: POST https://api.callrail.com/v3/a/{account_id}/companies/{company_id}/webhooks.json

Parameters:

  • apiKey (String) - CallRail API key
  • accountId (String) - CallRail account ID
  • companyId (String) - CallRail company ID
  • webhookUrl (String) - Webhook destination URL

Returns: Promise<Object> - Webhook details

HTTP Request:

POST /v3/a/470306151/companies/com_abc123/webhooks.json
Host: api.callrail.com
Authorization: Bearer {api_key}
Content-Type: application/json

{
"url": "https://dashclicks.com/api/webhooks/callrail"
}

Example Usage:

const webhook = await companiesApi.addWebhook(
apiKey,
'470306151',
'com_abc123',
'https://dashclicks.com/api/webhooks/callrail',
);

Side Effects:

  • โš ๏ธ Webhook Creation: Creates webhook in CallRail
  • โ„น๏ธ External API Call: Modifies CallRail configuration

updateWebhook(apiKey, accountId, companyId, webhookId, data)โ€‹

Purpose: Call CallRail API to update webhook

Source: Providers/companies-api.js

External API: PUT https://api.callrail.com/v3/a/{account_id}/companies/{company_id}/webhooks/{webhook_id}.json

Parameters:

  • apiKey (String) - CallRail API key
  • accountId (String) - CallRail account ID
  • companyId (String) - CallRail company ID
  • webhookId (String) - Webhook ID
  • data (Object) - Update data (url, status)

Returns: Promise<Object> - Updated webhook details

HTTP Request:

PUT /v3/a/470306151/companies/com_abc123/webhooks/web_12345.json
Host: api.callrail.com
Authorization: Bearer {api_key}
Content-Type: application/json

{
"status": "disabled"
}

Example Usage:

const webhook = await companiesApi.updateWebhook(apiKey, '470306151', 'com_abc123', 'web_12345', {
status: 'disabled',
});

Side Effects:

  • โš ๏ธ Webhook Update: Modifies webhook configuration
  • โ„น๏ธ External API Call: Updates CallRail configuration

๐Ÿ”€ Integration Pointsโ€‹

CallRail Hierarchyโ€‹

Account โ†’ Company Relationship:

  • One Account can have multiple Companies
  • Companies represent individual clients or business units
  • Each Company has its own trackers and calls

Usage Pattern:

  1. List accounts to get account IDs
  2. Select account and list companies
  3. Select company and create trackers
  4. Trackers generate calls

Webhook Integrationโ€‹

Real-time Event Processing:

  • Webhooks send POST requests to specified URL
  • Events include call data (caller, duration, recording, etc.)
  • Used for immediate campaign attribution and notifications

Webhook Payload Example:

{
"event": "call.completed",
"data": {
"id": "call_12345",
"company_id": "com_abc123",
"customer_phone_number": "+15551234567",
"duration": 180,
"recording": "https://api.callrail.com/recordings/rec_12345.mp3",
"start_time": "2023-10-01T14:30:00Z"
}
}

๐Ÿงช Edge Cases & Special Handlingโ€‹

Paginationโ€‹

Issue: Large accounts may have hundreds of companies

Handling:

  • Use per_page parameter (max 250)
  • Iterate through pages using page parameter
  • Response includes total_pages for UI implementation

Disabled Companiesโ€‹

Issue: Need to show/hide disabled companies

Handling:

  • Use disabled=true query parameter to include disabled companies
  • Default excludes disabled companies
  • disabled_at field shows when company was disabled

Search Functionalityโ€‹

Issue: Need to filter companies by name

Handling:

  • Use search query parameter for partial name match
  • CallRail API performs case-insensitive search
  • Combine with pagination for efficient browsing

Webhook Duplicationโ€‹

Issue: Creating duplicate webhooks causes errors

Handling:

  • CallRail returns error if webhook with same URL exists
  • Frontend should check existing webhooks before creation
  • Use update endpoint to modify existing webhooks

โš ๏ธ Important Notesโ€‹

  • ๐Ÿ“Š Hierarchy: Accounts โ†’ Companies โ†’ Trackers โ†’ Calls
  • ๐Ÿ” Filtering: Support for search, pagination, sorting, disabled filter
  • ๐Ÿ”„ Webhooks: Real-time event notifications for call tracking
  • ๐Ÿ” API Key: Required for all operations (Bearer token)
  • ๐Ÿ“ˆ Rate Limits: CallRail API has rate limits (check API docs)
  • ๐Ÿ—‘๏ธ Soft Delete: Companies marked as disabled, not deleted
  • ๐Ÿ“ Company Fields: Includes DNI script URL, timezone, lead scoring settings
  • โš ๏ธ Webhook Events: Subscribe to specific events (call.completed, call.received)

๐Ÿ’ฌ

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:30 AM