On this page:
3.1 Understanding the authentication flow
3.2 Creating an Azure AD app registration
3.2.1 Step 1:   Access the Azure Portal
3.2.2 Step 2:   Navigate to App registrations
3.2.3 Step 3:   Configure basic settings
3.2.4 Step 4:   Note your IDs
3.2.5 Step 5:   Create a client secret
3.2.6 Step 6:   Configure API permissions
3.3 Finding your Business Central company ID
3.4 Understanding Racket parameters
3.5 Storing credentials securely
3.5.1 Environment variables (recommended)
3.5.2 Separate configuration file
3.6 Authenticating with client credentials
3.7 Interactive authentication
3.8 Checking authentication status
3.9 Troubleshooting
3.9.1 AADSTS700016:   Application not found
3.9.2 AADSTS7000218:   Request body must contain client_  secret
3.9.3 401 Unauthorized from Business Central
3.10 Next steps
9.3

3 Setup & Authentication🔗

Before you can use bcnav to access Business Central, you need to set up authentication through Azure Active Directory (now called Microsoft Entra ID). This involves creating an "app registration" in Azure that represents your bcnav client.

This tutorial walks through the setup process step by step.

3.1 Understanding the authentication flow🔗

Business Central’s API uses OAuth 2.0 for authentication. Here’s what happens when you call bc-authenticate!:

  1. bcnav sends your client ID and secret to Microsoft’s authentication servers

  2. Microsoft verifies the credentials and returns an access token

  3. bcnav stores this token and includes it in all subsequent API requests

  4. When the token expires (typically after an hour), bcnav handles refresh automatically

For this to work, you need credentials from an Azure AD app registration.

3.2 Creating an Azure AD app registration🔗

3.2.1 Step 1: Access the Azure Portal🔗

Go to portal.azure.com and sign in with an account that has permission to create app registrations in your Azure AD tenant.

3.2.2 Step 2: Navigate to App registrations🔗

In the portal:

  1. Search for "Microsoft Entra ID" (or "Azure Active Directory") in the top search bar

  2. Select App registrations from the left menu

  3. Click New registration

3.2.3 Step 3: Configure basic settings🔗

Fill in the registration form:

  • Name: Something descriptive like "bcnav Client" or "BC API Access"

  • Supported account types: Choose based on your needs:
    • Single tenant Only users in your organization (most common)

    • Multitenant Users in any Azure AD organization

  • Redirect URI: Leave blank for now (only needed for interactive authentication)

Click Register.

3.2.4 Step 4: Note your IDs🔗

After registration, you’ll see an overview page. Copy these values—you’ll need them for bcnav:

  • Application (client) ID: A GUID like a1b2c3d4-e5f6-7890-abcd-ef1234567890

  • Directory (tenant) ID: Another GUID, or you can use your domain like contoso.onmicrosoft.com

3.2.5 Step 5: Create a client secret🔗

For automated (non-interactive) authentication, you need a client secret:

  1. In your app registration, go to Certificates & secrets

  2. Click New client secret

  3. Add a description (e.g., "bcnav access") and choose an expiration period

  4. Click Add

  5. Immediately copy the secret valueit won’t be shown again!

3.2.6 Step 6: Configure API permissions🔗

Your app needs permission to access the Business Central API:

  1. Go to API permissions

  2. Click Add a permission

  3. Select Dynamics 365 Business Central

  4. Choose Application permissions (for client credentials flow)

  5. Select API.ReadWrite.All or the specific permissions you need

  6. Click Add permissions

  7. Click Grant admin consent for [your organization]

The admin consent step is required for application permissions to take effect.

3.3 Finding your Business Central company ID🔗

BC’s API requires a company ID to know which company’s data you’re accessing. To find it:

  1. Open Business Central in your browser

  2. Use the search (Alt+Q) to open Companies

  3. The company ID appears in the URL, or you can find it programmatically once authenticated

Alternatively, once you’re authenticated with bcnav, you can query the companies endpoint to list all available companies with their IDs.

3.4 Understanding Racket parameters🔗

bcnav uses Racket parameters for configuration. If you’re new to Racket, a parameter is like a thread-safe global variable with some nice properties:

  • You can read the current value by calling it with no arguments: (current-bc-tenant)

  • You can set a new value by calling it with one argument: (current-bc-tenant "my-tenant-id")

  • You can temporarily change it with parameterize (the value reverts when the block exits)

bcnav provides these configuration parameters:

Parameter

Description

current-bc-tenant

Your Azure AD tenant ID or domain

current-bc-environment

BC environment name (default: "Production")

current-bc-company

The BC company GUID to access

current-bc-client-id

