Skip to main content

Bestway CSM API Toolkit

A Business Central AL extension that exposes read-only OData v4 API endpoints for service order data, fault reporting tables, and posted document lines. Built for the Bestway USA CSM (Customer Service Management) integration workflow and CMS FAQ Management automated test validation.

Overview

This extension publishes custom API pages under the bestway/csm/v1.0 API group. External systems (e.g., CSM platforms, reporting tools, automated test suites) can query service order data, fault reporting master tables, code relationships, and posted document lines.

All endpoints are read-onlyPOST, PATCH, and DELETE requests are rejected.

Prerequisites

  • Business Central version 27.0 or later (application 27.0.0.0, runtime 16.0)
  • BestwayUSA extension (publisher: Innovia Consulting, v27.0.0.0) — provides custom INVC-prefixed fields on Service Header, Service Line, Service Invoice Header, and Document Attachment tables
  • VS Code with the AL Language extension (for development)

Object ID Allocation

Object IDTypeNameSource TableDescription
56101PageService Order APIService HeaderService order headers
56102PageService Order Line APIService LineService order lines (subpage)
56103PageServ. Order Attachment APIDocument AttachmentDocument attachments (subpage)
56104CodeunitCSM API HelperExtracted computed field logic for testability
56105PageFault Area APIFault Area (5915)Fault area master data
56106PageSymptom Code APISymptom Code (5916)Symptom code master data
56107PageFault Code APIFault Code (5918)Fault code master data
56108PageResolution Code APIResolution Code (5919)Resolution code master data
56109PageFault Resol. Relation APIFault/Resol. Cod. Relationship (5920)Code relationship mappings
56120PageFA Symptom Relation APIINVC FA Symptom Code Relation (50113)Fault area/symptom code relationships
56121PagePosted Svc. Invoice Line APIService Invoice Line (5993)Posted service invoice lines
56122PagePosted Svc. Shipment Line APIService Shipment Line (5991)Posted service shipment lines
56123PagePosted Svc. Invoice Header APIService Invoice Header (5992)Posted service invoice headers

ID range 56100–56149 is reserved for this extension. Next available: 56124.

Data Model

CSM API Entity Model

API Reference

Base URL pattern:

https://api.businesscentral.dynamics.com/v2.0/{tenantId}/{environment}/api/bestway/csm/v1.0/companies({companyId})

Service Orders (Page 56101)

Endpoint: /serviceOrders Source Table: Service Header (filtered to Document Type = Order)

FieldTypeDescription
idGUIDSystemId
noTextService order number
customerNoTextCustomer number
orderDateDateOrder date
postingDateDatePosting date
csmQualitySentBooleanComputed: true if any posted service invoice for this order has INVC CSM Quality Sent = true

Subpages (expandable via $expand):

  • serviceOrderLines — linked by Document Type + Document No.
  • serviceOrderAttachments — linked by No.

Service Order Lines (Page 56102)

Endpoint: /serviceOrders({id})/serviceOrderLines Source Table: Service Line

FieldTypeDescription
idGUIDSystemId
noTextLine No.
bestwaySerialNoTextINVC Bestway Serial No. from BestwayUSA extension
itemCategoryCodeTextItem category code
faultAreaCodeTextFault area code
faultAreaDescriptionTextLooked up from Fault Area table
symptomCodeTextSymptom code
symptomCodeDescriptionTextLooked up from Symptom Code table
faultCodeTextFault code
faultCodeDescriptionTextLooked up from Fault Code table
resolutionCodeTextResolution code
descriptionTextLine description
description2TextLine description 2
quantityDecimalQuantity
serviceItemNoTextService item number
itemNoTextLooked up from Service Item → Item No.
salesDateDateLooked up from Service Item → Sales Date

Service Order Attachments (Page 56103)

Endpoint: /serviceOrders({id})/serviceOrderAttachments Source Table: Document Attachment (filtered to Table ID = 5900, Document Type = Order)

FieldTypeDescription
idGUIDSystemId
documentNoTextService order number
lineNoIntegerAttachment line number
fileNameTextFile name
fileExtensionTextFile extension (e.g., .jpg)
fileTypeEnumFile type (e.g., Image, PDF)
attachmentTypeEnumINVC Document Attachment Type from BestwayUSA extension
contentBase64TextBase64-encoded file content (streamed via Temp Blob + Base64 Convert)

Fault Areas (Page 56105)

Endpoint: /faultAreas Source Table: Fault Area (5915)

FieldTypeDescription
idGUIDSystemId
codeTextFault area code
descriptionTextFault area description

Symptom Codes (Page 56106)

