Skip to main content

Integration Guide — Price Table

Microservice: XDPeople.Soba.WebAPI (Core API)
Authentication: Bearer token (JWT) and tenant context — see Combined Login


Introduction

This guide describes how to integrate with the API to manage price lines (price tables) within the SOBA ecosystem. A price line consists of a header (PriceTableDTO) and lines (PriceTableItemDTO), each associated with an article (Item) or an article family (ItemGroup).

The model distinguishes two table types in the priceTableType field:

ValueName (enum)Meaning
0AbsoluteExplicit prices per article; may include family-type lines (ItemGroup) as per the model; the API requires at least one line in items.
1RelativeVariation relative to an absolute reference line (absolutePriceLineId); additional rules apply on save.

Each line in items uses itemType:

ValueName (enum)Meaning
0ItemIndividual article (itemKeyId = article key).
1ItemGroupArticle family (itemKeyId typically the family identifier as text).

The goal is to support integrators in correctly using the endpoints, constructing the JSON body, and anticipating validations and errors returned by the server.


Business Rules and Limits

The rules below are applied in the application service before persisting data. Violating any of them returns an error with the indicated code (typical API format — see HTTP error documentation).

RuleDetailError Code (example)
Relative tableIf priceTableType is Relative (1), absolutePriceLineId cannot be invalid (value strictly less than 0).PriceTableValidation.InvalidAbsolutePriceLine
Absolute tableIf priceTableType is Absolute (0), the items list must exist and contain at least one element.PriceTableValidation.AbsolutePriceLineRequiredItems
Date rangestartDate cannot be later than endDate.PriceTableValidation.InvalidDateInterval
Identifiers 0–5Reserved in the product (cost price and price lines 1 to 5). For new lines configurable by the integrator, prefer the identifier returned by GET /gateway/price-table/next-id (≥ 6).see GET /gateway/price-table/next-id

It is recommended to obtain the next identifier with GET /gateway/price-table/next-id before creating a new line to avoid collisions and respect the minimum configured on the server.


Payload Mandatory Fields and Consistency by priceTableType

The value of priceTableType changes the server validations and the set of fields that must be consistent in the JSON.

Absolute table (priceTableType = 0)

AspectWhat to ensure
Mandatory (API)items must exist and have at least one element. Otherwise: PriceTableValidation.AbsolutePriceLineRequiredItems.
ConsistencyFill discountPercentage1, discountPercentage2, discountPercentage3 in the header when the business model applies global discounts; replicate or complement per line in items as needed.
ConsistencyAlign isTaxIncludedPrice in the header with the pricing criterion in the lines: if the main price includes VAT, use taxIncludedPrice and isTaxIncludedPrice: true in relevant entries; otherwise, prefer netPrice and isTaxIncludedPrice: false.
DatesstartDate cannot be later than endDate (validation common to both types).

Relative table (priceTableType = 1)

AspectWhat to ensure
Mandatory (API)absolutePriceLineId cannot be less than 0. Otherwise: PriceTableValidation.InvalidAbsolutePriceLine. In practice, it must identify an existing and valid absolute price line in your context (reference for relative calculation).
ConsistencySet percentageReference according to the intended global percentage adjustment (value and sign per your convention for increase or discount). The DTO exposes only percentageReference; do not send properties not in the contract.
ConsistencyIn items, each article or family (itemType) must include the percentage discounts (discountPercentage13) and other fields required by the relative price flow they implement. Without lines, confirm with your business analyst if a relative table without items is allowed in the product — the current CanSave validation does not require lines for the relative type.
DatesSame rule as in the absolute table (startDate / endDate).

Fields common to both types

id, description, startDate, endDate, and priceTableType must always be validly defined in the request. Other fields of PriceTableDTO remain in the contract; default values (e.g., 0) are acceptable only if semantically correct for the use case.


Available Endpoints

All paths below assume the public prefix /gateway/price-table (Core API via gateway).

MethodURLBrief Description
GET/gateway/price-tableLists price lines with optional pagination.
GET/gateway/price-table/next-idReturns the next suggested identifier (minimum 6).
GET/gateway/price-table/{id}Retrieves a line by identifier, including items.
POST/gateway/price-tableCreates a new price line. 201 Created response on success.
PUT/gateway/price-table/{id}Updates the specified line. 204 No Content response on success.
DELETE/gateway/price-table/{id}Deletes the specified line. 204 No Content response on success.

List Price Lines

URL: /gateway/price-table

Method: GET

Query Parameters (optional):

ParameterTypeDescription
pageintPage number (base 1), when applicable.
pageSizeintPage size.

Behavior: returns a paginated list of price tables.

See more →


Get Next Identifier

URL: /gateway/price-table/next-id

Method: GET

Behavior: returns an integer with the next suggested ID, not less than 6, for new custom price lines.

See more →


Get a Line by Identifier

URL: /gateway/price-table/{id}

Method: GET

Route Parameter:

ParameterTypeRequiredDescription
idintYesPrice line identifier.

Behavior: returns PriceTableDTO with the items collection populated when present.

See more →


Create Price Line

URL: /gateway/price-table

Method: POST

Body: JSON in the PriceTableDTO model (see field tables below).

Success behavior: 201 Created (no response body in the current controller).

See more →


Update Price Line

URL: /gateway/price-table/{id}

Method: PUT

Parameters: id in route; body PriceTableDTO.

Success behavior: 204 No Content.

See more →


Delete Price Line

URL: /gateway/price-table/{id}

Method: DELETE

Success behavior: 204 No Content.

See more →


