How-toMicrosoft Dynamics 365 Business CentralAL Development / HttpClient

How to call an external REST API from AL in Business Central

Question
How to call an external REST API from AL in Business Central using HttpClient

Also searched as

  • business central al httpclient post json example
  • business central HttpClient requests not allowed extension setting
  • al http request oauth bearer token business central

Short answer

Use the HttpClient, HttpRequestMessage, HttpResponseMessage and HttpContent types in AL, send the request with Send, check IsSuccessStatusCode, and parse the body with JsonObject.ReadFrom. Make sure the extension has Allow HttpClient Requests turned on, and keep tokens out of source code. Keep calls short, because they run inside the AL session.

Applies to: Business Central online (SaaS) and on-premises, AL runtime 6 and later

How to do it

  1. 1Create an AL codeunit that will own the call, so the rest of the extension never touches HttpClient directly.
  2. 2Build the request: set Method, RequestUri and add headers such as Accept and Authorization on the request headers collection.
  3. 3For POST or PATCH, create an HttpContent with WriteFrom of the JSON text and set Content-Type to application/json on the content headers.
  4. 4Call Client.Send(Request, Response). Check the Boolean result, which is false if the network call itself failed.
  5. 5Check Response.IsSuccessStatusCode and read Response.HttpStatusCode so you can react to 401, 404, 429 and 5xx differently.
  6. 6Read the body with Response.Content.ReadAs(Text) and parse it with JsonObject.ReadFrom, then use Get and AsValue to pull fields.
  7. 7In the Extension Management area, open Extension Settings for your extension and enable Allow HttpClient Requests so the runtime lets it call out.
  8. 8Store secrets in Isolated Storage or a secure key, not in code, and use a job queue entry for anything slow or retried.

A working pattern

The following codeunit posts a small JSON body to an external service and returns the response text. It separates building the request from interpreting the result, which makes it easy to test and to change the endpoint. Replace the URL and token handling with your own. The Authorization value is shown as a placeholder variable, never a literal secret.

Notice that Send returns a Boolean for transport success, while IsSuccessStatusCode reports whether the HTTP status was 2xx. Both must be checked. A 400 or 500 response still returns true from Send, so skipping the status check hides failures from callers.

codeunit 50100 "Ext Api Client"
{
    procedure PostOrder(Payload: JsonObject; Token: Text): Text
    var
        Client: HttpClient;
        Request: HttpRequestMessage;
        Response: HttpResponseMessage;
        Content: HttpContent;
        ContentHeaders: HttpHeaders;
        Body: Text;
        ResponseText: Text;
    begin
        Payload.WriteTo(Body);
        Content.WriteFrom(Body);
        Content.GetHeaders(ContentHeaders);
        ContentHeaders.Remove('Content-Type');
        ContentHeaders.Add('Content-Type', 'application/json');

        Request.Method := 'POST';
        Request.SetRequestUri('https://api.example.com/v1/orders');
        Request.GetHeaders(ContentHeaders);
        ContentHeaders.Add('Authorization', 'Bearer ' + Token);
        Request.Content := Content;

        if not Client.Send(Request, Response) then
            Error('Could not reach the service.');

        Response.Content.ReadAs(ResponseText);
        if not Response.IsSuccessStatusCode then
            Error('Service returned %1: %2', Response.HttpStatusCode, ResponseText);
        exit(ResponseText);
    end;
}

Permissions, settings and common failures

The first failure most developers see is a message that the extension is not allowed to make the request. In the SaaS service, outbound calls are controlled per extension through the Extension Settings page, where Allow HttpClient Requests must be enabled, and in sandboxes this commonly needs to be set after each deployment. On-premises, the setting also exists, and firewalls and certificates then matter as well.

A second class of failures is TLS and DNS. The service must present a certificate the Business Central service tier trusts, and the host must be reachable from where the service tier runs. For SaaS that means a public endpoint; private endpoints inside your network are not reachable from the cloud service unless you expose them.

A third is timeout. AL calls run synchronously inside a user session or job. Do not call slow services from page triggers or from inside a posting transaction. Run them from a job queue entry and store the result, so a slow partner does not block users or hold locks.

Authentication and secrets

Most modern services want a bearer token. For OAuth 2.0 client credentials, request the token from the identity provider with a separate HttpClient call, cache it until shortly before it expires, and send it in the Authorization header. Newer versions of the base application include an OAuth2 helper codeunit for acquiring tokens, so check the version you target before writing your own.

Keep client secrets in Isolated Storage with the right data scope, or in the service's own key store, and show them only through a protected setup page. Never write a token or key into a text field that appears in the change log or in a table readable by many users.

