← Back to TutorialsINTEGRATION

Business Central Custom API Page: Step-by-Step Guide

Dynexal • Beginner to Intermediate • 15 min read

When a standard Business Central API does not expose the data or contract your integration needs, an AL API page lets you publish a custom REST endpoint. This guide walks through the API page structure, endpoint naming, CRUD operations, authentication concepts, Postman testing, permissions, troubleshooting and production best practices.

What you will learn: API PageType, APIPublisher, APIGroup, APIVersion, EntityName, EntitySetName, ODataKeyFields, SourceTable, CRUD operations, endpoint URLs, Postman testing, permissions and versioning.

What is a custom API page?

A custom API page is an AL page object with PageType = API. It exposes Business Central data through a versioned, OData v4-enabled REST web service and is intended for integration scenarios rather than the Business Central user interface. Microsoft documents API pages as supporting create, read, update and delete operations. citeturn0search2

Custom API pages are useful when an external website, mobile application, e-commerce platform, middleware service or another ERP system needs a focused Business Central data contract.

Standard API vs custom API

Business Central includes many built-in APIs that can often be used without writing AL. Microsoft recommends using the built-in API stack where it meets the integration requirement. A custom API is appropriate when the standard endpoint does not expose the required fields, entity shape or business-specific contract. citeturn0search5turn0search8

Custom API page structure

A minimal API page contains a small set of properties that define the endpoint and its data source:

page 50120 "Dynexal Customer API"
{
    PageType = API;
    Caption = 'Dynexal Customer API';

    APIPublisher = 'dynexal';
    APIGroup = 'integration';
    APIVersion = 'v1.0';

    EntityName = 'customer';
    EntitySetName = 'customers';

    SourceTable = Customer;
    ODataKeyFields = SystemId;
    DelayedInsert = true;

    layout
    {
        area(Content)
        {
            repeater(Group)
            {
                field(id; Rec.SystemId)
                {
                    Caption = 'Id';
                    Editable = false;
                }
                field(number; Rec."No.")
                {
                    Caption = 'Number';
                }
                field(name; Rec.Name)
                {
                    Caption = 'Name';
                }
                field(city; Rec.City)
                {
                    Caption = 'City';
                }
            }
        }
    }
}

This pattern follows Microsoft's documented API page model. The API properties determine the route, while the layout determines which fields are exposed. citeturn0search0turn0search2

Understanding the important API properties

PageType

PageType = API; identifies the page as an API endpoint. It is not a normal list, card or document page and cannot be displayed as a user-interface page. citeturn0search2

APIPublisher

Defines the publisher portion of the custom API route. Use a stable, lowercase identifier for your integration namespace.

APIGroup

Groups related APIs. For example, integration could contain customer, product and order endpoints belonging to the same integration family.

APIVersion

Defines the API version, such as v1.0. Versioning is important because external systems depend on the API contract.

EntityName and EntitySetName

EntityName is the singular entity name and EntitySetName is the collection name used in the endpoint. Microsoft recommends the documented API naming conventions, including camelCase for these identifiers. citeturn0search2

ODataKeyFields

For custom APIs, Microsoft recommends using a single GUID field such as SystemId as the OData key. This provides a unique, immutable identifier and improves compatibility with external integrations. citeturn0search0

SourceTable

Defines the Business Central table that supplies the API data. Keep the API contract focused and expose only the fields that external consumers actually need.

DelayedInsert

DelayedInsert = true; is commonly used on API pages and is included in Microsoft's API page examples.

How the custom API URL is constructed

For a custom API, the route contains the publisher, group and version from your AL object. A typical Business Central Online endpoint has this structure:

https://api.businesscentral.dynamics.com/v2.0/{environment}/api/{publisher}/{group}/{version}/{endpoint}

For a company-specific request, the company can be included in the route:

https://api.businesscentral.dynamics.com/v2.0/{environment}/api/dynexal/integration/v1.0/companies({companyId})/customers

Microsoft documents the current endpoint structure and explains that a company can also be supplied as a query parameter. citeturn0search1

Example: a custom Customer API

Assume the API uses:

The collection endpoint would conceptually be:

GET https://api.businesscentral.dynamics.com/v2.0/{environment}/api/dynexal/integration/v1.0/companies({companyId})/customers

Replace the environment and company identifiers with the values from your own Business Central tenant.

GET: read records

The simplest first test is a GET request. It confirms that the endpoint exists, the authentication works and the calling identity can read the exposed data.

GET /api/dynexal/integration/v1.0/companies({companyId})/customers

You can request an individual record using its API key where appropriate:

GET /api/dynexal/integration/v1.0/companies({companyId})/customers({id})
Development tip: test a simple GET before attempting POST, PATCH or DELETE. It makes endpoint and authentication problems easier to isolate.