Body Structure (PriceTableDTO)

Most relevant fields for integration (other synchronization or cloud fields may be omitted or null depending on the use case). Rules by table type are in Payload Mandatory Fields and Consistency by Type.

FieldTypeMandatory (API / validation)Description
idintYes in practiceLine identifier.
descriptionstringYes (max 20 characters)Short description.
priceTableTypeint (enum)Yes0 Absolute, 1 Relative.
startDatedate-timeYesEffective start date.
endDatedate-timeYesEffective end date (cannot be earlier than startDate).
absolutePriceLineIdintConditionalMandatory and consistent for relative type (reference to absolute line; server validation disallows negative).
percentageReferencedecimalNoGlobal percentage reference (sign may indicate increase or discount per client convention).
discountPercentage1decimalNoDiscount 1 (%).
discountPercentage2decimalNoDiscount 2 (%).
discountPercentage3decimalNoDiscount 3 (%).
isTaxIncludedPriceboolNoWhether prices in lines are treated as tax included.
inactiveboolNoInactive line.
itemsarrayConditionalMust have elements for absolute type.

Structure of Each Line (PriceTableItemDTO)

FieldTypeDescription
priceLineIdintPrice line identifier within the table context.
itemKeyIdstringArticle key or identifier used for family, according to itemType.
itemAttributeCodestringArticle attribute code, when applicable.
itemTypeint0 Article, 1 Family.
descriptionstringDisplayable description.
percentageReferencedecimalPercentage reference at the line level.
discountPercentage1decimalDiscount 1 (%).
discountPercentage2decimalDiscount 2 (%).
discountPercentage3decimalDiscount 3 (%).
netPricedecimalNet price.
taxIncludedPricedecimalPrice including tax.
isTaxIncludedPriceboolWhether the line price includes tax.
itemPriceLineIdint?Reference price line per article (when used in the product).

Example Create Request (Absolute Table)

Illustrative JSON body (example values):

{
"id": 14,
"description": "Line 14",
"startDate": "2026-05-13T10:15:58.222Z",
"endDate": "2026-05-14T10:15:58.222Z",
"priceTableType": 0,
"absolutePriceLineId": 0,
"percentageReference": 0,
"discountPercentage1": 1,
"discountPercentage2": 0,
"discountPercentage3": 0,
"isTaxIncludedPrice": true,
"inactive": false,
"items": [
{
"priceLineId": 14,
"itemKeyId": "1",
"itemAttributeCode": "",
"itemType": 0,
"description": "Dom Diogo (Arinto)",
"percentageReference": 0,
"discountPercentage1": 1,
"discountPercentage2": 0,
"discountPercentage3": 0,
"netPrice": 0,
"taxIncludedPrice": 0,
"isTaxIncludedPrice": true,
"itemPriceLineId": null
}
]
}

Example Create Request (Relative Table)

{
"id": 15,
"description": "Line 15",
"startDate": "2026-05-13T10:15:58.222Z",
"endDate": "2026-05-14T10:15:58.222Z",
"priceTableType": 1,
"absolutePriceLineId": 1,
"percentageReference": 10,
"discountPercentage1": 0,
"discountPercentage2": 0,
"discountPercentage3": 0,
"isTaxIncludedPrice": false,
"inactive": false,
"items": [
{
"priceLineId": 15,
"itemKeyId": "3",
"itemAttributeCode": "",
"itemType": 1,
"description": "Meats",
"percentageReference": 0,
"discountPercentage1": 0,
"discountPercentage2": 0,
"discountPercentage3": 0,
"netPrice": 0,
"taxIncludedPrice": 0,
"isTaxIncludedPrice": false,
"itemPriceLineId": null
}
]
}

Notes on the Payload (API Only)

  • The integrator must send JSON conforming to PriceTableDTO and PriceTableItemDTO. The validations described in this guide apply to any API client system.
  • The section Payload Mandatory Fields and Consistency by Type summarizes what the integrator must send or align per priceTableType, in addition to the generic validations below.
  • In a relative table (priceTableType = 1), fill absolutePriceLineId consistently with the absolute reference line (the API rejects invalid references according to server rules).
  • In an absolute table (priceTableType = 0), the items list must have at least one entry.
  • The fields discountPercentage1, discountPercentage2, discountPercentage3, and percentageReference exist in the contract both in the header and in the lines; they can be used according to your pricing model, provided the set respects server validations.
  • Bulk load: there is no dedicated resource for file import; build items in your system and use POST or PUT.

Common Errors

CodeTypical TypeMeaning and Suggested Action
PriceTable.NotFound404Nonexistent identifier in retrieval, update, or deletion.
PriceTableCreate.Fail409 / failureCreation persistence failed; review data and retry; contact support if it persists.
PriceTableUpdate.Fail409 / failureUpdate failed during storage.
PriceTableDelete.Fail409 / failureDeletion failed during storage.
PriceTableValidation.InvalidAbsolutePriceLine400Relative table with invalid absolute reference (absolutePriceLineId negative).
PriceTableValidation.AbsolutePriceLineRequiredItems400Absolute table without lines in items.
PriceTableValidation.InvalidDateInterval400startDate later than endDate.

Error responses follow the API HTTP standard (Problem Details / HttpResponseError depending on version). Always validate the HTTP code and error payload.


Conclusion

Managing price lines via Core API boils down to CRUD operations on /gateway/price-table, with clear validations for absolute and relative types and for the date range. It is recommended to test all scenarios in a staging environment (creation with next-id, partial update of items, relative tables with valid reference, and validation errors) before production.


Last updated: May 13, 2026