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!:
bcnav sends your client ID and secret to Microsoft’s authentication servers
Microsoft verifies the credentials and returns an access token
bcnav stores this token and includes it in all subsequent API requests
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:
Search for "Microsoft Entra ID" (or "Azure Active Directory") in the top search bar
Select App registrations from the left menu
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—
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:
In your app registration, go to Certificates & secrets
Click New client secret
Add a description (e.g., "bcnav access") and choose an expiration period
Click Add
Immediately copy the secret value—
it won’t be shown again!
3.2.6 Step 6: Configure API permissions
Your app needs permission to access the Business Central API:
Go to API permissions
Click Add a permission
Select Dynamics 365 Business Central
Choose Application permissions (for client credentials flow)
Select API.ReadWrite.All or the specific permissions you need
Click Add permissions
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:
Open Business Central in your browser
Use the search (Alt+Q) to open Companies
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 |
Your Azure AD tenant ID or domain | |
BC environment name (default: "Production") | |
The BC company GUID to access | |
Your app registration's client ID | |
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:
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"
$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:
In your app registration, go to Authentication
Click Add a platform
Select Mobile and desktop applications
Add this redirect URI: http://localhost:8080/oauth/authorization
Click Configure
Also add Delegated permissions (in addition to or instead of Application permissions) under API permissions.
Then use bc-authenticate/interactive!:
Open your default browser to Microsoft’s login page
Wait for you to sign in and grant consent
Receive the authorization code via the redirect URI
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
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:
In Business Central, search for Microsoft Entra Applications
Add a new entry with your app’s Client ID
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.