Web service integration with WooCommerce in AL and Business Central

In this video, I look into how I can integrate Business Central with WooCommerce using web services. Check it out:

https://youtu.be/kzlXsa5_C-Q

In this video, Erik demonstrates how to integrate Business Central with WooCommerce using AL code and the WooCommerce REST API. He walks through the entire process — from obtaining API credentials to making HTTP requests and parsing JSON responses — all in roughly 35 lines of code.

The Big Plan

Erik runs a small app company called hougaard.com where his wife sells symbolic optic designs, a toolbox product, and other items. With such a small team, automation is essential. The “big plan” is to have Business Central serve as the central hub that connects to several external systems:

  • AppSource lead generation — sending follow-up emails with video links to people who download apps
  • WooCommerce webshop — the hougaard.com store, which requires custom integration due to the need for serial numbers and license keys
  • AppSource telemetry — monitoring how published apps are performing
  • Mailsend (Musend) — for email sending

The existing out-of-the-box AppSource apps for WooCommerce integration don’t work for this scenario because of the custom license key requirements. So Erik builds the integration from scratch — and shows just how straightforward it is.

WooCommerce API Authentication

To talk to WooCommerce, you first need to create a REST API key in the WooCommerce admin panel. This gives you two pieces of information:

  • Consumer Key (prefixed with ck_)
  • Consumer Secret (prefixed with cs_)

The WooCommerce API documentation provides examples in Ruby, Python, PHP, and Node — all of which use dedicated WooCommerce libraries. However, the curl example is the most useful for understanding the raw HTTP call. It reveals that you can simply pass the consumer key and consumer secret as query string parameters. No special SDK needed.

Erik addresses a common concern about security: passing credentials in the query string versus using Basic Auth headers. When using HTTPS, the entire HTTP request — including the query string — is sent within an encrypted block. The query string is not singled out or sent in plain text. So from a security standpoint, both approaches are equivalent over HTTPS.

Building the WooCommerce Connector

The core of the integration is a codeunit that makes an HTTP GET request to the WooCommerce products endpoint and parses the JSON response. Here’s the complete code:

codeunit 51200 "WooCommerce Connector"
{
    procedure GetProducts()
    var
        Client: HttpClient;
        Request: HttpRequestMessage;
        Response: HttpResponseMessage;
        ResponseTxt: Text;
        Products: JsonArray;
        Product: JsonObject;
        T: JsonToken;
        NameField: JsonToken;
        ck: Text;
        cs: Text;
    begin
        ck := 'ck_31d8c555d66ebd1c7bc8f61c5020eb647b64f3b9';
        cs := 'cs_a5e0706a4b9e3afcb36c2f576fe417ac83f37c9e';
        Request.Method := 'GET';
        Request.SetRequestUri(
            'https://www.hougaard.com/wp-json/wc/v3/products?consumer_key=' + ck 
            + '&consumer_secret=' + cs);

        if Client.Send(Request, Response) then begin
            if Response.IsSuccessStatusCode() then begin
                Response.Content().ReadAs(ResponseTxt);
                Products.ReadFrom(ResponseTxt);
                foreach T in Products do begin
                    Product := T.AsObject();
                    Product.Get('name', NameField);
                    message('%1', NameField.AsValue().AsText());
                end;
            end else
                error('We got %1 problems', Response.HttpStatusCode());
        end else
            error('We got a problem');
    end;
}

Let’s break down the key parts of this code.

The HTTP Request Pattern

Whenever you need to call a web service from AL, the pattern involves three core variables:

  • HttpClient — the client that sends the request
  • HttpRequestMessage — defines what you’re asking for
  • HttpResponseMessage — holds what comes back

The “business end” of the whole thing is this single line:

if Client.Send(Request, Response) then begin

If Send returns false, the request couldn’t even be sent — perhaps due to the environment blocking HTTP calls (there’s a configuration in Extension Management that controls whether HTTP requests are allowed). If the request was sent but the status code isn’t successful, you get an error with the HTTP status code (e.g., “We got 404 problems”).

Constructing the Request

Setting up the request is straightforward — just two properties:

Request.Method := 'GET';
Request.SetRequestUri('https://www.hougaard.com/wp-json/wc/v3/products?consumer_key=' + ck 
    + '&consumer_secret=' + cs);

The URL structure is your WooCommerce site’s base URL, followed by /wp-json/wc/v3/products, with the API credentials appended as query parameters. In a production scenario, you’d store these credentials in a setup table rather than hardcoding them.

A Note on the HTTP Permission Dialog

Erik highlights a classic gotcha when testing: after stepping through the code in the debugger, the request appears to hang. Nothing seems to happen. But if you switch back to the browser, Business Central is showing a permission dialog asking whether you want to allow the outbound HTTP request. Once you approve it, execution continues immediately and you’re in the success path.

Parsing the JSON Response

The WooCommerce API returns JSON, and the products endpoint returns a JSON array (starts with a square bracket [). Each element in the array is a JSON object representing a product.

The parsing follows a specific chain:

  1. Read the response content as text: Response.Content().ReadAs(ResponseTxt)
  2. Parse the text into a JsonArray: Products.ReadFrom(ResponseTxt)
  3. Loop through the array using a JsonToken: foreach T in Products do
  4. Cast each token to a JsonObject: Product := T.AsObject()
  5. Extract fields from the object: Product.Get('name', NameField)
  6. Convert the field value to an AL data type: NameField.AsValue().AsText()

Erik mentions he’d love to see a future overload of ReadAs that could read directly into a JsonObject, JsonArray, or JsonToken, skipping the intermediate text variable. But for now, the ReadAs(Text) followed by ReadFrom(Text) pattern is how it’s done.

Understanding JsonToken

The JsonToken type is the generic, flexible type in AL’s JSON handling. A token can be an object, an array, or a value. You use it as the iteration variable when looping through arrays, and then cast it to the specific type you need. In this case, we know each element is an object, so we call T.AsObject(). If the data were different, you could check with T.IsObject() before casting.

The ReadAs / ReadFrom Confusion

Erik references his video on “In Out Read Write Confusing Directions” — a common pain point in AL development. ReadAs reads out of content into a variable, while ReadFrom reads from a variable into a JSON structure. The naming can be counterintuitive, but the pattern becomes second nature with practice.

Triggering the Integration from the UI

To test the integration, Erik adds a simple action button to the Item List page:

pageextension 51200 Items extends "Item List"
{
    actions
    {
        addfirst(processing)
        {
            action(Woo)
            {
                Caption = 'Woo';
                ApplicationArea = all;
                trigger OnAction()
                var
                    Woo: Codeunit "WooCommerce Connector";
                begin
                    Woo.GetProducts();
                end;
            }
        }
    }
}

Clicking the “Woo” action on the Item List calls GetProducts(), which fetches all products from WooCommerce and displays each product name in a message dialog. The stacked message boxes confirm that all products are being retrieved successfully.

Pagination

Erik briefly mentions that if you have many products, WooCommerce supports pagination through query parameters (like an offset parameter) that you can append to the URL. For his small catalog, this wasn’t necessary.

WooCommerce Add-on Endpoints

An important observation: WooCommerce add-ons (plugins that extend WooCommerce functionality) tend to register their own REST API endpoints following the same patterns. This means you can use the exact same HTTP client approach to interact with extended WooCommerce features — such as subscriptions, license keys, or custom product types.

Summary

Integrating Business Central with WooCommerce via the REST API is remarkably straightforward. In about 35 lines of AL code, you can authenticate with the WooCommerce API, make HTTP requests, and parse JSON responses. The key takeaways:

  • WooCommerce REST API uses simple consumer key/secret authentication via query parameters
  • The AL HttpClient / HttpRequestMessage / HttpResponseMessage pattern handles the web service call
  • JSON parsing in AL follows a chain: text → JsonArray → JsonToken → JsonObject → field values
  • Remember to approve the HTTP permission dialog when testing in a sandboxed environment
  • This same pattern works for any REST API, not just WooCommerce

No special libraries, no third-party apps — just standard AL web service capabilities talking to a well-documented REST API.