This guide shows you how to connect Microsoft Dynamics 365 Business Central to API2Cart. Business Central supports two authentication methods, and the one you use depends on where the ERP runs. Therefore, start by choosing your deployment:

  • Business Central Online (SaaS) - OAuth 2.0 service-to-service (S2S) authentication through a Microsoft Entra application. This is the only supported option for *.dynamics.com environments, and it is described in detail below.
  • Business Central on-premises - Basic authentication with a Business Central user name and a web service access key.

API2Cart never asks a merchant to sign in interactively. The S2S flow runs entirely with an application identity. As a result, the integration keeps working without a user session, without MFA prompts and without a Business Central user license for the application.

You store the credentials once through the connection.add method, which returns a connection_key. After that, all further calls use that key.

What You Need Before You Connect Business Central to API2Cart

For Business Central Online you need:

  • An account in Microsoft Entra ID with permission to register applications and to grant admin consent for the tenant.
  • An administrator account in Business Central that can open the Microsoft Entra applications page.
  • The name of the Business Central environment you want to connect, for example production or sandbox.

For Business Central on-premises you need:

  • Business Central 18.0 or newer with API services enabled.
  • The server instance configured for NavUserPassword or AccessControlService authentication.
  • Network access from API2Cart to the Business Central OData/API port, which is 7048 by default, over HTTPS.

In both cases you also need an API2Cart account and its API key. The table below lists every credential that API2Cart stores, so the whole setup boils down to producing these values:

Parameter Business Central Online Business Central On-Premises Example
dynamics365bc_tenant_id Required - Microsoft Entra Directory (tenant) ID Required - Business Central tenant name 00001111-aaaa-2222-bbbb-3333cccc4444 / default
dynamics365bc_client_id Required - Application (client) ID Not used 11112222-bbbb-3333-cccc-4444dddd5555
dynamics365bc_client_secret Required - client secret value Not used A1b8Q~FaKeSecretVaLuE_1234567890abcdefghijk
dynamics365bc_environment Optional, defaults to production Not used production
dynamics365bc_api_url Not used Required - base URL of the server instance https://bc.example.com:7048/BC
dynamics365bc_username Not used Required ADMIN
dynamics365bc_password Not used Required - web service access key, or the user password on a NavUserPassword server P@ssw0rd

The two sets are mutually exclusive. Consequently, if dynamics365bc_api_url is sent together with dynamics365bc_client_id or dynamics365bc_client_secret, API2Cart rejects the request:

Parameter 'dynamics365bc_api_url' can't be used with parameter(s): 'dynamics365bc_client_id', 'dynamics365bc_client_secret'

Step 1: Register an Application in Microsoft Entra ID

First, sign in to the Microsoft Entra admin center and go to Entra ID → App registrations → New registration. Then fill in the registration form:

  • Enter a name for the application, for example API2Cart integration.
  • In Supported account types, select Single tenant only.
  • Leave Redirect URI empty. You only need it if you prefer to grant consent from the Business Central web client instead of the Entra admin center.
  • Select Register.

Finally, open the application Overview page and copy two values. The Application (client) ID becomes dynamics365bc_client_id, and the Directory (tenant) ID becomes dynamics365bc_tenant_id.

Step 2: Create a Client Secret

Next, open Certificates & secrets → Client secrets → New client secret. Add a description, choose an expiry period and confirm.

Copy the secret Value immediately, because Microsoft shows it only once. This value is dynamics365bc_client_secret.

Note the expiry date as well. When the secret expires, Business Central calls start failing with an authentication error. In that case, you have to update the connection with a new secret through connection.update.

Step 3: Grant the API Permission

Now open API permissions → Add a permission → Microsoft APIs → Dynamics 365 Business Central. Select Application permissions, select API.ReadWrite.All and confirm with Add permissions.

After that, select Grant admin consent for <tenant name> and confirm. Until consent is granted, the permission stays in the Not granted state, and every Business Central call returns an authentication error.

API2Cart requests the token scope https://api.businesscentral.dynamics.com/.default automatically. Therefore, there is nothing to configure for it.

Step 4: Register the Application Inside Business Central