Log the status code and a correlation identifier for each call, not the full request body if it contains personal or commercial data.

Common pitfalls

  • !Checking only the Boolean from Send and treating a 4xx or 5xx response as success.
  • !Forgetting to enable Allow HttpClient Requests for the extension after a new deployment or in a new environment.
  • !Calling a slow external service from inside a posting routine or page trigger, which blocks the user and extends locks.
  • !Putting secrets or tokens in source code or in a table many users can read.
  • !Expecting a SaaS environment to reach an on-premises-only URL.

How an ERP-grounded AI assistant handles this

For a private deployment the interesting case is the reverse: calling a locally hosted model from AL. A Business Central extension can post a question and retrieved context to an internal inference endpoint served by vLLM or Ollama and show the answer on a page. Netray builds this kind of integration with the model on the customer's own GPUs, read-only access to Business Central data by default, and human approval before anything is written back.

Frequently asked questions

Why does HttpClient say the request is not allowed?

The extension has not been permitted to make outbound HTTP calls. Open the Extension Management page, select your extension, choose Extension Settings, and turn on Allow HttpClient Requests. In sandboxes this setting often has to be switched on again after redeploying the extension.

What is the difference between Send returning true and IsSuccessStatusCode?

Send returns true when the HTTP exchange completed at all, even if the server answered 404 or 500. IsSuccessStatusCode is true only for 2xx codes. You need both checks: the first catches network failures, the second catches errors reported by the service.

Can I call the API from a page trigger?

Technically yes, but avoid it. The call is synchronous, so a slow partner freezes the user's session and can hold database locks if you are inside a transaction. Run external calls from a job queue entry or a separate action and store the result for the page to display.

How should I store the API key?

Use Isolated Storage with an appropriate data scope, or a dedicated key store, and expose it only through a protected setup page. Do not hardcode it in AL, and do not keep it in a normal table field that many users or the change log can read.

Related

Error fix

Business Central: "Another user has modified the record after you retrieved it"

Business Central uses optimistic concurrency. Every record carries a row version, and a write is rejected if the stored version no longer matches what you read. For users, refresh the page and redo the edit. For developers, read and modify in the same short transaction, use LockTable or the right read isolation, and send an If-Match ETag from API clients.

How-to

Calling and extending the Business Central API v2.0

The Business Central API v2.0 is a REST/OData endpoint at api.businesscentral.dynamics.com/v2.0/{tenant}/{environment}/api/v2.0, authenticated with Azure AD OAuth 2.0. It exposes standard entities like customers and items, and lets you publish your own with an AL API page.

Error fix

Fixing "You do not have the following permissions on TableData (table): (permission)" in Business Central AL

This runtime error means the current user's assigned permission sets do not grant the required Insert, Modify, Delete, Read, or Execute right on that specific table. It is most common right after installing or updating a custom AL extension, because Business Central checks object-level permissions even for tables an extension owns.

Error fix

Fixing "Cannot create a record in (table). The record already exists" in D365 F&SCM data entity imports

This is the standard kernel duplicate-key exception, thrown when the Data Management Framework tries to insert a staging row into a target table whose unique or alternate key already matches an existing record. It almost always means the entity's insert-vs-update logic did not recognize the target row as an update, not that you have a true accidental duplicate in your source file.

Error fix

Fixing "There are currently no batch servers available for processing" in D365 F&SCM

This message means the batch framework cannot find any AOS instance flagged as a batch server and available for the batch group the job is assigned to. The fix is almost always in server configuration (System administration > Servers) or batch group assignment, not in the batch job itself.

Error fix

Fixing "The CIL object was not found" in Dynamics AX 2012

This error appears when the AOS tries to execute compiled CIL for a class or method that has not actually been regenerated since a code change was imported or edited, so the .NET runtime has nothing matching to run. The fix is a full compile followed by a full CIL generation and an AOS restart, not just a partial or incremental rebuild.

AI for ERP

AI for Dynamics 365 Business Central, on-premises or SaaS, beyond Copilot

AI for Business Central beyond Copilot: grounded question answering over BC's data via OData and APIs, for on-premises and SaaS tenants alike.

AI for ERP

AI for Business Central manufacturing operations, beyond Copilot

AI for Business Central manufacturing beyond Copilot: grounded answers on production orders, routings, and capacity via APIs v2.0, on-prem capable.

Stuck on Microsoft Dynamics 365 Business Central?

Talk to engineers who work inside Microsoft Dynamics 365 Business Central every week, and who build private AI that answers these questions from your own ERP data.