Skip to main content

BC Dialing Application

Business Central extension that integrates Nextiva phone and email events with Customer records. Receives incoming call and email notifications via API, creates or matches Customer records, and asynchronously syncs call summaries, recordings, and transcripts to Customer record links via Azure Blob Storage.

Overview

When a phone call or email arrives through Nextiva, an Azure Function forwards the event to one of this extension's API pages. The API page looks up the Customer by phone number or email address. If no match is found, it creates a new Customer from the configured customer template (default: ECOMMERCE) and returns a URL to the Customer Card. CS agents use this URL to immediately open the customer's record during the call.

After the call ends, a Job Queue entry (CU-60003) runs on a recurring schedule to process pending log records. For each record, the codeunit calls the Nextiva Analytics API to retrieve the call summary, recording, and transcript, then uploads each artifact to Azure Blob Storage and links the blob URL to the Customer record.

Architecture

BC Dialing Architecture

Prerequisites

  • Business Central version 27.0 or later (application 27.0.0.0, runtime 16.0)
  • VS Code with the AL Language extension (for development)
  • Azure Blob Storage account (p360data) with the nextiva-bc container and a valid SAS token
  • Nextiva analytics API credentials (configured via the Nextiva Config Setup page)
  • No BC extension dependencies — this extension is standalone

Object ID Allocation

Object IDTypeNamePurpose
60000CodeunitPhone IntegrationOriginal call handling logic (legacy)
60001CodeunitAttach Media CodeunitMedia attachment helper
60002CodeunitAzure Blob StorageBlob storage operations (legacy)
60003CodeunitNextiva IntegrationJob Queue processor — async sync of summaries, recordings, transcripts, and emails
60004CodeunitNextiva Integration ManualManual sync trigger with standalone API calls
60005CodeunitDialer UpgradeUpgrade codeunit — populates NextivaConfig on deployment
60000Table ExtensionCustomerDialerKeysSecondary indexes on Customer table for Phone No. and E-Mail lookups
60000TableCallLogLegacy call log table
60001TableAzureStorageConfigAzure Storage configuration
80000TableCustomerPhoneLogPhone call log records
80001TableNextivaDataTemporary data structure for Nextiva API processing
80002TableCustomerEmailLogEmail log records
80003TableNextivaConfigExtension configuration
80004TableNextiva Error LogsError log for failed sync operations
60000PageReceivingComponentLegacy receiving component UI
60001PageCompletionComponentLegacy completion component UI
60008PageCallLogListCall log list view
60009PageAzureStorageConfigurationAzure Storage setup page
60010PageTestReceivingComponentTest page for receiving component
60011PageTestCompletionComponentTest page for completion component
80000PageReceivePhoneNumberAPI page — incoming phone call webhook
80001PageEndCallAPI page — call end webhook
80002PageNextivaAPIViewerNextiva API data viewer
80003PageReceiveEmailAPI page — incoming email webhook
80004PageEndMailCallEmail call end page
80005PageCustomerPhoneLogViewerPhone log list page
80006PageCustomerEmailLogViewerEmail log list page
80007PageNextivaSetupPageExtension setup page
80008PageNextivaErrorLogsViewerError log viewer
80009PageNextivaManualSyncManual sync trigger page
80010PageNextivaConfigAPIAPI page — read-only config verification endpoint
PermissionSetBCDialerPermissionsExtension permission set

ID range 60000–99999 is reserved for this extension. Next available table: 80005. Next available page: 80011. Next available codeunit: 60006.

API Pages (Webhook Endpoints)

All API pages are published under APIPublisher = 'CambaySolutions' and APIGroup = 'PhoneIntegration'.

ReceivePhoneNumber (Page 80000)

Endpoint: POST /CambaySolutions/PhoneIntegration/PhoneNumbers

Receives an incoming phone call event. Looks up the Customer by Phone No.. If no match is found, creates a new Customer using the ECOMMERCE template with Name = 'New Customer' and the incoming phone number. Returns the Customer Card URL and Customer No.

FieldTypeDirectionDescription
phonenumberTextInIncoming phone number
customerurlTextOutURL to the Customer Card in BC
customernumTextOutCustomer No.

EndCall (Page 80001)

Endpoint: POST /CambaySolutions/PhoneIntegration/CallEnds

Receives a call-end event with the Nextiva session ID. Creates a phone log record for the Job Queue to process asynchronously.

FieldTypeDirectionDescription
phonenumTextInPhone number
sessionidTextInNextiva session ID for API lookups

ReceiveEmail (Page 80003)

Endpoint: POST /CambaySolutions/PhoneIntegration/Emails

Receives an incoming email event. Same Customer lookup/creation logic as ReceivePhoneNumber but matches on E-Mail instead of Phone No..

FieldTypeDirectionDescription
emailTextInIncoming email address
customerurlTextOutURL to the Customer Card in BC
customernumTextOutCustomer No.

Customer Record Management

Customer Creation Sequence

When an incoming call or email arrives for a phone number or email address not already on file:

  1. The customer template is loaded from NextivaConfig."Customer Template" (default: ECOMMERCE) via Customer Templ.
  2. A new Customer record is initialized with Name = 'New Customer' and the incoming phone/email
  3. The customer number is assigned via InitCustomerNo from the template's No. Series
  4. Insert(true) fires the standard OnInsert trigger for complete BC customer setup
  5. ApplyCustomerTemplate applies template defaults (posting groups, payment terms, etc.)
  6. The phone number or email is re-applied after template application as a defensive measure
  7. Modify(true) persists the final state

Read-only lookups use SetLoadFields with a separate record variable to avoid SetLoadFields bleed-through into the creation path.

Job Queue & Async Processing

Job Queue Processing Sequence