Your app registration's client ID

current-bc-client-secret

Your app registration's client secret

3.5 Storing credentials securely🔗

You should never put secrets directly in source files that might be committed to version control. Here are better approaches:

3.5.1 Environment variables (recommended)🔗

Set environment variables before running your Racket code:

On macOS/Linux:
export BC_TENANT_ID="your-tenant-id"
export BC_CLIENT_ID="your-client-id"
export BC_CLIENT_SECRET="your-secret"
export BC_COMPANY_ID="your-company-guid"

On Windows (PowerShell):
$env:BC_TENANT_ID = "your-tenant-id"
$env:BC_CLIENT_ID = "your-client-id"
$env:BC_CLIENT_SECRET = "your-secret"
$env:BC_COMPANY_ID = "your-company-guid"

Then in your Racket code:

(current-bc-tenant (getenv "BC_TENANT_ID"))
(current-bc-client-id (getenv "BC_CLIENT_ID"))
(current-bc-client-secret (getenv "BC_CLIENT_SECRET"))
(current-bc-company (getenv "BC_COMPANY_ID"))

3.5.2 Separate configuration file🔗

Keep a configuration file that’s excluded from version control:

;; config.rkt (add to .gitignore!)
;; #lang racket/base
(provide configure-bc!)
 
(require bcnav)
 
(define (configure-bc!)
  (current-bc-tenant "your-tenant-id")
  (current-bc-client-id "your-client-id")
  (current-bc-client-secret "your-secret")
  (current-bc-company "your-company-guid")
  (current-bc-environment "Production"))

Then in your main code:

(require "config.rkt")
(configure-bc!)
(bc-authenticate!)

3.6 Authenticating with client credentials🔗

With configuration in place, authenticate with bc-authenticate!:

;; #lang racket
 
(require bcnav)
 
;; Configure (assuming environment variables are set)
(current-bc-tenant (getenv "BC_TENANT_ID"))
(current-bc-client-id (getenv "BC_CLIENT_ID"))
(current-bc-client-secret (getenv "BC_CLIENT_SECRET"))
(current-bc-company (getenv "BC_COMPANY_ID"))
 
;; Authenticate
(bc-authenticate!)

If successful, this returns a token struct and stores it in current-bc-token. If there’s a problem, you’ll get an error message explaining what went wrong.

3.7 Interactive authentication🔗

For scenarios where you want to authenticate as a specific user (rather than as a service), bcnav supports interactive authentication. This opens a browser window for the user to sign in.

First, add a redirect URI to your app registration:

  1. In your app registration, go to Authentication

  2. Click Add a platform

  3. Select Mobile and desktop applications

  4. Add this redirect URI: http://localhost:8080/oauth/authorization

  5. Click Configure

Also add Delegated permissions (in addition to or instead of Application permissions) under API permissions.

Then use bc-authenticate/interactive!:

(bc-authenticate/interactive!)

This will:
  1. Open your default browser to Microsoft’s login page

  2. Wait for you to sign in and grant consent

  3. Receive the authorization code via the redirect URI

  4. Exchange the code for tokens

Interactive authentication provides a refresh token, so bcnav can automatically refresh your session without requiring you to sign in again.

3.8 Checking authentication status🔗

You can check if you have a valid token:

(token-valid?)   ;; #t if authenticated and token not expired
(token-expired?) ;; #t if token has expired

If your token expires and you authenticated with bc-authenticate! (client credentials), you’ll need to call it again. If you used bc-authenticate/interactive!, bcnav will automatically refresh the token when needed.

3.9 Troubleshooting🔗

3.9.1 AADSTS700016: Application not found🔗

This usually means:
  • The client ID is incorrect

  • You’re trying to authenticate against the wrong tenant

Double-check your current-bc-client-id and current-bc-tenant values.

3.9.2 AADSTS7000218: Request body must contain client_secret🔗

You’re using client credentials flow but haven’t provided a secret. Make sure current-bc-client-secret is set.

3.9.3 401 Unauthorized from Business Central🔗

The OAuth token was accepted, but BC rejected the request. Common causes:

  • API permissions weren’t granted admin consent in Azure

  • The app isn’t registered in Business Central (for application permissions)

  • The company ID is incorrect

  • The environment name is wrong

For application permissions, you also need to register your app in Business Central:

  1. In Business Central, search for Microsoft Entra Applications

  2. Add a new entry with your app’s Client ID

  3. Assign an appropriate permission set (e.g., D365 BUS FULL ACCESS)

3.10 Next steps🔗

With authentication working, you’re ready to start querying data. Continue to Querying with OData to learn about bcnav’s query language.