Seamless Integration of Microsoft Dynamics 365 Business Central with Django

Vinod Charan Kumar

25.jpg

Microsoft Dynamics 365 Business Central is an all-in-one enterprise resource planning (ERP) solution designed to help small and medium-sized businesses manage their operations efficiently. It’s part of the Microsoft Dynamics 365 family, a suite of business applications, but Business Central specifically focuses on integrating core business functions into a unified platform. Think of it as a digital hub that connects finance, sales, customer service, supply chain, and operations, reducing silos and manual work while giving businesses real-time visibility into their performance.

Core Components and Functionality

  1. Financial Management: This is the backbone for many users. It handles general ledger, budgeting, cash flow forecasting, accounts payable and receivable, fixed assets, and bank reconciliation. It supports multi-currency transactions and tax compliance, making it adaptable for businesses operating globally.
  2. Supply Chain Management: This covers inventory tracking, warehouse management, purchase orders, and sales order processing. It helps optimize stock levels, manage vendor relationships, and ensure timely delivery to customers.
  3. Sales and Customer Management: Built-in CRM (Customer Relationship Management) tools let you track customer interactions, manage sales pipelines, and create quotes or invoices. It syncs with Outlook for seamless communication.
  4. Project Management: Ideal for service-based or project-driven businesses, it allows you to plan projects, allocate resources, track time, and monitor profitability—all within the same system.
  5. Manufacturing and Operations: For companies that produce goods, it offers production planning, bill of materials (BOM), and capacity management. It’s not as robust as specialized manufacturing ERPs but works well for light assembly or make-to-order scenarios.
  6. Reporting and Analytics: Powered by integration with Power BI, it provides customizable dashboards and real-time insights. You can drill down into data—like sales trends or cash flow—without needing a separate tool.

Integrating Microsoft Dynamics 365 Business Central with Django can offer several benefits, depending on your business needs. Here’s why you might want to do it:

1. Centralized Data Management

  • ERPs manage core business data such as finance, HR, procurement, inventory, etc.
  • Django can serve as an intermediary, synchronizing data between the ERP and other platforms.
  • Reduces data duplication and inconsistencies across multiple systems.

2. Automation of Business Processes

Instead of manually updating Business Central records, Django can automate tasks like:

  • Syncing inventory data
  • Processing orders
  • Generating invoices e.t.c

3. Custom Web & Mobile Applications

  • ERP UIs are often complex and rigid.
  • Django allows you to create custom web dashboards and mobile-friendly apps using Ionic, React, or Angular.
  • Example: A warehouse management system pulling data from ERP and showing real-time stock levels in a Django-based dashboard.

4. Data Reporting & Analysis

Django can extract and store Business Central data for:

  • Advanced reporting (using Django + Pandas, Matplotlib, or Power BI)
  • Custom analytics dashboards
  • Machine learning models for business insights

Integration with Other Services

Django can act as a bridge between Business Central and other services, such as:

  • AWS S3 for storing invoices and documents
  • Payment Gateways (Stripe, Razorpay) for automated billing
  • E-commerce Platforms (Shopify, WooCommerce) for inventory sync
  • CRM Systems (Salesforce, HubSpot) for customer data
  • BI & Reporting Tools (Power BI, Pandas, Matplotlib) for analytics
  •  

Use Case: Why We Integrated Business Central

Our application needed to communicate with Business Central to:

  • Fetch warehouse shipments
  • Get and update pick details
  • Register shipment picks
  • Post warehouse shipments

We wanted all of this to be configurable through the Admin panel without changing code.

High-Level Design Overview

Our goal is to create a flexible and reusable integration system within Django that:

  • Manages and stores Business Central API credentials and configurations.
  • Authenticates using OAuth2 and refreshes tokens when needed.
  • Makes dynamic API calls to Business Central endpoints.

We built a Django model called AppIntegration to store:

  • OAuth credentials (Client ID, Secret, Tenant ID)
  • Base API URL and environment identifiers
  • Access/Refresh tokens
  • List of API endpoints and HTTP methods

Everything is dynamic and editable.This allows you to store and manage APIs dynamically from the UI without changing code.

This screen is the central control panel for configuring and managing the integration between your platform and Microsoft Dynamics 365 Business Central. It offers complete flexibility for setting up API access, authorizing OAuth2 tokens, and managing dynamic API endpoints.

Screenshot from 2025 05 05 14 27 33.png

1. Integration Information Section

Screenshot from 2025 05 05 14 42 38.png
  • Enter the name of the integration, e.g., Microsoft Business Central.

  • Provide the Base URL for the Business Central API.

  • Define the API version used by both Business Central and your own app.

  • Fill in Tenant ID, Database Name, and Company details for Business Central multi-tenant configuration.

  • Enter OAuth2 credentials like Client ID and Client Secret.

  • Set a Redirect URI that the Microsoft OAuth system will call back after authentication.

2. OAuth2 Authorization Section

Screenshot from 2025 05 05 14 43 31.png
  • A “Authorize” button initiates Microsoft login to generate the token.

  • A status indicator shows whether the token is currently valid.

  • The “Deauthorize” button revokes the token and clears the session.

  • This section connects to Microsoft’s identity system to handle secure token management.

  • As shown in the screenshot, a popup window allows the user to log in using Microsoft credentials.