Endpoint: /symptomCodes Source Table: Symptom Code (5916)

FieldTypeDescription
idGUIDSystemId
codeTextSymptom code
descriptionTextSymptom code description

Fault Codes (Page 56107)

Endpoint: /faultCodes Source Table: Fault Code (5918)

FieldTypeDescription
idGUIDSystemId
codeTextFault code
descriptionTextFault code description

Resolution Codes (Page 56108)

Endpoint: /resolutionCodes Source Table: Resolution Code (5919)

FieldTypeDescription
idGUIDSystemId
codeTextResolution code
descriptionTextResolution code description

Fault/Resolution Relations (Page 56109)

Endpoint: /faultResolutionRelations Source Table: Fault/Resol. Cod. Relationship (5920)

FieldTypeDescription
idGUIDSystemId
faultAreaCodeTextFault area code
symptomCodeTextSymptom code
faultCodeTextFault code
resolutionCodeTextResolution code
serviceItemGroupCodeTextService item group code
descriptionTextRelationship description
occurrencesIntegerUsage count
createdManuallyBooleanWhether created manually vs. auto-generated

Fault Area/Symptom Relations (Page 56120)

Endpoint: /faultAreaSymptomRelations Source Table: INVC FA Symptom Code Relation (50113)

FieldTypeDescription
idGUIDSystemId
faultAreaTextFault area code
symptomCodeTextSymptom code

Posted Service Invoice Headers (Page 56123)

Endpoint: /postedServiceInvoiceHeaders Source Table: Service Invoice Header (5992)

FieldTypeDescription
idGUIDSystemId
noTextPosted invoice document number
customerNoTextCustomer number
orderNoTextOriginal service order number
orderDateDateOrder date
postingDateDatePosting date
locationCodeTextLocation code
csmQualitySentBooleanINVC CSM Quality Sent flag from BestwayUSA extension
fileUrlsTextComputed: JSON array of Link-type Record Link URLs attached to this invoice. Notes and other Record Link types are excluded. Format: [{"url":"https://...","type":"1"}]

Subpage (expandable via $expand):

  • postedServiceInvoiceLines — linked by Document No.

Posted Service Invoice Lines (Page 56121)

Endpoint: /postedServiceInvoiceLines Source Table: Service Invoice Line (5993)

FieldTypeDescription
idGUIDSystemId
documentNoTextPosted invoice document number
lineNoIntegerLine number
typeEnumLine type (Item, Resource, Cost, G/L Account)
noTextItem/resource/account number
descriptionTextLine description
description2TextLine description 2
quantityDecimalQuantity
unitPriceDecimalUnit price
lineAmountDecimalLine amount
customerNoTextCustomer number
orderNoTextOriginal service order number
postingDateDatePosting date
serviceItemNoTextService item number
serviceItemSerialNoTextService item serial number
itemCategoryCodeTextItem category code
faultAreaCodeTextFault area code
symptomCodeTextSymptom code
faultCodeTextFault code
resolutionCodeTextResolution code
faultReasonCodeTextFault reason code
bestwaySerialNoTextINVC Bestway Serial No.
faultCodeDescriptionTextINVC Fault Code Description
symptomCodeDescriptionTextINVC Symptom Code Description
faultAreaDescriptionTextINVC Fault Area Description
itemNoTextComputed: Item No. looked up from Service Item record
salesDateDateComputed: Sales Date looked up from Service Item record

Posted Service Shipment Lines (Page 56122)

Endpoint: /postedServiceShipmentLines Source Table: Service Shipment Line (5991)

FieldTypeDescription
idGUIDSystemId
documentNoTextPosted shipment document number
lineNoIntegerLine number
typeEnumLine type
noTextItem/resource/account number
descriptionTextLine description
description2TextLine description 2
quantityDecimalQuantity
customerNoTextCustomer number
orderNoTextOriginal service order number
postingDateDatePosting date
serviceItemNoTextService item number
serviceItemSerialNoTextService item serial number
itemCategoryCodeTextItem category code
faultAreaCodeTextFault area code
symptomCodeTextSymptom code
faultCodeTextFault code
resolutionCodeTextResolution code
faultReasonCodeTextFault reason code

OData Query Examples

All examples use the service orders endpoint. Replace {baseUrl} with your base URL.

Filter by order number:

GET {baseUrl}/serviceOrders?$filter=no eq 'SO-001234'

Filter by date range:

GET {baseUrl}/serviceOrders?$filter=orderDate ge 2024-01-01 and orderDate le 2024-12-31

Filter by customer:

GET {baseUrl}/serviceOrders?$filter=customerNo eq 'C00010'

