An easy way to get QR codes from a web service with AL

In this video, I write a few lines AL code to generate QR codes from a web service. Easy and very effective, check it out:

https://youtu.be/ddMp579NqnM

In this video, Erik demonstrates a quick and practical way to generate QR codes in Business Central by calling a free web service API. He walks through the entire process — from discovering the API, to building a small AL extension that fetches a QR code image and stores it in a Blob field on the Item Card. The whole solution comes together in roughly 50 lines of code.

The QR Code Web Service

Erik stumbled across a handy free web service at api.qrserver.com that generates QR codes on the fly. The API is straightforward — you pass in the data you want encoded and a size parameter, and it returns a QR code image as binary data. For example:

http://api.qrserver.com/v1/create-qr-code/?data=HelloYouTube&size=200x200

The API supports additional parameters like character sets and error correction levels, but for this demo, Erik keeps it simple with just the data and size parameters.

Setting Up the Table Extension

The first step is creating a place to store the QR code. Erik adds a Blob field to the Item table using a table extension:

tableextension 50100 "QR Codes" extends Item
{
    fields
    {
        field(50100; QRCode; Blob)
        {
            Caption = 'QR Code';
            Subtype = Bitmap;
        }
    }
}

The key details here are the field type Blob and the Subtype = Bitmap, which tells Business Central that this Blob field contains image data.

Building the Page Extension

Next, Erik extends the Item Card page to display the QR code and provide a way to generate it. He runs into an interesting UX challenge: Blob fields don’t support assist edits in the way he initially planned. His workaround is clever — he creates a Label variable and adds it as a field on the page with ShowCaption = false. This causes the label text to render as a clickable link, and he hooks the generation logic into the OnDrillDown trigger:

pageextension 50101 "QR Code" extends "Item Card"
{
    layout
    {
        addlast(Item)
        {
            field(QRCode; Rec.QRCode)
            {
                ApplicationArea = all;
            }
            field(GenerateQR; GenerateQR)
            {
                ApplicationArea = all;
                ShowCaption = false;
                Trigger OnDrillDown()
                var
                    Client: HttpClient;
                    Response: HttpResponseMessage;
                    URL: Text;
                    InS: InStream;
                    OutS: OutStream;
                begin
                    URL := 'http://api.qrserver.com/v1/create-qr-code/?data=' + Rec."No." + '!&size=200x200';
                    if Client.get(URL, Response) then begin
                        if Response.IsSuccessStatusCode() then begin
                            Response.Content().ReadAs(InS);
                            Rec.QRCode.CreateOutStream(OutS);
                            CopyStream(OutS, InS);
                            Rec.Modify();
                        end;
                    end;
                end;
            }
        }
    }
    var
        GenerateQR: Label 'Generate QR Code';
}

How the Web Service Call Works

Let’s break down the core logic, which is really just about eight lines of meaningful code:

  1. Build the URL: The item number is concatenated into the API URL, so each item gets a unique QR code encoding its number.
  2. Make the HTTP GET request: The HttpClient.Get() method sends the request. It takes the URL and an HttpResponseMessage variable to store the response.
  3. Check for success: Response.IsSuccessStatusCode() confirms the web service returned a valid response.
  4. Read the response content as a stream: Response.Content().ReadAs(InS) gives you an InStream — essentially a pointer to the binary data sitting in the response buffer in memory.
  5. Create an OutStream to the Blob field: Rec.QRCode.CreateOutStream(OutS) gives you a write pointer to the Blob field’s memory, so you can pump data into it.
  6. Copy the data: CopyStream(OutS, InS) pulls the data from the HTTP response and pushes it into the Blob field.
  7. Save the record: Rec.Modify() persists everything to the database.

A Note on Streams

If the InStream/OutStream pattern feels a bit confusing, Erik mentions he has an older video on the channel called “In Out Read Write Confusing Directions” that covers streams in detail. The mental model is: an InStream is something you read from, and an OutStream is something you write to. The CopyStream function bridges the two — reading from the InStream (the HTTP response) and writing to the OutStream (the Blob field).

The Label-as-Link Trick

One practical UX tip from this video: if you need a clickable link on a page, you can declare a Label variable, add it as a field with ShowCaption = false, and use the OnDrillDown trigger for your logic. Business Central renders the label text as a hyperlink, giving you a clean, clickable “Generate QR Code” action right on the card.

Running in a Sandbox

Since Erik is working in a sandbox environment, Business Central prompts for confirmation when making external web service calls. In a production environment, you’d want to make sure your HTTP calls are properly secured and that the endpoint is whitelisted as needed. Also note the URL uses http — in a production scenario, you’d want to use https if the service supports it.

Summary

This is an elegant, minimal solution for generating QR codes in Business Central without dealing with fonts, barcode libraries, or complex encoding logic. The entire extension weighs in at around 50 lines of code and leverages a free API to do the heavy lifting. The key takeaways are:

  • Use HttpClient and HttpResponseMessage to call external web services from AL
  • Use streams (InStream / OutStream) to move binary data from an HTTP response into a Blob field
  • Store images in Blob fields with Subtype = Bitmap for proper rendering
  • Use the Label-as-link pattern for clean, clickable actions on pages