Microsoft Business Central API
This guide explains how to use API to establish a direct, secure connection to SOLSOL Microsoft Dynamics 365 Business Central environment, allowing authorized 3rd parties to read master data for products, units of measure, and commercial terms.
Gemini said
Fair Usage & Access Policy
To ensure the performance, security, and availability of the SOLSOL Dynamics 365 API for all users, we implement a Fair Usage Policy. By using this API, you agree to the following terms:
1. Rate Limiting & Resource Usage
The API is intended for efficient data synchronization. Users are expected to optimize their requests by using OData filters (e.g., ?$filter=...) to minimize server load.
-
Excessive Polling: Repetitive, high-frequency "polling" for data that has not changed is discouraged.
-
Throttling: We reserve the right to throttle or temporarily limit requests from any Client ID that consistently exceeds reasonable volume thresholds or impacts the performance of the Business Central environment.
2. Security & Unauthorized Access
Data integrity and privacy are our highest priorities.
-
Scope of Access: You may only access endpoints and data fields explicitly granted to your API credentials.
-
Prohibited Actions: Any attempt to bypass security layers, perform "brute force" discovery of undocumented endpoints, or extract data outside of your authorized scope is strictly prohibited.
3. Right to Revoke Access
SOLSOL reserves the right to immediately suspend or permanently revoke API access (including Client IDs and Secrets) without prior notice for any entity found to be:
-
Engaging in malicious activity or "stress-testing" the production environment.
-
Attempting to access unauthorized datasets.
-
Sharing API credentials with unauthorized third parties.
-
Violating the technical guidelines outlined in this documentation.
1. Authentication
Access is managed via OAuth 2.0 Client Credentials Flow. You must request a Bearer Token before making any data calls.
1. Token Request
[POST] https://login.microsoftonline.com/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/oauth2/v2.0/tokenRequest Body Params:
- client_id
Provided upon request - grant_type
client_credentials - client_secret
Provided upon request - scope
https://api.businesscentral.dynamics.com/.default
Note: The token is valid for 3600 seconds (1 hour). We recommend caching the token and only refreshing it upon expiration or a 401 Unauthorized response.
Example of valid response (200 OK):
{ "token_type": "Bearer", "expires_in": 3599, "ext_expires_in": 3599, "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlBjWDk4R1g0MjBUMVg2c0JEa3poUW1xZ3dNVSIsImtpZCI6IlBjWDk4R1g0MjBUMVg2c0JEa3poUW1xZ3dNVSJ9.eyJhdWQiOiJodHRwczovL2FwaS5idXNpbmVzc2NlbnRyYWwuZHluYW1pY3MuY29tIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZDE4YzJiMzMtZGM4OC00YzA2LWI3MWMtNjdhN2JhM2Q4M2ZlLyIsImlhdCI6MTc2ODk5NDM2NywibmJmIjoxNzY4OTk0MzY3LCJleHAiOjE3Njg5OTgyNjcsImFpbyI6ImsyWmdZSGoza0hsTG12Z2xpNFdpZkI4T1RIMFhCUUE9IiwiYXBwaWQiOiIzYTMwOWE2NS00NmEwLTQ2YjUtODRiNy1hYmExMjI0YjRiMjgiLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9kMThjMmIzMy1kYzg4LTRjMDYtYjcxYy02N2E3YmEzZDgzZmUvIiwiaWR0eXAiOiJhcHAiLCJvaWQiOiIyYmUwYzk2Mi02MWU3LTRlMTYtYWI0MS1jMGM3YTZlMmI1OTkiLCJyaCI6IjEuQVJBQU15dU0wWWpjQmt5M0hHZW51ajJEX2ozdmJabHNzMU5CaGdlbV9Ud0J1SjlMQVFBUUFBLiIsInJvbGVzIjpbIkFQSS5SZWFkV3JpdGUuQWxsIl0sInN1YiI6IjJiZTBjOTYyLTYxZTctNGUxNi1hYjQxLWMwYzdhNmUyYjU5OSIsInRpZCI6ImQxOGMyYjMzLWRjODgtNGMwNi1iNzFjLTY3YTdiYTNkODNmZSIsInV0aSI6InZqdy01RkhjYVVxNUV3UlloM2gwQUEiLCJ2ZXIiOiIxLjAiLCJ4bXNfYWN0X2ZjdCI6IjkgMyIsInhtc19mdGQiOiJLWW9BUXlmTzBHaGp5d3N5bmRjb1Z1VzAxZlZscTI4eHJSNFNEcjlPYUl3QmMzZGxaR1Z1WXkxa2MyMXoiLCJ4bXNfaWRyZWwiOiI3IDMwIiwieG1zX3JkIjoiMC40MkxsWUJKaUZCQVM0V0FYRXVDbzRuRm1ZaWx5bk10OEsySEM5c2kzUUZGT0lZRmdWOGIxaHFlelhlZXNzdm15NHFURmM2QW9oNUNBN2Z2Y21UbWJneDNiMkpmOXRXSGNNUjhBIiwieG1zX3N1Yl9mY3QiOiIzIDkifQ.GYBvO1R9-QQ9VJzoz4q_HaOYm8W0SsaK_bnhN6MoCx19S2oervAK6qFvDKgn01oF-fV1BPMiqFDfuK6WTQBq-BlR-FfxzskzBnskwsJdCVHyVKt_UW9l9FoX7iiAlkOPB7pcizOVKHq5MZC92VGocd20gp7S1sKymCD1ugWkwn0PYE6aIBP2EleQ3MAT3mPpihQ286F9X6CfR9AC-uMbqPu6ozD0bFOvzsbIWhEkw7CiZjch_HJZkpd-28R3CPo18vMNbru-cygLGiIsWEPSIt8l0e7diFW7CK1Mqf7cKoooh5EGTc49mpqKYZP9Axa-i0YsWP_poDdMyDNiTBoDAg" }
2. Global Headers
Every data request must include the following header:
2. Product & Inventory Endpoints
A.1. Retrieve Item List
Returns a high-level list of all products available for the specified company. It includes item's category, technical specifications, and commercial constraints.
[GET] https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/items
Pay attention to attribute "purchasingBlocked". If value is set to “true” then the selling of such item has been stopped.
B.2. Retrieve Prices
To obtain prices from one specific price list, use filter on parameter validForCode.
Example for price list “VIP AJ”:
[GET] https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/salesPrices?$filter=validForCode eq 'VIP AJ'
Pricing Data Structure
The SalesPrices endpoint returns an array of objects representing a specific price point valid under a unique set of conditions. To resolve the "actual" price for a customer, the consuming application must filter the results based on the hierarchy of Currency, Price List, and Volume Tiers.
Primary Key Attributes
To identify the correct price record, evaluate these attributes in order:
|
Attribute |
Logic / Description |
|
|
The currency of the transaction. Note: If this field is empty ( |
|
|
The Price List or Customer Group (e.g., |
|
|
The threshold for volume-based pricing. The applicable price is the one where the purchase quantity is >= |
|
|
The unit of measure (e.g., |
Volume Tiering Logic
The endpoint provides "Step Pricing." For a single currency and price list, multiple records will exist with different minQuantity values.
Example for Product 128453 (EUR):
-
Tier 1: 0–35 units -> 57.33 EUR (
minQuantity: 0) -
Tier 2: 36–935 units -> 52.78 EUR (
minQuantity: 36) -
Tier 3: 936+ units → 50.51 EUR (
minQuantity: 936)
Implementation Note: Always sort the filtered results by
minQuantityin descending order. The first record wherePurchaseQuantity >= minQuantityis the applicable price.
Field Mapping Reference
-
unitPrice: The net price per unit (excluding VAT). -
unitPriceInclVat: The gross price per unit (including VAT).
Quick Filter Cheat Sheet (Example)
If you need the price for a VIP AJ customer buying 50 units in Czech Koruna:
-
Filter
validForCode == "VIP AJ" -
Filter
currency == ""(Empty string = CZK) -
Find the highest
minQuantitythat is =< 50 (In this case, the record withminQuantity: 36). -
Result:
unitPrice: 1313.166
C.3. Retrieve Product Translations
To pull translations of product descriptions, use the /ItemTranslations endpoint
[GET] https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/ItemTranslations
To pull product descriptions just for one specific PLU, use the $filteroperator on itemNumber. API may return multiple objects for a single item to support multi-language variations.
[GET] https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/ItemTranslations?$filter=itemNumber eq '104403'
-
Marketing Content: The primary commercial description for e-shop is located in the
marketingTextfield. -
Short Descriptions: Use the
descriptionfield for the technical product name/title (e.g., "FV panel Canadian Solar...")
Note: If marketingText is empty for a specific item, we recommend falling back to the description field as a secondary title.
D.4. Retrieve SellingProduct Units
Descriptions
To pull detailed descriptions and unit-of-measure data,descriptions, use the /ItemTranslations endpoint with following parameter endpoint.?$expand=itemUnits
Method: HTTP GET
Request URL: [GET] https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies({{CompanyID}}e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/ItemTranslations
If you want to retrieve product description for a single item, use the itemNumber filter.
Example URL: https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/ItemTranslations?$filter=itemNumber eq '{{item_number}}'
Returns a list of products including their core metadata and a detailed breakdown of available selling units. This endpoint iswill essentialreturn foran determiningEnglish, howGerman, aPolish and Czech translations of product candescription. be ordered—whether as individual pieces, full palettes, or shipping containers.
Each item defines a Base Unit (typically pieces), while the expanded itemUnits collection provides the conversion logic and physical dimensions for alternative packaging options.
|
Field |
Description |
|
|
|
|
|
|
|
|
|
|
E.5. Retrieve Stock availabilities
To check how many units are available for sale, use the /items endpoint with parameter $expand=itemAvailability . This provides stock availability across all our warehouses grouped by logical regions.
Method: HTTP GET
Request URL: GEThttps://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/items?$expand=itemAvailability
https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/items?$expand=itemAvailability&$filter=itemNumber eq '104500'
{
"@odata.context": "https://api.businesscentral.dynamics.com/v2.0/d18c2b33-dc88-4c06-b71c-67a7ba3d83fe/PRODUCTION/api/autocont/eshop/v2.0/$metadata#companies(e5de3ad7-17fe-ed11-8f6e-000d3abde3ea)/itemAvailability",
"value": [
{
"@odata.etag": "W/\"JzIwOzEzMjYyODQ1ODQ1ODY5ODUwOTg4MTswMDsn\"",
"warehouseGroupId": "1",
"warehouseGroupName": "CZ",
"itemNumber": "104500",
"unit": "KS",
"quantityOnStock": 513,
"quantityAvailable": -371.00000
},
{
"@odata.etag": "W/\"JzE5OzIxOTI3MjcyNjkxMzc1ODkwNTExOzAwOyc=\"",
"warehouseGroupId": "2",
"warehouseGroupName": "NL",
"itemNumber": "104500",
"unit": "KS",
"quantityOnStock": 0,
"quantityAvailable": 0
},
{
"@odata.etag": "W/\"JzE5OzUwODIwNDA1MjU3ODY3ODM4NTExOzAwOyc=\"",
"warehouseGroupId": "3",
"warehouseGroupName": "CESTA",
"itemNumber": "104500",
"unit": "KS",
"quantityOnStock": 0,
"quantityAvailable": 0
}
]
}
|
Field |
Description |
|---|---|
|
|
The geographical or logical region (e.g., ! Only use stock quantities where |
|
|
Total physical units currently located in that region. |
|
|
The "Sellable" Quantity: Total physical units minus existing reservations. |