Granting the Entra permission is only half of the setup. You must also enable the application in Business Central itself. Otherwise, Microsoft Entra issues the token successfully, but Business Central rejects every API call.

  • Sign in to Business Central, search for Microsoft Entra applications with Alt+Q and open the page.
  • Select New.
  • In Client ID, paste the Application (client) ID from Step 1.
  • Fill in Description, so that you can identify the application later.
  • Set State to Enabled.
  • Assign permission sets to the application. The permissions section below explains which objects the integration needs.

Keep in mind that the SUPER permission set cannot be assigned to an application. For this reason, assign a permission set that covers the objects the integration actually uses.

Step 5: Find the Environment Name

The environment name appears in the Business Central Admin Center on the Environments page, and in the web client URL right after /environmentName/. Common values are production and sandbox, however an environment can have any custom name.

Pass it in dynamics365bc_environment. If you omit the parameter, API2Cart uses production.

Step 6: Connect Microsoft Dynamics 365 Business Central to API2Cart

Then send the credentials to the connection.add method:

curl -X POST 'https://api.api2cart.com/accounting/v1/connection.add.json' \
-H 'x-api-key: <YOUR_API2CART_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
  "integration_id": "Dynamics365bc",
  "dynamics365bc_tenant_id": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "dynamics365bc_client_id": "11112222-bbbb-3333-cccc-4444dddd5555",
  "dynamics365bc_client_secret": "A1b8Q~FaKeSecretVaLuE_1234567890abcdefghijk",
  "dynamics365bc_environment": "production",
  "custom_label": "Contoso BC production"
}'

The response returns the key that every other method uses:

{"return_code": 0, "return_message": "", "result": {"connection_key": "641d2038c10588df0f8258ac3ee93536"}}

By default verify is true. As a result, API2Cart requests a token and reads the list of companies before it saves the connection, so invalid credentials are reported at this point instead of later. The custom_label parameter is optional and only sets a human-readable name for the connection.

Step 7: Verify the Connection

Finally, read the organisation list with the connection key:

curl 'https://api.api2cart.com/accounting/v1/organization.list.json?count=1' \
-H 'x-api-key: <YOUR_API2CART_API_KEY>' \
-H 'x-connection-key: <CONNECTION_KEY>'

Every Business Central company available to the application is returned as one organisation. The sample below is shortened, because the full response also carries contact_name, email, taxable, tax_number and the whole currency list:

{
  "return_code": 0,
  "return_message": "",
  "result": {
    "total_count": 2,
    "organizations": [
      {
        "id": "ce48dd11-ce79-f111-a5c3-7c1e523f94f7",
        "name": "CRONUS International Ltd.",
        "default": true,
        "legal_name": "CRONUS USA, Inc.",
        "is_active": true,
        "country_code": "US",
        "currencies": [{"id": "USD", "name": "US Dollar", "iso3": "USD", "default": true}]
      }
    ]
  }
}

The id of an organisation is the Business Central company ID. Methods that work with company-scoped data accept it in organization_id. When you omit the parameter, API2Cart uses the default company.

How to Connect Business Central On-Premises to API2Cart

Basic authentication is supported for on-premises deployments only. Microsoft deprecated it for Business Central online in October 2022, so it cannot be used against api.businesscentral.dynamics.com.

1. Enable API services on the server. Run the two commands below and restart the service instance:

Set-NAVServerConfiguration <instance> -KeyName ODataServicesEnabled -KeyValue true
Set-NAVServerConfiguration <instance> -KeyName ApiServicesEnabled -KeyValue true

Then open the API Setup page in Business Central and run Integrate APIs. Until you do this, API calls return HTTP 405.

2. Create the credentials. On the Users page, open the user that the integration will use and generate a Web Service Access Key. The user name becomes dynamics365bc_username, and the key becomes dynamics365bc_password. Microsoft’s documentation prescribes the key, because you can make it non-expiring and revoke it on its own. A server running in NavUserPassword mode also accepts the user’s own password in the same field, and this is how Docker and development containers are usually connected. On a production server, however, prefer the access key. Assign the user the permission sets listed in the permissions section below.

User names and passwords that contain non-ASCII characters cannot be used, because this is a limitation of HTTP Basic authentication.

