Study guide
16.1 HttpClient, HttpRequestMessage & REST API Consumption
Microsoft Dynamics 365 Business Central Developer MB-820
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: Business Central Architecture & Platform Foundation
1.1 Business Central Architecture & Extensions Model 1.2 Customization Lifecycle: Cloud (SaaS) vs. On-Premises 1.3 Base Application, System Application & AppSource
2 Chapter 2: Development Environment & Configuration
2.1: Development Environment Setup: VS Code, AL: Go! Projects & Sandboxes 2.2: AL Configuration Files: app.json & launch.json Parameters 2.3: Multi-Root Workspaces & Project Dependencies
3 Chapter 3: Extension Lifecycle: Debugging, Deployment, Multilanguage & Maintenance
3.1 Debugging & Snapshot Debugging in Visual Studio Code 3.2 Extension Deployment & Schema Synchronization Modes 3.3 Multilanguage Development with XLIFF & Translation Files 3.4 Extension Maintenance, Deprecation & Breaking Changes
4 Chapter 4: Tables, Table Extensions & Data Modeling
4.1: Building Tables, Fields, Keys & Data Types 4.2: Table Extensions & Table Modifications 4.3: FlowFields, FlowFilters & Table Relations 4.4: Enums, Enum Extensions & Extensible Types
5 Chapter 5: Pages, Page Extensions & Role Centers
5.1: Page Types, Anatomy & Control Structure 5.2: Building Card, List & Document Pages 5.3: Page Extensions & Page Customizations 5.4: Role Centers, Headlines & Cue Data Modeling
6 Chapter 6: Reports & Document Generation
6.1 Report Architecture, DataItems & Dataset Design 6.2 Report Layouts: RDLC, Word, Excel & Multilanguage 6.3 Document Reports & Request Page Programming 6.4 Processing-Only Reports & Report Substitutions
7 Chapter 7: XMLports & Data Exchange
7.1 XMLport Architecture, Formats & Properties 7.2 XMLport Node Hierarchy, Triggers & Stream Manipulation
8 Chapter 8: Codeunits, Events, Triggers & Interfaces
8.1 Codeunit Types, Execution & SingleInstance Codeunits 8.2 Events, Publishers, Subscribers & Event Isolation 8.3 Interfaces, Polymorphism & Dynamic Codeunit Invocation 8.4 Installation & Upgrade Codeunits, Data Transfer & Archive
9 Chapter 9: Entitlements, Permissions & Queries
9.1 Permission Sets & Permission Set Extensions 9.2 Inherent Permissions, Inherent Entitlements & Security Scoping 9.3 Query Objects: Joins, Aggregation & Query as Report Data Source
10 Chapter 10: UI Customization, User Assistance & Onboarding
10.1 Profile Objects & Custom Page Views in AL 10.2 User Assistance: ToolTips, Teaching Tips & In-App Tours 10.3 Assisted Setup, Guided Experience & Onboarding Checklists
11 Chapter 11: Business Central Design Patterns & Data Process Model
11.1 Functional Table Types: Master Data, Supplemental & Setup Patterns 11.2 Document Standards: Header, Line, History & Journal Architectures 11.3 Data Process Model & Posting Routine Architecture
12 Chapter 12: AL Language Fundamentals, Data Types & Variables
12.1 AL Syntax, Variable Scope, Primitive & Complex Data Types 12.2 Expressions, Control Flow Statements & Built-in Functions 12.3 Access Modifiers (Public, Internal, Local) & Code Scoping
13 Chapter 13: Data Manipulation, Streams & Error Handling
13.1 Record Operations: Get, FindSet, ModifyAll & Filter Functions 13.2 Streams, File Management & TempBlob 13.3 Error Handling: ErrorInfo, TryFunctions & Collectible Errors
14 Chapter 14: Testing, Test Toolkit & Automation
14.1 Testing Architecture & the Test Toolkit 14.2 Authoring Test Codeunits & UI Handler Functions
15 Chapter 15: Telemetry, Performance Optimization & Analyzers
15.1 Telemetry Configuration & Azure Application Insights 15.2 Custom Telemetry Signals with Session.LogMessage & KQL 15.3 Performance Profiler, SetLoadFields & Query Optimization 15.4 AL Analyzers: CodeCop, AppSourceCop, UICop & PTECop
16 Chapter 16: REST Web Services & JSON in AL
16.1 HttpClient, HttpRequestMessage & REST API Consumption 16.2 JSON Processing: JsonObject, JsonArray, JsonValue & JsonToken
17 Chapter 17: API Pages, OData, Read Scale-Out & OAuth
17.1 API Pages (PageType=API), OData Web Services & REST Endpoints 17.2 Bound and Unbound OData Actions with [ServiceEnabled] 17.3 Read Scale-Out Architecture & DataAccessIntent Configuration 17.4 Microsoft Entra ID App Registrations & OAuth 2.0 Integration
16.1 HttpClient, HttpRequestMessage & REST API Consumption
Key Takeaways Explain This Topic AI
AL provides five foundational HTTP classes for REST integration: HttpClient (client transport engine), HttpRequestMessage (request envelope), HttpResponseMessage (response container), HttpHeaders (header collections), and HttpContent (entity payload and MIME headers).
HttpClient provides shorthand helper methods for GET, POST, PUT, and DELETE; however, HTTP PATCH requests require explicitly configuring an HttpRequestMessage with Method('PATCH') and dispatching via HttpClient.Send().
Request-level headers (such as Authorization, Accept, and X-API-Key) must be attached to HttpRequestMessage.GetHeaders(), whereas entity/payload headers (such as Content-Type and Content-Encoding) must be attached to HttpContent.GetHeaders().
Robust integration error handling requires a two-tiered evaluation: testing the boolean return of HttpClient.Send() for transport/network/timeout failures, followed by evaluating HttpResponseMessage.IsSuccessStatusCode() for 2xx HTTP response status.
In Business Central SaaS environments, outbound HTTP calls are blocked by default for newly deployed extensions until a tenant administrator enables the 'Allow HttpClient Requests' toggle on the Extension Management card.
Last updated: August 2026
16.1 HttpClient, HttpRequestMessage & REST API Consumption
Modern enterprise resource planning (ERP) architectures require Microsoft Dynamics 365 Business Central to communicate bidirectionally with external third-party software-as-a-service (SaaS) applications, payment gateways, logistics carriers, tax calculation engines, ecommerce storefronts, and internal microservices. In AL, developers consume external Representational State Transfer (REST) web services using a suite of native HTTP data types modeled closely after the .NET System.Net.Http namespace.
For the MB-820 (Microsoft Dynamics 365 Business Central Developer Associate) examination, developers must master the five core AL HTTP classes, understand the strict distinction between general request headers and content-specific MIME headers, configure request timeouts, handle complex HTTP verbs such as PATCH , implement two-tiered error handling, stream large binary and text payloads, and manage cloud sandbox network security permissions.
1. The AL HTTP Object Model & Architecture
The AL HTTP framework consists of five core reference types that encapsulate the client transport engine, message definitions, headers, and entity payloads: +-----------------------------------------------------------------------+
- | AL HTTP ARCHITECTURE |
- +-----------------------------------------------------------------------+
- [ HttpClient ]
- │ - Timeout (Default: 100,000 ms / 100 seconds)
- │ - Clear() / DefaultRequestHeaders()
- │ - Get() / Post() / Put() / Delete() / Send()
- │
- ▼ Dispatches
- [ HttpRequestMessage ]
- ├── .SetRequestUri('https://api.contoso.com/v1/shipments')
- ├── .Method('POST' | 'GET' | 'PATCH' | 'PUT' | 'DELETE')
- ├── .GetHeaders(RequestHeaders) ──► [ HttpHeaders ]
- │ - Authorization: Bearer
- │ - Accept: application/json
- │ - X-API-Key: secret123
- └── .Content(HttpBody)
- │
- ▼
- [ HttpContent ]
- ├── .WriteFrom(JsonPayloadText | InStream)
- └── .GetHeaders(ContentHeaders) ──► [ HttpHeaders ]
- Content-Type
- Content-Length
- ▲ Receives
- │
- [ HttpResponseMessage ]
- ├── .HttpStatusCode (Integer, e.g., 200, 201, 400, 404, 500)
- ├── .IsSuccessStatusCode() (Boolean: True if 200..299)
- ├── .ReasonPhrase (Text, e.g., 'OK', 'Not Found')
- ├── .Headers ──► [ HttpHeaders ] (Response Headers)
- └── .Content ──► [ HttpContent ]
- └── .ReadAs(ResponseText | InStream)
- The Five Core HTTP Classes
AL Class Description & Core Responsibilities Key Methods & Properties
HttpClient The client transport engine responsible for managing network sockets, SSL/TLS handshake negotiation, applying client timeouts, and dispatching HTTP requests over the network. Get(Uri, HttpResponseMessage) ; Post(Uri, HttpContent, HttpResponseMessage) ; Put(Uri, HttpContent, HttpResponseMessage) ; Delete(Uri, HttpResponseMessage) ; Send(HttpRequestMessage, HttpResponseMessage) ; Timeout(Integer) ; DefaultRequestHeaders(HttpHeaders) ; Clear()
HttpRequestMessage Represents an outbound HTTP request package. Encapsulates the target endpoint URI, HTTP verb method, request-level headers, and entity payload. SetRequestUri(Text) ; GetRequestUri(Text) ; Method(Text) ; GetHeaders(HttpHeaders) ; Content(HttpContent)
HttpResponseMessage Container for the inbound HTTP response returned by the remote server, including HTTP status codes, status descriptions, response headers, and body payload. HttpStatusCode() ; IsSuccessStatusCode() ; ReasonPhrase() ; Content(HttpContent) ; Headers(HttpHeaders)
HttpHeaders Represents a key-value collection of RFC-compliant HTTP headers. Used interchangeably for request headers, response headers, and content-specific entity headers. Add(Text, Text) ; TryAddWithoutValidation(Text, Text) ; GetValues(Text, Array of [Text]) ; Contains(Text) ; Remove(Text) ; Clear()
HttpContent Represents the entity body (payload) and associated MIME/content headers of an HTTP request or response. WriteFrom(Text | InStream) ; ReadAs(Text | InStream) ; GetHeaders(HttpHeaders) ; Clear()
2. Constructing and Sending REST Requests
When consuming REST APIs in AL, developers can execute requests using high-level shorthand methods on HttpClient or by constructing a full HttpRequestMessage for complete control over HTTP verbs, authentication headers, and request configuration.
General Request Headers vs. Content Headers (Crucial Exam Concept)
A frequent point of failure and a primary focus of the MB-820 exam is the strict separation between Request Headers and Content Headers :
Request Headers: Describe the client, authorization, and negotiation parameters. Examples include Authorization , Accept , User-Agent , If-Match , Prefer , and custom headers like X-API-Key or X-Correlation-ID . These headers must be retrieved from and added to HttpRequestMessage.GetHeaders(RequestHeaders) or HttpClient.DefaultRequestHeaders(DefaultHeaders) .
Content Headers: Describe the entity payload format, size, and encoding. Examples include Content-Type (e.g., application/json , application/xml ), Content-Length , Content-Encoding , and Content-Disposition . These headers must be retrieved from and added to HttpContent.GetHeaders(ContentHeaders) .
Exam Warning: If you attempt to add Content-Type or Content-Length to the HttpRequestMessage headers collection, Business Central will either throw a runtime exception or silently omit the header during serialization. As a result, the external REST API will reject the request with HTTP 415 (Unsupported Media Type) or HTTP 400 (Bad Request) .
Shorthand Methods vs. HttpClient.Send()
HttpClient provides convenience shorthand methods for simple scenarios where custom request headers are minimal:
- HttpClient.Get(RequestUri: Text, var Response: HttpResponseMessage): Boolean
- HttpClient.Post(RequestUri: Text, Content: HttpContent, var Response: HttpResponseMessage): Boolean
- HttpClient.Put(RequestUri: Text, Content: HttpContent, var Response: HttpResponseMessage): Boolean
- HttpClient.Delete(RequestUri: Text, var Response: HttpResponseMessage): Boolean
However, for enterprise integration where requests require authentication tokens, custom telemetry headers, or the PATCH HTTP verb, developers must construct an HttpRequestMessage and dispatch it using HttpClient.Send(HttpRequestMessage, HttpResponseMessage): Boolean .
Exam Watchout — HTTP PATCH in AL: Notice that HttpClient does not have a HttpClient.Patch() shorthand method. To issue an HTTP PATCH request in AL, you must instantiate an HttpRequestMessage , invoke HttpRequestMessage.Method('PATCH') , attach your HttpContent , and call HttpClient.Send() .
Configuring Client Timeout
By default, HttpClient requests wait up to 100,000 milliseconds (100 seconds) before timing out. In synchronous UI actions (such as a user pressing a button on a card page to validate a tax ID or calculate freight rates), a 100-second freeze severely degrades user experience. Developers should explicitly set the timeout duration using the Timeout method (measured in milliseconds): // Set client timeout to 15,000 milliseconds (15 seconds)
Client.Timeout(15000);
Loading diagram... AL HTTP Request Pipeline & SaaS Permission Enforcement
3. Production AL Pattern: Secure REST Call with Bearer Authentication
The following codeunit demonstrates a production-ready AL pattern for posting JSON data to an external REST endpoint with OAuth bearer token authentication, proper header placement, timeout configuration, and defensive two-tiered error handling: codeunit 50120 "REST Integration Management"
- {
- Access = Public;
- procedure PostCustomerToExternalApi(CustomerNo: Code[20]; JsonPayload: Text): Boolean
- var
- Client: HttpClient;
- Request: HttpRequestMessage;
- Response: HttpResponseMessage;
- RequestHeaders: HttpHeaders;
- ContentHeaders: HttpHeaders;
- Content: HttpContent;
- ResponseText: Text;
- TargetUri: Label 'https://api.logistics-partner.com/v2/customers/%1', Locked = true;
- BearerToken: Text;
- begin
- // 1. Retrieve authorization token securely from IsolatedStorage
- if not IsolatedStorage.Get('LogisticsApiBearerToken', DataScope::Company, BearerToken) then
- Error('OAuth token not found. Please re-authenticate the logistics service.');
- // 2. Configure entity body and Content-Type header on HttpContent
- Content.WriteFrom(JsonPayload);
- Content.GetHeaders(ContentHeaders);
- if ContentHeaders.Contains('Content-Type') then
- ContentHeaders.Remove('Content-Type');
- ContentHeaders.Add('Content-Type', 'application/json');
- // 3. Configure HttpRequestMessage (URI, Method, and Request Headers)
- Request.SetRequestUri(StrSubstNo(TargetUri, CustomerNo));
- Request.Method('POST');
- Request.Content(Content);
- Request.GetHeaders(RequestHeaders);
- RequestHeaders.Add('Authorization', StrSubstNo('Bearer %1', BearerToken));
- RequestHeaders.Add('Accept', 'application/json');
- RequestHeaders.Add('X-Correlation-ID', Format(CreateGuid()));
- // 4. Configure client timeout (30,000 milliseconds = 30 seconds)
- Client.Timeout(30000);
- // 5. Send request and evaluate Tier 1 transport success
- if not Client.Send(Request, Response) then
- Error('Network communication failure: Unable to establish connection to external endpoint.');
- // 6. Evaluate Tier 2 HTTP response status code
- if not Response.IsSuccessStatusCode() then begin
- Response.Content().ReadAs(ResponseText);
- Error('External API call failed with HTTP Status Code %1 (%2). Server Response: %3',
- Response.HttpStatusCode(),
- Response.ReasonPhrase(),
- ResponseText);
- end;
- // 7. Read and process successful response payload
- Response.Content().ReadAs(ResponseText);
- ProcessSuccessResponse(ResponseText);
- exit(true);
- end;
- local procedure ProcessSuccessResponse(Payload: Text)
- begin
- // Ingest and process response payload
- end;
- }
- 4. Handling Inbound Responses, Stream Buffering & Diagnostic Errors
When HttpClient.Send() executes, the response handling logic must differentiate between two fundamentally distinct failure modes:
Tier 1: Transport / Network Failures ( Client.Send returns false ):
Occurs when the DNS lookup fails, the remote server IP is unreachable, the SSL/TLS certificate handshake is invalid, the connection times out, or the request was blocked by the Business Central SaaS security sandbox.
When Send() returns false , no HttpResponseMessage is received from the remote server, and inspecting Response.HttpStatusCode() is invalid.
Tier 2: HTTP Application Failures ( Response.IsSuccessStatusCode() returns false ):
Occurs when network communication was successful and the server replied, but the remote server returned an HTTP error code (4xx client error or 5xx server error).
In this case, Send() returns true , and the developer must inspect Response.HttpStatusCode() and read Response.Content() to extract diagnostic error details emitted by the remote API.
Inspecting HTTP Status Codes
Response.IsSuccessStatusCode(): Boolean : Returns true if Response.HttpStatusCode() falls within the 200 to 299 range (e.g., 200 OK , 201 Created , 204 No Content ).
Response.HttpStatusCode(): Integer : Returns the integer status code returned by the server (e.g., 400 Bad Request , 401 Unauthorized , 403 Forbidden , 404 Not Found , 429 Too Many Requests , 500 Internal Server Error , 503 Service Unavailable ).
Response.ReasonPhrase(): Text : Returns the human-readable status description (e.g., 'Unauthorized' , 'Not Found' ).
Reading Content: Text vs. InStream
HttpContent.ReadAs() supports two destination formats:
ReadAs(ResponseText: Text): Boolean : Reads the payload directly into an AL string variable. Best suited for JSON and XML payloads of moderate size (< 10 MB).
ReadAs(Stream: InStream): Boolean : Reads the raw byte stream directly into an InStream . Mandatory when handling large binary downloads (PDF invoices, shipping labels, Excel files, images, zip files) or very large JSON datasets that would exceed AL string memory limits. procedure DownloadShippingLabelPdf(LabelUrl: Text; var PdfInStream: InStream)
- var
- Client: HttpClient;
- Response: HttpResponseMessage;
- begin
- // Set timeout for large file download
- Client.Timeout(60000);
- if not Client.Get(LabelUrl, Response) then
- Error('Failed to establish connection to shipping label server.');
- if not Response.IsSuccessStatusCode() then
- Error('Label download failed with HTTP %1: %2', Response.HttpStatusCode(), Response.ReasonPhrase());
- // Stream binary content directly into InStream without string conversion
- Response.Content().ReadAs(PdfInStream);
- end;
- 5. Cloud & SaaS Outbound HTTP Security & Permission Management
In Dynamics 365 Business Central SaaS (cloud environments), multi-tenant security architecture strictly regulates outbound network traffic originating from AL extensions. By default, newly installed extensions are blocked from making outbound HTTP requests to protect customer data privacy and prevent unintended data exfiltration.
The "Allow HttpClient Requests" Setting
When an extension attempts to invoke HttpClient.Send() , HttpClient.Get() , or any other HTTP method in Business Central SaaS without explicit permission, the platform blocks the request and throws the following runtime error:
- "An error occurred while sending the request. The request was blocked by the administrator."
- Administrative Configuration Steps
To grant outbound network communication permissions in Business Central SaaS:
Open the Business Central Web Client.
Search for and open the Extension Management page ( Page 2500 ).
Locate and select the extension requiring HTTP communication.
Click Manage -> Configure (or open the Extension Card).
Enable the Allow HttpClient Requests toggle switch. +-----------------------------------------------------------------------+
- | EXTENSION MANAGEMENT - EXTENSION CARD |
- +-----------------------------------------------------------------------+
- | Extension Name: Contoso Carrier Logistics Integration |
- | Publisher: Contoso Solutions Inc. |
- | Version: 24.0.100.0 |
- | |
- | [Settings] |
- | Deploy Target: Cloud |
- | Allow HttpClient Requests: [ X ] Enabled ◄── (MANDATORY FOR REST)|
- +-----------------------------------------------------------------------+
- Developer Manifest Considerations ( app.json )
While developers cannot force-enable this setting inside app.json (as tenant administrators retain ultimate security authority over outbound traffic), extensions must declare target compatibility:
In cloud deployments, "target": "Cloud" ensures that the extension compiles against cloud-safe runtime APIs.
For automated installation scripts and CI/CD pipelines, administrators utilize PowerShell cmdlets (on-premises/private cloud: Set-NAVAppSetting -AllowHttpClientRequests ) or Admin Center APIs to automate permission toggling during deployment pipelines.