Screenshot from 2025 05 05 14 28 59.png

3. API Configuration Section

Screenshot from 2025 05 05 14 41 48.png

This section is fully dynamic and allows users to configure multiple APIs:

  • Add a custom code to identify the API (e.g., GET_SALES_ORDER_NOS).

  • Define a user-friendly name for each API (e.g., “Get Sales Order Number”).

  • Choose the HTTP method (GET or POST).

  • Enter the API URI relative to the base URL (e.g., GetNextSalesOrderNo).

  • Enable or disable each API using the “API Enabled”

  • APIs can be updated, or deleted dynamically without touching backend code.

Here’s how the flow works:

  1. Admin sets up credentials + API metadata.
  2. Django app fetches/stores tokens with expiry handling.
  3. Each API call is constructed dynamically using stored metadata.
  4. If a token has expired, it auto-refreshes before retrying.

The AppIntegration Model

class AppIntegration(SembaModel):

    code = models.CharField(max_length=50, unique=True)

    name = models.CharField(max_length=100)

    is_valid_auth = models.BooleanField(default=False)

    auth_details = JSONField(blank=True, null=True)

    api_details = JSONField(blank=True, null=True)

    …. other required fields

 

auth_details holds everything for authentication:

{

  “client_id”: “…”,

  “client_secret”: “…”,

  “access_token_details”: {

    “access_token”: “…”,

    “refresh_token”: “…”,

    “expires_in”: 3600

  },

  “tenant_id”: “…”,

  “token_url”: “…”,

  “resource_url”: “…”,

  “scope”: “…”

}

api_details includes custom API endpoints:

[

  {

    “is_enabled”:true,

    “api_url”:”GetNextSalesOrderNo”,

    “code”:”GET_SALES_ORDER_NOS”,

    “name”:”Get Sales Order Number”,

    “method”:”POST”

  },

  {

    “is_enabled”:true,

    “api_url”:”GetWhseShipmentList”,

    “code”:”GET_WHSE_SHPT_LINES”,

    “name”:”Get Warehouse Shipment Lines”,

    “method”:”POST”

  }

]

This allows us to add/edit endpoints on the fly without any code changes.

Encrypt auth_details and api_details if stored as plain JSON in DB.

Token Handling and Auto-Refresh

We check token validity before every request. If the token has expired, we refresh it automatically using the refresh token.

def refresh_access_token(app_integration_obj):

    payload = {

        “client_id”: …,

        “client_secret”: …,

        “grant_type”: “refresh_token”,

        “refresh_token”: …,

        “scope”: …

    }

    response = requests.post(token_url, data=payload)

    if response.status_code == 200:

        app_integration_obj.auth_details[“access_token_details”] = response.json()

        app_integration_obj.is_valid_auth = True

        app_integration_obj.save()

This means we never need to re-authenticate manually once the initial setup is done.

Making API Requests the Smart Way

We created a generic method to make API calls based on the stored metadata:

def process_api_request(url, method, access_token, payload):

    headers = {

        “Authorization”: f”Bearer {access_token}”,

        “Content-Type”: “application/json”

    }

    response = requests.request(method, url, headers=headers, json=payload)   

    if response.status_code == 401:

        # Token might be expired. Try refreshing it.

        new_token = refresh_access_token(…)

        return process_api_request(url, method, new_token, payload)

    return response

Constructing the API URLs

Business Central APIs have a specific structure:

https://<resource_url>/<api_version>/<environment>/<tenant>/<endpoint>?Company=<company_name>

We dynamically construct this in code:

def construct_api_url(auth_details, entity_set_name):

    return f”{auth_details[‘resource_url’]}/{auth_details[‘api_version’]}/{auth_details[‘environment’]}/{auth_details[‘tenant’]}/APICodeunits_{entity_set_name}?Company={auth_details[‘company’]}”

Real-Life API Methods

Each use case maps to a method in our AppIntegrations class:

class AppIntegrations:

    @classmethod

    def get_warehouse_shipment_list(cls, payload):

        return cls.execute_bc_api(“get_warehouse_shipment_list”, payload)

    @classmethod

    def execute_bc_api(cls, api_key, payload):

        …

        url = construct_api_url(auth_details, api_code)

        return process_api_request(url, http_method, token, payload)

This modular design allows adding new API actions in minutes.

Admin Panel View

Here’s what our admin panel looks like:

  • API Details
    • API Code: GetWhseShipmentList
    • Method: POST
    • Enabled: true

  • OAuth Info
    • Client ID & Secret
    • Tenant ID
    • Refresh Token & Access Token (auto-updated)

  • Environment Info
    • Base API URL
    • Company ID
    • API Version
    • Environment (Sandbox/Production)

This interface is so flexible that non-developers can update credentials or add APIs.

Key Benefits

  • No code changes needed to add new BC APIs
  • Automatic token refresh avoids manual headaches
  • Centralized admin panel for full control
  • Reusable, modular code structure for any ERP/REST API

Read More Articles

Serverless application
AWS Serverless

Serverless Application

Serverless architecture is a software design pattern where applications’ hosting is outsourced to a third-party service provider, eliminating the developer’s need for server software and

 Contact Us Now

Talk to us to find out about our flexible engagement models.

Get In Touch With Us