3. Build the API URL and the tenant name. The dynamics365bc_api_url parameter is the base URL of the server instance, including scheme, host, port and instance name, for example https://bc.example.com:7048/BC. API2Cart appends the API path itself. The dynamics365bc_tenant_id parameter is the Business Central tenant name, and single-tenant or container deployments use default.

4. Create the connection.

curl -X POST 'https://api.api2cart.com/accounting/v1/connection.add.json' \
-H 'x-api-key: <YOUR_API2CART_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
  "integration_id": "Dynamics365bc",
  "dynamics365bc_api_url": "https://bc.example.com:7048/BC",
  "dynamics365bc_username": "ADMIN",
  "dynamics365bc_password": "P@ssw0rd",
  "dynamics365bc_tenant_id": "default"
}'

Verification works exactly as in Step 7 above.

Business Central Permissions Required by API2Cart

Permissions are set in two independent places, and both of them must be correct. First, Microsoft Entra decides whether the application may talk to Business Central at all:

API / Permission Name Type Microsoft Description Required by API2Cart
Dynamics 365 Business Central / API.ReadWrite.All Application Access to APIs and webservices Yes - required by every method that reads or writes Business Central data
Dynamics 365 Business Central / Automation.ReadWrite.All Application Full access to automation No - API2Cart does not call the automation APIs
Token scope https://api.businesscentral.dynamics.com/.default - Requested by API2Cart automatically Not configurable

Microsoft's own setup article asks for both permissions, because it also covers tenant provisioning through the automation APIs. API2Cart works only with the /api/v2.0 endpoints. Therefore, API.ReadWrite.All alone is enough.

Second, the permission set assigned to the Entra application, or to the integration user on-premises, must cover the Business Central API entities that the methods touch. In the standard Base Application, the broad business-data set is D365 BUS FULL ACCESS with the caption Dyn. 365 Full Business Acc. It includes D365 BASIC together with the banking, payables, receivables, inventory-document and setup sets. For a least-privilege setup, build a custom permission set from the objects behind the entities you actually call.

Data permissions are not the whole story, because the account must also be allowed to run the API pages themselves. If calls fail with Sorry, the current permissions prevented the action. (Page 30008 APIV2 - Items ...) while the same call works for an administrator, then the account is missing that entitlement rather than a data permission.


Table of Business Central Entities Used by API2Cart Methods

Below is the comprehensive list of Business Central API entities behind each API2Cart method. Use it as a checklist when you build a custom permission set. Read the table with these rules in mind:

  • Read access to companies is required by every method, because the company list is what resolves organization_id.
  • Entities marked with are read only on some requests, so a permission set without them still works. However, those requests end with a less specific error message.
  • connection.list, connection.delete and connection.supported_integrations work entirely inside API2Cart and need no Business Central permissions at all.
API2Cart Method Business Central Entities Read Business Central Entities Written
connection.add, connection.update, connection.validate companies -
organization.list companies, companyInformation, currencies, locations -
account.list accounts, bankAccounts -
account.add bankAccounts bankAccounts
account.update bankAccounts, accounts bankAccounts
account.delete bankAccounts, accounts bankAccounts
item.list items -
item.add unitsOfMeasure items
item.update items, unitsOfMeasure items
item.delete items items
tax.rate.list taxGroups -
contact.list customers, vendors -
contact.add, contact.update customers, vendors customers, vendors
contact.delete customers, vendors customers, vendors
bill.list purchaseInvoices, purchaseInvoiceLines, taxGroups -
bill.add, bill.update purchaseInvoices, purchaseInvoiceLines, vendors, items, accounts, taxGroups, customers †, bankAccounts purchaseInvoices, purchaseInvoiceLines
bill.payment.list vendorPaymentJournals, vendorPayments -
bill.payment.add vendorPaymentJournals, purchaseInvoices vendorPayments

The conditional reads marked with happen in these cases: unitsOfMeasure when Business Central rejects a measure unit, customers when the contact of a bill turns out to be a customer rather than a vendor, bankAccounts when a bill line points at an account that is not a general ledger account, and accounts when the id passed to an account method turns out to be a general ledger account.

How API2Cart Uses Your Business Central API Quota

Once you connect Microsoft Dynamics 365 Business Central to API2Cart, every unified call consumes a part of the merchant's Business Central quota. It is important to understand that one API2Cart request is not always one Business Central request. Under the hood, API2Cart may perform several native calls to build a unified response or to validate the input data. For example, organization.list reads the company list once, and then it reads company information, currencies and locations for each company. Similarly, bill.list reads purchase invoices with their lines expanded, plus the tax group list.