Filter by CSM quality sent status:

GET {baseUrl}/serviceOrders?$filter=csmQualitySent eq false

Expand lines and attachments:

GET {baseUrl}/serviceOrders?$expand=serviceOrderLines,serviceOrderAttachments

Sort by order date (newest first):

GET {baseUrl}/serviceOrders?$orderby=orderDate desc

Get count with results:

GET {baseUrl}/serviceOrders?$count=true

Limit results:

GET {baseUrl}/serviceOrders?$top=10

Combined (filter + sort + count + expand):

GET {baseUrl}/serviceOrders?$filter=orderDate ge 2024-01-01&$orderby=orderDate desc&$count=true&$expand=serviceOrderLines,serviceOrderAttachments

Filter attachment lines by type:

GET {baseUrl}/serviceOrders({id})/serviceOrderAttachments?$filter=attachmentType eq 'DamagePhoto'

Postman Guide

A pre-built Postman collection is included at BestwayCSM.postman_collection.json.

Import the collection

  1. Open Postman and click Import.
  2. Select BestwayCSM.postman_collection.json.

Configure variables

Edit the collection variables (click the collection name → Variables tab):

VariableDescription
tenantIdYour Azure AD tenant ID (GUID)
companyIdBusiness Central company ID (GUID)
clientIdAzure AD app registration client ID
clientSecretAzure AD app registration client secret
serviceOrderIdA service order SystemId GUID (for single-record requests)
serviceOrderNoA service order number (for filter-based requests)

Configure authentication

The collection uses OAuth2 client credentials at the collection level. The token URL is:

https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token

With scope: https://api.businesscentral.dynamics.com/.default

To get a token: click the collection → Authorization tab → Get New Access TokenUse Token.

Run requests

The collection includes folders for:

  • Service Orders — all orders, single order by ID, filter by date/customer/quality-sent, sorting, pagination, expand lines/attachments
  • Service Order Lines — lines for a specific order, filter by fault area, count
  • Service Order Attachments — attachments for a specific order, filter by file type/extension/attachment type, count

Authentication

The API uses standard Business Central OData authentication. For external integrations, configure an Azure AD app registration with:

  • API permissions: Dynamics 365 Business CentralAPI.ReadWrite.All (or Financials.ReadWrite.All)
  • Client secret for server-to-server authentication
  • A BC user mapped to the app registration with appropriate Service Management permissions

Alternatively, use user-delegated OAuth2 flow for interactive/testing scenarios (e.g., Postman authorization code flow).

Development

Folder structure

AL source files are organized by object type:

bc-csm-api/
├── Codeunit/ Helper codeunits (CsmApiHelper)
├── Page/ API page objects (all 11 endpoints)
└── docs/ Changelog and change documents

Files follow the {Name}.{ObjectType}.al naming convention (e.g., ServiceOrderAPI.Page.al, CsmApiHelper.Codeunit.al).

Download symbols

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

Publish to sandbox

Press F5 or run AL: Publish to deploy to the configured sandbox environment (see .vscode/launch.json).

Package

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

Testing

Automated tests live in a separate extension at ../bc-csm-api-test/.

Test Object Allocation

Object IDTypeNameTests
56110CodeunitCSM API Test LibraryTest data helpers
56111CodeunitService Order API Test4 unit tests
56112CodeunitService Order Line API Test11 unit tests
56113CodeunitServ. Order Attach. API Test3 unit tests
56114CodeunitServ. Order API Func. Test2 functional tests
56115CodeunitPosted Inv. Header API Test6 unit tests

Test ID range 56110–56119 is reserved for the test extension. Next available: 56116.

Test categories

Unit tests (56111–56113): Exercise the CSM API Helper codeunit in isolation — computed field lookups, Base64 encoding, edge cases.

Functional tests (56114): Open the actual API pages via TestPage and verify end-to-end behavior:

  • Get Service Order by ID — creates a full order with line + attachment + lookup master data, navigates to the record, asserts all fields including computed values (csmQualitySent, itemNo, faultAreaDescription, etc.) and subpage content (lines, attachments with base64).
  • Get Service Orders (top 20 with expand) — creates 25 orders each with a line and attachment, iterates up to 20 records, verifies each has accessible line and attachment subpages.

Running tests

  1. Publish the main extension (bc-csm-api) to the sandbox.
  2. Open bc-csm-api-test in VS Code, run AL: Download Symbols, then AL: Publish.
  3. Navigate to the Test Tool page (130401) in the sandbox.
  4. Add the test codeunits (56111–56114) and run all tests.

All tests use BC's auto-rollback transaction model — inserted test data rolls back after each test.