Codeunit 60003 (Nextiva Integration) runs as a recurring Job Queue entry. Each cycle processes up to Max Phone Logs Per Run phone records and Max Email Logs Per Run email records (both configurable, default 50):

  1. Queries CustomerPhoneLog for records where all three sync flags are false and Attempts < 3
  2. For each pending record (up to the batch cap), calls the Nextiva Analytics API to fetch the call summary, recording URL, and transcript
  3. Uploads each artifact (HTML for summary/transcript, MP3 for recording) to Azure Blob Storage
  4. Creates a Record Link on the matched Customer record pointing to the blob URL
  5. Sets the corresponding sync flag (SummaryUpdated, TranscriptUpdated, RecordingUpdated) to true and increments the Attempts counter in a single database write
  6. Commits after each record (micro-transaction pattern) to release locks between iterations
  7. When the batch cap is reached, remaining records are deferred to the next Job Queue run

The same pattern applies for email logs using InboundEmailUpdated and OutboundEmailUpdated flags.

Records with 3 or more attempts are skipped — these represent persistent failures that need manual investigation via the Nextiva Error Logs viewer (Page 80008). Records that fail due to permanent conditions (e.g., no matching Customer) are immediately abandoned (set to 3 attempts) to avoid wasting retries.

Logging & Monitoring

  • Nextiva Error Logs (Table 80004, Page 80008): Captures errors from the Job Queue processor with source type, source number, session ID, customer number, and error message
  • Application Insights: Extension-level telemetry flows to Bestway's Azure Application Insights resource via the connection string in app.json
  • Phone/Email Log Viewers (Pages 80005, 80006): Browse all phone and email log records with their sync status flags and attempt counts

Development

Folder Structure

Cambay Solutions_BC Dialing Application/
├── app.json
├── BCDialerPermissions.permissionset.al
├── README.md
├── docs/
│ ├── CHANGELOG.md
│ ├── CHANGE-v2.4.0.0.md
│ ├── CHANGE-v2.3.0.0.md
│ ├── CHANGE-v2.2.1.0.md
│ ├── CHANGE-v2.2.0.0.md
│ ├── CHANGE-v2.1.0.0.md
│ └── INVESTIGATION-Performance-Locking.md
├── tools/
│ ├── verify_deployment.py (deployment verification script)
│ └── requirements.txt
├── src/
│ ├── Codeunit/
│ ├── Page/
│ ├── Table/
│ └── TableExt/
└── BCDialingAzure/ (Azure Function — separate deployment)

Download Symbols

Run AL: Download Symbols in VS Code to pull base application symbols into .alpackages/.

Publish to Sandbox

Press F5 or run AL: Publish to deploy to the configured sandbox environment.

Package

Run AL: Package to build the .app file for deployment to other environments.

Configuration

All integration credentials and environment-specific values are stored in the NextivaConfig table (80003), managed via the Nextiva Config Setup page (80007). The upgrade codeunit (CU-60005) auto-populates the config record during initial deployment.

FieldPurposeExample
BC Base URLCustomer Card URL template (must contain %1 for customer number)https://businesscentral.dynamics.com/.../Production/?company=...&page=21&filter=''No.'' IS ''%1''
Customer TemplateBC Customer Template code used when creating new customersECOMMERCE
Nextiva Login URLNextiva authentication endpointhttps://login.thrio.com
Nextiva AuthTextNextiva API credentials (stored masked)user@nextiva.com:password
Azure Blob SAS TokenSAS token for Azure Blob Storage container access (stored masked)si=BCDialer&spr=https&...
Max Phone Logs Per RunMaximum phone log records processed per Job Queue run (default: 50)50
Max Email Logs Per RunMaximum email log records processed per Job Queue run (default: 50)50

Deployment Verification

A Python deployment verification script is included at tools/verify_deployment.py. It validates config population, Nextiva API connectivity, Azure Blob access, and customer template existence. See docs/CHANGE-v2.3.0.0.md for full usage instructions.

cd tools
../../tools/venv/bin/python verify_deployment.py --config-only # config check only
../../tools/venv/bin/python verify_deployment.py \ # full validation
--nextiva-auth-text "user:pass" --azure-sas-token "si=BCDialer&..."

Requires Python 3.13 venv at ../../tools/venv/ with requests, python-dotenv, and azure-storage-blob.

Known Limitations

  • Hardcoded credential fallbacks (transitional) — v2.3.0.0 reads all credentials from the NextivaConfig table but retains hardcoded fallback values in else branches for backward compatibility. Each fallback branch emits a Session.LogMessage warning to Application Insights (event IDs BCDIALER-0001 through BCDIALER-0003), making fallback activation immediately detectable in telemetry. After confirming the config-driven approach works in production (no BCDIALER-000* warnings in telemetry), the fallbacks should be replaced with Error() calls in v2.4.0.0. See docs/CHANGE-v2.3.0.0.md (Credential Migration section) for the complete inventory, KQL query, and remediation plan.
  • Azure Storage Account and Container not yet configurable — The storage account name (p360data) and container name (nextiva-bc) remain hardcoded in CU-60003 and CU-60004. These should be added to NextivaConfig in v2.4.0.0.
  • No automated tests — The extension has no AL test codeunits. Business logic in the API pages and Job Queue processor should be extracted into testable helper codeunits.
  • Duplicate Customer risk — Simultaneous API calls for the same phone number could theoretically create duplicate Customers (sub-millisecond race window). See docs/CHANGE-v2.2.0.0.md for full analysis.

Changelog

See docs/CHANGELOG.md for the full version history, docs/ for detailed per-version change documents, and docs/INVESTIGATION-Performance-Locking.md for the full performance investigation timeline (v2.0.0.12 through v2.3.0.0).