Integrating Python with Microsoft Dynamics 365 Business Central
Learn how to connect Python with Microsoft Dynamics 365 Business Central using OData and REST APIs for automation, data retrieval, and ERP integration.
Microsoft Dynamics 365 Business Central (BC) is a powerful ERP system that allows API-based integration. This guide will help you connect Business Central with Python using OData and REST APIs, covering authentication, data retrieval, and automation.
1. Understanding Business Central APIs
Business Central provides two main APIs:
- OData V4 API – For querying and interacting with ERP data.
- REST API – For interacting with Business Central web services.
Both require authentication, typically using OAuth2 or Basic Authentication (for on-premises setups).
2. Authentication: Getting Access to Business Central
Option 1: OAuth2 Authentication (Cloud BC - Recommended)
OAuth2 is the preferred method for Business Central Online (SaaS).
Step 1: Register an Azure App
- Go to Azure Portal → App registrations.
- Register a new app and note the Client ID and Tenant ID.
- Generate a Client Secret under “Certificates & secrets”.
- Assign API permissions for Business Central.
Step 2: Get an Access Token Using Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
TENANT_ID = "your-tenant-id"
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
SCOPE = "https://api.businesscentral.dynamics.com/.default"
TOKEN_URL = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"
payload = {
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"scope": SCOPE,
}
response = requests.post(TOKEN_URL, data=payload)
token = response.json().get("access_token")
print("Access Token:", token)
Option 2: Basic Authentication (On-Premises BC Only)
For Business Central On-Premises, use Basic Authentication with a Web Service Access Key.
1
2
3
4
5
6
from requests.auth import HTTPBasicAuth
USER = "your-username"
PASSWORD = "your-web-service-access-key"
auth = HTTPBasicAuth(USER, PASSWORD)
3. Fetching Data from Business Central API
Once authenticated, we can query the Business Central OData API.
Example: Retrieve Customer Data
1
2
3
4
5
6
7
8
9
10
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}
URL = "https://api.businesscentral.dynamics.com/v2.0/{tenant_id}/sandbox/ODataV4/Company('CRONUS')/Customers"
response = requests.get(URL, headers=headers)
if response.status_code == 200:
customers = response.json()
print(customers)
else:
print(f"Error: {response.status_code}, {response.text}")
4. Creating Records in Business Central
We can send a POST request to create new records.
1
2
3
4
5
6
7
8
9
10
11
12
13
customer_data = {
"Name": "Skewed Monk Ltd.",
"Address": "Kathmandu, Nepal",
"City": "Kathmandu",
"PhoneNo": "9800000000",
}
response = requests.post(URL, headers=headers, json=customer_data)
if response.status_code == 201:
print("Customer created successfully.")
else:
print(f"Error: {response.status_code}, {response.text}")
5. Updating and Deleting Records
Update an Existing Customer
1
2
3
4
5
6
7
8
9
10
11
customer_id = "123456" # Replace with actual Customer ID
update_url = f"{URL}('{customer_id}')"
update_data = {"City": "Pokhara"} # Updating the city
response = requests.patch(update_url, headers=headers, json=update_data)
if response.status_code == 204:
print("Customer updated successfully.")
else:
print(f"Error: {response.status_code}, {response.text}")
Delete a Customer Record
1
2
3
4
5
6
7
delete_url = f"{URL}('{customer_id}')"
response = requests.delete(delete_url, headers=headers)
if response.status_code == 204:
print("Customer deleted successfully.")
else:
print(f"Error: {response.status_code}, {response.text}")
6. Automating ERP Integration
We can automate API calls using cron jobs (Linux) or Task Scheduler (Windows).
Example: Automating Data Sync
Create a Python script (sync_customers.py
) and schedule it to run every night.
1
2
3
4
5
6
7
8
9
10
11
12
13
import time
def fetch_data_with_retry(url, headers, retries=3, delay=5):
for i in range(retries):
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
else:
print(f"Attempt {i+1} failed: {response.status_code}")
time.sleep(delay)
return None
customers = fetch_data_with_retry(URL, headers)
Linux (cron job example):
1
0 2 * * * /usr/bin/python3 /path/to/sync_customers.py
Windows (Task Scheduler example):
- Create a new task
- Set the trigger: Daily at 2 AM
- Set the action: Run python sync_customers.py
7. Handling Common API Issues
1. Rate Limits & Retry Strategy
ERP APIs may throttle requests if you exceed the limit. Implement exponential backoff.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import time
def api_call_with_backoff(url, headers, retries=3):
delay = 2
for i in range(retries):
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
elif response.status_code == 429: # Too many requests
print(f"Rate limit hit, retrying in {delay} seconds...")
time.sleep(delay)
delay *= 2
else:
break
return None
2. Authentication Expiry
OAuth tokens expire after some time. Implement a token refresh mechanism.
8. Business Use Cases for Python-ERP Integration
Python can be used to automate several ERP-related tasks:
Use Case | Implementation |
---|---|
Customer & Vendor Sync | Fetch/update customers & vendors from BC |
Order Processing | Automate sales order creation |
Inventory Management | Update stock levels dynamically |
Payment Gateway Integration | Sync payments with Business Central |
Report Generation & Email Alerts | Generate automated sales reports |
Conclusion
Integrating Python with Business Central allows for automation, real-time data exchange, and enhanced ERP functionality. We explored authentication, data retrieval, record creation, updates, and automation.