Create API Endpoints
This page explains how to create API endpoints for tables using Simple Object Designer.
Accessing API Creation
- Open Expose Data > Expose data as web service APIs
- The API Endpoints page opens
- View existing endpoints or create new ones
The API Endpoints Page
Columns
| Column | Description |
|---|---|
| Table No. | Source table ID |
| Table Name | Source table name |
| Group | API grouping category |
| Entity Name | API entity identifier |
Actions
| Action | Purpose |
|---|---|
| Create API from Page | Generate API based on existing page |
| New | Create API manually |
Creating an API Endpoint
Method 1: From Page (Recommended)
Use an existing page as a template:
- Click Create API from Page
- Select a page that shows the table you want to expose
- SOD creates an API with fields matching the page
- Adjust configuration as needed
Method 2: Manual Creation
Create from scratch:
- Click New
- Select the source table
- Configure the API properties
- Add fields manually
API Configuration Steps
Step 1: Select Table
- Click the Table lookup
- Browse available tables
- Select the table to expose
Tables available include:
- Standard BC tables (Customer, Item, etc.)
- Custom tables from extensions
- SOD feature tables
Step 2: Configure Entity Names
| Field | Purpose | Example |
|---|---|---|
| Entity Name | Singular name | customEquipment |
| Entity Set Name | Plural collection | customEquipments |
| Entity Caption | Display name | Custom Equipment |
| Entity Set Caption | Collection display | Custom Equipments |
Naming Guidelines
- Use camelCase for API names
- Keep names concise but descriptive
- Follow REST conventions
- Avoid special characters
Step 3: Select Fields
Choose which fields to include in the API:
- Open the API Page Card
- Navigate to Field List
- Check/uncheck fields to include
Field Selection Considerations
Include:
- Every field of the primary key — see below
- Essential business data
- Fields needed by consumers
Exclude:
- Internal system fields
- Sensitive data
- Unnecessary fields
- Fields whose name starts with a number — these are not supported in API endpoints and will make publishing fail. Unselect them and republish.
- Blob fields such as Work Description — they commonly break external consumers like Power BI
Tables with Composite or Option Keys (Sales Header, Sales Line, …)
Some standard tables have a primary key made of several fields, and one of them may be an Option/Enum field. Sales Header and Sales Line are the classic examples: their primary key includes Document Type.
Every field that forms the primary key must be included in the API. If a key field is missing, the entity cannot resolve its key and the endpoint fails — the OData feed itself errors, even before the consuming tool has selected any fields.
This is why Item and Vendor APIs "just work" while Sales document APIs error: the simpler tables have simple keys, whereas sales documents need the whole composite key, Option field included, exposed.
Diagnostic: when an endpoint fails, inspect the generated API page object and compare the exposed field list against the source table's primary key fields.
Verifying what was actually published
After adding a field, republishing and downloading the .app, the generated API page contains an explicit field(...) declaration per included field, for example:
field(documenttype; Rec."Document Type")
field(billtoaddress2; Rec."Bill-to Address 2")
If the declaration for a field you intended to add is missing, the published endpoint still reflects the previous field set.
Property names in the generated source are lowercase, normalized forms of the source field name with spaces and special characters removed: "Document Type" → documenttype, "Sell-to Customer No." → selltocustomerno_, "No." → no_.
Step 4: Set Group
Assign the API to a group:
- Select or create a group name
- Group organizes APIs logically
- Appears in API discovery
Step 5: Publish
Publish your extension to make the API available.
Field Configuration
The API Page Field List
| Column | Description |
|---|---|
| Field Name | Source field name |
| Type | Source field type |
| Class | AL field class (Normal, FlowField, etc.) |
| Included | Whether to expose this field |
| ObsoleteState | Whether the source field is obsolete |
Customizing Field Names
The underlying API page field record supports an OverrideName value so the API exposes a different property name than the source field. Edit it on the field's setting card. The override is not shown as a column on the field list page.
Field Types
Most field types expose via API:
| Type | API Representation |
|---|---|
| Text, Code | String |
| Integer | Integer |
| Decimal | Decimal number |
| Boolean | Boolean |
| Date | Date string |
| DateTime | DateTime string |
| Enum/Option | String (value name) |
| FlowField | Calculated automatically (see below) |
FlowFields on API Pages
FlowFields are automatically calculated when included in an API endpoint. Business Central runs CalcFields for each FlowField on every record returned by the API, so their values are always up to date. The AutoCalcField property does not apply to API pages and should not be set.
Performance note: Each FlowField adds a calculation per record. Only include FlowFields that API consumers actually need, as unnecessary FlowFields can significantly slow down API responses on large data sets.
Caution: some standard FlowFields break Business Central updates. Certain standard-table FlowFields — on the Item table,
Coupled to DataverseandService Commitment Optionare known examples — cause a Business Central update or deployment to fail when they are included in an API. If a FlowField-related error appears during an update, remove the offending FlowField(s) from the API and republish. Use the Class column in the field list to see which included fields are FlowFields.
System Fields
Business Central maintains system fields on every table: SystemId, SystemCreatedAt, SystemCreatedBy, SystemModifiedAt and SystemModifiedBy. The data always exists and can be seen in the Page Inspection panel.
- SOD's feature field configuration only manages user-defined fields. System fields are not listed there and cannot currently be selected.
SystemIdis exposed in the generated API response, as the"id"property in the JSON output.SystemModifiedAtis not currently included automatically in feature-generated API pages.
There is at present no way inside SOD's feature configuration to add a system field such as SystemModifiedAt to the API output; doing so would require a code-level change to the generated API page (setting ODataSystemFields = true, or including the field explicitly). This matters most for incremental refresh scenarios in Power BI and data warehousing, which rely on SystemModifiedAt.
Support for exposing system fields in feature-generated APIs is planned for an upcoming release.
Parent and Child Tables
SOD does not expose a parent and its child table as a single nested API entity.
- Expose each table — parent and every related sub-table — as its own separate endpoint
- Deep insert and nested writes are not supported; insert child records through the child table's endpoint
$expandis not available, because SOD-generated APIs declare no navigation properties
Consumers join the two datasets on their shared key fields. See Consuming APIs.
Category Fields Live on the Parent Table
When you add a classification or category field to an existing table using a Data Table or Related Table feature, the value lives on the parent record.
Querying the API for the category table itself returns only the category definitions — the distinct values — not the business records carrying them. To get parent records together with their category values:
- Create an API endpoint on the parent table
- Include the category/classification field in its field selection
- Publish
- Consume that parent-table endpoint
Enum Fields and the Companion Text Field
The API card includes a helper function, Add Enum Companion Text Field.
It adds an extra field exposing the unencoded value of an enum or option field, which avoids the x0020 encoded output that Microsoft's API layer now produces for values containing spaces. Downstream consumers such as Power Automate can then read the readable value.
If the function is not on your API card, update SOD — see Updating SOD. Background and the full symptom are in Consuming APIs.
Force Lowercase
The Force lowercase setting is on the API card, in the right column.
- Enabled — field names are forced to lowercase, so OData field references are not case sensitive
- Disabled — OData field names are case sensitive
This setting exists only for API cards, not for APIs generated from Features, and requires a recent SOD version.
API Page Object IDs and Publish Behaviour
SOD assigns object IDs sequentially, based on the order objects are created and processed at publish time. As a result, API page object IDs can shift when objects are added, removed, or reordered between publishes.
This is by design for general customization scenarios, but it is a real limitation if something external references APIs by page object ID: object IDs for API pages are not guaranteed to be stable across publishes, and there is currently no way to pin or lock them.
How to keep IDs as stable as possible:
- Freeze the order. Once the APIs exist in the order you want, avoid inserting new APIs between existing ones. Adding new APIs at the end of the list leaves previously assigned IDs untouched.
- Leave room. If you expect to add more APIs, allocate a dedicated, well-spaced object number range up front.
For external tooling — including MCP servers — reference APIs by entity name, not by page object ID. Entity names (the API's entity / entity set name) are stable and change only when you rename them deliberately, so a configuration built on entity names is unaffected by ID reshuffling.
Creating APIs for Feature Tables
From Feature Card
- Open your feature in Feature List
- Click API Endpoints
- Configure the API
Automatic Exposure
When creating features with API enabled:
- API is pre-configured
- Adjust entity names if needed
- Modify field selection
Verifying API Creation
Check in SOD
- Return to API Endpoints list
- Verify your API appears
- Review configuration
After Publishing
- Test the endpoint URL
- Verify authentication works
- Check data returns correctly
Multiple APIs Per Table
You can create multiple APIs for one table:
- Different field selections
- Different use cases
- Different consumer needs
Example:
customers- Full customer data for admincustomersBasic- Limited fields for reporting
Modifying APIs
Adding Fields
- Open API configuration
- Add fields to the list
- Republish
Removing Fields
- Open API configuration
- Remove fields from the list
- Republish
- Note: May break existing consumers
Changing Entity Names
- Modify entity name configuration
- Republish
- Warning: Changes the URL - breaks existing consumers
Best Practices
Entity Naming
- Use clear, descriptive names
- Follow organization standards
- Consider consumer perspective
- Be consistent across APIs
Field Selection
- Start minimal, add as needed
- Document exposed fields
- Consider security implications
- Think about data volume
Versioning
- Plan for API evolution
- Consider naming conventions for versions
- Document changes for consumers
Troubleshooting
API Not Appearing
Check:
- Extension published successfully — and without errors. A partial or failed publish means the endpoints do not exist, even though the configuration looks correct
- The generated customer app is Installed in Extension Management
- API configuration complete
- Table accessible
Fields Missing
Check:
- Fields included in configuration
- Fields exist on source table
- Field types supported
- The generated API page source actually contains the
field(...)declaration
Field removed by a BC upgrade: if a BC upgrade fails because an endpoint references a field Microsoft removed or relocated, edit the endpoint's field list, set the removed field to Included = No, and republish. Make sure SOD is on the latest version first. See Business Central Updates.
Obsoleted fields before an upgrade: if a field exposed in an API becomes obsoleted in a new BC release, the extension is reported as incompatible with that version. Exclude the obsoleted field(s) and republish before upgrading the environment. The ObsoleteState column in the field list shows which included fields are affected.
Publish Fails on a CRM / CDS / Dataverse Table
Exposing a table whose name contains "CRM", "CDS" or "DataVerse" makes publishing fail with:
using RegisterTableConnection or cmdlet New-NAVTableConnection before it can be used.
These tables need a registered table connection and are not supported as SOD API endpoints. Remove the endpoint from the API Endpoints list and republish.
Publish Fails on an Obsoleted Table
If you built an API on a table that has since been obsoleted or removed from Business Central, publishing fails. The error names the table and states that it is obsoleted, and SOD reports "Page Simple Object Designer has to close."
Fix: open Expose Data > Expose data as web service APIs, delete the endpoint whose source table was removed, and republish.
Publish Fails on an Empty API Definition
An API endpoint that exists but has nothing configured causes publishing to fail. Delete the empty definition and republish. When diagnosing publish errors after creating a new API, scan the API Endpoints list for stray or empty entries.
The Error May Come from a Query, Not an API
Publish errors that appear while you are working on APIs sometimes originate from a query object. Read the object named in the error message, and see Create Queries for query-specific validation errors such as a missing root element.
AL0185: Codeunit 'NoSeriesManagement' is missing
After a BC v27 upgrade, generated code referencing the legacy NoSeriesManagement codeunit fails with this error. Update SOD to a version that handles the new number series implementation — the fix shipped in 12.0.0.621 or later — and republish.
Template Not Applied on Records Created via POST
Symptom: a record created through the API does not have its Business Central template applied.
Cause: SOD table APIs perform standard CRUD inserts. Template application is not part of API record creation.
Resolution: templates cannot be triggered through the table API. Expose the template as a separate API and set the relevant values explicitly from the consuming application.
Permission Errors
Check:
- User has table permissions
- The Entra application has the app's permission set assigned — Azure AD API permissions alone are not enough
- The identity has page-level permission to the generated API page objects
- Permissions are assigned for the company being accessed
- BC license valid
See Consuming APIs for the full two-layer permission model.