POST: create a record

API pages support create operations. The JSON body must contain fields exposed by the API and accepted by the underlying table.

POST /api/dynexal/integration/v1.0/companies({companyId})/customers
Content-Type: application/json

{
  "number": "DYN-1001",
  "name": "Dynexal Demo Customer",
  "city": "Noida"
}

The exact writable fields depend on your API definition and Business Central table behavior. Do not assume that every source-table field should be exposed.

PATCH: update a record

PATCH is commonly used when an external application needs to update selected fields on an existing API resource.

PATCH /api/dynexal/integration/v1.0/companies({companyId})/customers({id})
Content-Type: application/json

{
  "city": "Delhi"
}

For production integrations, follow the API's concurrency and request requirements and use the response to determine whether the update succeeded.

DELETE: remove a record

API pages support delete operations by default, but deletion can be disabled using the API page properties when appropriate. Microsoft documents InsertAllowed, ModifyAllowed and DeleteAllowed for controlling these operations. citeturn0search2

DELETE /api/dynexal/integration/v1.0/companies({companyId})/customers({id})
Production warning: do not expose DELETE simply because the platform supports it. Evaluate business rules, permissions, audit requirements and recovery procedures before allowing external systems to delete ERP records.

Restricting API operations

If an endpoint should be read-only, restrict write operations in the API page. For example:

InsertAllowed = false;
ModifyAllowed = false;
DeleteAllowed = false;

This is useful for APIs that are intended only to provide data to a website, analytics application or reporting service.

Authentication and permissions

Publishing an API endpoint does not mean that every anonymous internet user can access it. Business Central integrations normally authenticate through Microsoft Entra ID and the calling identity must have the appropriate Business Central permissions.

Think of security in two layers:

  1. Authentication: verifies the identity of the application or user.
  2. Authorization: determines which Business Central resources and operations that identity can use.

Use the authentication flow appropriate for your application architecture and never place production secrets or access tokens directly in AL source code or public Git repositories.

Testing a custom API with Postman

Postman is a convenient way to validate an endpoint before connecting it to a website or middleware platform.

  1. Create a new HTTP request in Postman.
  2. Select GET.
  3. Enter the custom API URL.
  4. Configure the required authentication.
  5. Send the request.
  6. Check the HTTP status and JSON response.

After GET works, test POST with non-production data. Then test PATCH and DELETE only if those operations are actually required.

Never publish: real access tokens, client secrets, passwords or production customer data in screenshots, tutorials or GitHub repositories.

Common errors and troubleshooting

404 Not Found

Check the environment name, publisher, group, version, endpoint name and company ID. A single spelling or casing difference can produce a different route.

401 Unauthorized

The request is not authenticated correctly. Check the access token, authentication configuration and token validity.

403 Forbidden

The identity is authenticated but does not have the required Business Central permissions.

400 Bad Request

Inspect the JSON body and field names. The payload may contain an unsupported field, invalid data type or missing required information.

409 Conflict

The request can conflict with the current resource state or concurrency requirements. Review the API response and retry logic rather than blindly repeating the request.

API exists but a field is missing

Check the API page layout. A field must be exposed by the API page if the external client needs to read or write it.

API page vs API query

Use an API page when the external application needs a custom entity with read/write behavior. Use an API query when you need a read-only endpoint that combines data from multiple sources. Microsoft specifically documents API queries as read-only and suitable for joining data from different sources. citeturn0search6

Custom API relationships

Related API entities can be exposed using API page parts and relationships. Microsoft recommends making relationship fields available in the API pages and using appropriate SystemId-based links so the platform can generate referential constraints for consumers. citeturn0search0

For example, an order API could expose related order lines through a navigation property instead of building a large custom JSON structure manually.

Versioning strategy

Once another system depends on your API, the endpoint becomes a contract. Avoid breaking changes to a published version whenever possible.

Best practices for production custom APIs

Real-world integration example

Imagine a website where customers place orders. A practical architecture could be:

Customer Website
       |
       v
Integration / Middleware
       |
       v
Business Central Custom API
       |
       v
AL Business Logic
       |
       v
Business Central Tables

The custom API provides a stable contract, while the AL application handles validation and business rules. This separation makes the integration easier to maintain than exposing every internal table field directly.

Custom API checklist

What should you learn next?

Business Central API Integration — understand the wider REST API architecture and endpoint concepts.

HttpClient in Business Central AL — learn how AL calls external REST APIs.

JSON Handling in Business Central AL — parse and build API request/response payloads.

Codeunits in Business Central — keep reusable integration logic in dedicated AL codeunits.

AL Event Subscribers — build event-driven extensions around Business Central processes.

← Explore all Dynexal tutorials