Business Central Online applies the following limits per service principal:

Limit Value
Requests 6,000 per 5-minute sliding window
Concurrently processed requests 5
Simultaneous connections 100
Queued requests 95

On top of that, each environment allows 600 requests per minute for production and 300 for sandbox environments, a maximum page size of 20,000 records and an 8-minute operation timeout.

When Business Central answers with HTTP 429, API2Cart waits for the period given in the Retry-After header and repeats the request up to three times. If the limit is still exceeded, the call returns a "too many requests" error, so you should retry it later. Business Central has no daily quota, so the limits that a bulk import hits first are the 5-minute window and the per-minute environment limit. Plan bulk request throughput with enough headroom for them.

Managing the Connection

After you connect Business Central to API2Cart, you manage the connection with four methods:

Action Method
Update credentials, for example after a client secret is rotated connection.update
List the connections of the account connection.list
Check that stored credentials still work connection.validate
Remove the connection connection.delete

The connection.update method accepts the same credential parameters and keeps the same connection_key. Therefore, nothing has to change on your side after a secret rotation.

Troubleshooting

Most problems appear right after you connect Microsoft Dynamics 365 Business Central to API2Cart, and they usually come from a handful of causes. Therefore, check these first:

Message or Symptom Cause What to Do
Some parameters are invalid! Please check your 'dynamics365bc_client_id' and 'dynamics365bc_client_secret'. Microsoft Entra rejected the application credentials: wrong client ID, wrong secret, or the secret has expired Re-copy the Application (client) ID, create a new client secret and call connection.update
Failed to obtain access token. Microsoft Entra Error: ... The token request failed for another reason, most often a wrong tenant ID Check Directory (tenant) ID on the application Overview page; the quoted AADSTS code identifies the exact cause
Invalid credentials specified or the application is not authorized in Business Central. The token is valid, but Business Central rejected it: the application is missing from the Microsoft Entra applications page, its State is not Enabled, or admin consent was not granted Complete Step 3 and Step 4
No companies are available for the specified Business Central credentials. The application authenticated, but it sees no company. Business Central answers an unpermitted account with an empty company list rather than an error, so this is what a missing permission set looks like Assign permission sets to the application; if a permission set was assigned for one company only, make sure it is the company you need
Business Central API Error: Sorry, the current permissions prevented the action. (Page 30008 APIV2 - Items ...) The account may read the data, but it is not allowed to run the API pages Compare with an administrator account: if the same call works there, the integration account is missing the API entitlement, not a data permission
API services are disabled on the Business Central server. On-premises only: OData/API services are turned off, or Integrate APIs was never run Complete step 1 of the on-premises section
Unable to connect to the Business Central server. Make sure the API URL is correct and the server is reachable. On-premises only: wrong host, port or instance name in dynamics365bc_api_url, or the port is not reachable from outside Verify the URL in a browser and open the port for API2Cart
Parameter 'dynamics365bc_api_url' can't be used with parameter(s): 'dynamics365bc_client_id', 'dynamics365bc_client_secret' Online and on-premises credentials were sent in one request Send only the set that matches your deployment
Business Central API Error: Account Type must be equal to 'Posting' in G/L Account: No.=10000. Current value is 'Heading'. A bill line points at a general ledger account that cannot be posted to. Headings and totals structure the chart of accounts, and they are not postable accounts account.list returns ledger_account_type in additional_fields - pick an account whose value is Posting; Heading, Total, Begin-Total and End-Total accounts are rejected by Business Central
Business Central does not allow modifying or deleting general ledger accounts through its API. Only accounts with type 'bank' can be changed. account.update or account.delete was called with a general ledger account. The chart of accounts is maintained inside Business Central and is read-only over the API Change only accounts whose type is bank in account.list; general ledger accounts are exported for reading and for use as bill line accounts
Business Central API Error: ... Business Central rejected the operation itself, for example because of a posting rule or a blocked record The quoted message comes from Business Central and describes the business rule that was violated
Calls worked and then started failing with an authentication error The client secret expired Create a new secret and call connection.update