Integration Guide — Extra Tables and Fields
Microservice: XDPeople.Soba.WebAPI (Core API)
Authentication: Bearer token (JWT) and tenant context — see Combined Login
Introduction
The extra tables and fields functionality allows defining, per entity type, a set of logical tables and fields with persistence in physical tables in the database, as well as values per entity instance (by primary key).
Two groups of endpoints cover distinct cases:
- Configuration — create, modify, and remove tables and fields; retrieve the complete configuration for the
{entityTypeName}segment in the route. - Values — read and write (upsert) extra values for one instance, identified by
entityKeyId.
See Entity Type Identifier for supported {entityTypeName} values in routes.
Prefix and Routes
| Area | URL Prefix |
|---|---|
| Configuration | /gateway/extra-tables-fields-config/{entityTypeName} |
| Values | /gateway/extra-fields-values/{entityTypeName} |
The segments {entityTypeName} and {entityKeyId} must be URL-encoded when containing reserved characters.
Entity Type Identifier (entityTypeName)
The {entityTypeName} segment in the URL is the type identifier recognized by the server. The comparison is case-insensitive. Any other value returns ExtraTablesAndFields.UnsupportedEntityType.
entityTypeName | entityKeyId in values |
|---|---|
AccountHeadingBE | integer |
AccountTypeBE | integer |
AdvancedDiscount | text up to 50 characters |
BusinessAccount | integer |
EntityContactsBE | integer |
Entity | text up to 25 characters |
EntityAddress | integer |
EntityGroups | integer |
EntityTypes | integer |
FixedExpensesAndRevenues | integer |
ItemBarcodeBE | integer |
ItemBE | text up to 60 characters |
ItemGroupBE | integer |
LoadUnloadPlaceBE | integer |
PointsConfig | GUID |
PriceTable | integer |
SalesPromoBE | integer |
SalesZone | integer |
UserBE | integer |
UserGroupBE | integer |
WarehouseBE | integer |
XDfree01 | text up to 25 characters |
XDfree02 | text up to 25 characters |
XDfree03 | text up to 25 characters |
XConfigCurrency | integer |
XConfigItemUnit | integer |
XConfigPaymentMode | integer |
XConfigPaymentType | integer |
The entityTypeName field in the JSON body of the GET configuration corresponds to the value requested in the route.
Physical Table Name
For each logical table named Name and entity type entityTypeName, the physical table follows the pattern:
{Name}_{entityTypeName_lowercase}_extrafields
Example: logical table Extras with entityTypeName ItemBE → Extras_itembe_extrafields.
This name appears in the configuration response as physicalTableName.
Endpoints — Configuration
Base: /gateway/extra-tables-fields-config/{entityTypeName}
| Method | URL | Description | Success Response |
|---|---|---|---|
| GET | /gateway/extra-tables-fields-config/{entityTypeName} | Lists tables and their respective fields. | 200 — body ExtraFieldsConfigurationResponse |
| POST | /gateway/extra-tables-fields-config/{entityTypeName}/tables | Creates a logical table and the physical table. | 200 — created table body |
| PUT | /gateway/extra-tables-fields-config/{entityTypeName}/tables/{tableGuid} | Updates table metadata (does not change logical name). | 204 |
| DELETE | /gateway/extra-tables-fields-config/{entityTypeName}/tables/{tableGuid} | Removes configuration, associated fields, and drops the physical table. | 204 |
| POST | /gateway/extra-tables-fields-config/{entityTypeName}/tables/{tableGuid}/fields | Creates a field (physical column). | 200 — created field body |
| PUT | /gateway/extra-tables-fields-config/{entityTypeName}/fields/{fieldGuid} | Updates field metadata (does not change name or type). | 204 |
| DELETE | /gateway/extra-tables-fields-config/{entityTypeName}/fields/{fieldGuid} | Removes the field and drops the column from the physical table. | 204 |
Configuration Body (GET /gateway/extra-tables-fields-config/{entityTypeName})
Main properties (JSON in camelCase):
| Property | Type | Description |
|---|---|---|
entityTypeName | string | Same as the identifier used in the request route segment (the server returns it back in the body). |
tables | array | Logical tables ordered in the response. |
Each element of tables:
| Property | Type | Description |
|---|---|---|
guid | string | Unique identifier of the table in the configuration. |
order | number | Display order (≥ 0). |
name | string | Logical table name (identifier). |
description | string | Descriptive text (can be empty on creation). |
permissionType | number | See Table Permissions. |
allowInDocuments | boolean | Permission to use in documents. |
allowMultipleRegistries | boolean | If true, the table allows multiple records per entity; see Values per Instance. |
physicalTableName | string | Database table name. |
fields | array | Table fields. |
Each element of fields:
| Property | Type | Description |
|---|---|---|
guid | string | Unique identifier of the field. |
order | number | Order (≥ 0). |
name | string | Logical column name. |
description | string | Description (mandatory on creation; 1–500 characters). |
fieldType | string | Logical type; see Field Types. |
length | number | For String, maximum length; for Decimal, decimal places; otherwise follows server rules (1–16383). |
required | boolean | Field required in configuration. |
inactive | boolean | If true, the field is ignored when reading values. |
tableName | string | Logical table name to which the field belongs. |
values | object | Index → text map (options when applicable). |
canEditValues | boolean | Whether options are editable at runtime. |
entityType | string | null | Target entity type for lookup-style field; optional. |
Create Table (POST /gateway/extra-tables-fields-config/{entityTypeName}/tables)
| Property | Required | Rules |
|---|---|---|
name | yes | 1–25 characters; first character letter; rest letters or digits (^[a-zA-Z][a-zA-Z0-9]*$). |
description | yes | Up to 2000 characters; can be empty string. |
order | yes | ≥ 0. |
permissionType | yes | Between 0 and 2; see Table Permissions. |
allowInDocuments | yes | boolean |
allowMultipleRegistries | yes | boolean |
The server validates the logical name and rejects creation if a physical table with the derived name already exists (ExtraTablesAndFields.PhysicalTableExists).
Update Table (PUT /gateway/extra-tables-fields-config/{entityTypeName}/tables/{tableGuid})
Body: description, order, permissionType, allowInDocuments, allowMultipleRegistries (the logical table name cannot be changed via this endpoint).
Create Field (POST /gateway/extra-tables-fields-config/{entityTypeName}/tables/{tableGuid}/fields)
| Property | Required | Rules |
|---|---|---|
name | yes | Same identifier rules as logical table name (1–25, initial letter). |
description | yes | 1–500 characters. |
order | yes | ≥ 0. |
fieldType | yes | Non-empty string up to 16 characters; see Field Types. |
length | yes | 1–16383 (meaning depends on type). |
required | yes | boolean |
inactive | yes | boolean |
values | yes | Object with numeric keys and text values (can be {}). |
canEditValues | yes | boolean |
entityType | no | Up to 32 characters; empty or omitted = no lookup. |
Update Field (PUT /gateway/extra-tables-fields-config/{entityTypeName}/fields/{fieldGuid})
Body: description, order, length, required, inactive, values, canEditValues, entityType. The name and type of the field are not changed by this flow.
Table Permissions
Values of permissionType (aligned with internal enum):
| Value | Meaning |
|---|---|
0 | All users |
1 | Current user |
2 | User groups |
Field Types
Typical values of fieldType on creation (internally mapped to CLR and DDL types):
fieldType | Summary Usage |
|---|---|
String | Text; length = maximum text column length. |
LongText | Long text |
Int32 | Integer number. |
Decimal | Decimal; length = decimal places. |
Boolean | True/false. |
DateTime | Date and time. |
Date | Date (stored as date/time). |
Guid | Unique identifier. |
Image | Image |
Unrecognized types tend to be treated as text.
Endpoints — Values per Instance
Base: /gateway/extra-fields-values/{entityTypeName}
| Method | URL | Description | Success Response |
|---|---|---|---|
| GET | .../{entityKeyId} | Returns all extra values applicable to the instance. | 200 |
| PUT | .../{entityKeyId} | Writes values (upsert: inserts row if not existing, otherwise updates). | 204 |
Key Format
All keys in the values object use the format {logicalTableName}.{fieldName}, for example Extras.Notas.
Matching is case-insensitive on the key. Keys that do not correspond to any active field in a single-record table are ignored in PUT (do not cause error).
PUT Body
{
"values": {
"MyTable.TextField": "note",
"MyTable.DecimalField": 12.34,
"MyTable.BoolField": true
}
}
Conversion on Write
For each field, the server converts the received value according to the type:
fieldType | Treatment |
|---|---|
Int32 | Integer. |
Decimal | Decimal. |
Boolean | Boolean. |
DateTime, Date | Date/time (if received as text, interpreted on server). |
| Others | Persisted as text from the received value. |
Null or missing JSON values may be persisted as SQL NULL depending on the column.
GET Body
The same structure { "values": { "Table.Field": ... } }. For boolean, integer, and decimal types, the response normalizes to native JSON types; for other types the returned value reflects what came from the database (e.g., dates as string or native value, depending on the database driver).
Errors (Stable Codes)
Issues are returned in the gateway HTTP error format; relevant business codes:
| Code | Typical Situation |
|---|---|
ExtraTablesAndFields.UnsupportedEntityType | Unsupported entityTypeName. |
ExtraTablesAndFields.InvalidTableName | Invalid table or field name per identifier rules (same code used for field name validation on creation). |
ExtraTablesAndFields.TableNotFound | Unknown tableGuid for the type. |
ExtraTablesAndFields.FieldNotFound | Unknown fieldGuid (or inconsistent parent table on deletion). |
ExtraTablesAndFields.PhysicalTableExists | Physical table with generated name already exists. |
ExtraTablesAndFields.DdlFailed | Failure applying DDL (create/alter structure). |
ExtraTablesAndFields.SaveFailed | Failure saving configuration metadata. |
ExtraTablesAndFields.DeleteFailed | Failure deleting table/field. |
ExtraTablesAndFields.ReadValuesFailed | Failure reading values. |
ExtraTablesAndFields.SaveValuesFailed | Failure writing values. |
404 responses apply to missing table/field in configuration operations; 400 to entity type or payload validation; 500 to internal or DDL failures as mapped by the gateway.
Minimal Example (Configuration + Values)
- POST
/gateway/extra-tables-fields-config/ItemBE/tableswith body, for example:
{
"name": "Tabela",
"description": "Tabela 1",
"order": 2,
"permissionType": 0,
"allowInDocuments": false,
"allowMultipleRegistries": false
}
- With the returned table
guid
POST/gateway/extra-tables-fields-config/ItemBE/tables/cfbe5b29-5777-4c4a-84c3-68c065811ed7/fields.
{
"name": "Campo1",
"description": "Campo1 desc",
"order": 1,
"fieldType": "String",
"length": 255,
"required": true,
"inactive": false,
"values": {},
"canEditValues": false,
"entityType": "Entity"
}
- GET
/gateway/extra-tables-fields-config/ItemBE— retrieve existingtablesandfields(example for items).
{
"entityTypeName": "ItemBE",
"tables": [
{
"guid": "cfbe5b29-5777-4c4a-84c3-68c065811ed7",
"order": 2,
"name": "Tabela",
"description": "Tabela 1",
"permissionType": 0,
"allowInDocuments": false,
"allowMultipleRegistries": false,
"physicalTableName": "Tabela_itembe_extrafields",
"fields": [
{
"guid": "3d63058f-1df6-439e-9d9b-f04e55103d3c",
"order": 1,
"name": "Campo1",
"description": "Campo1 desc",
"fieldType": "String",
"length": 255,
"required": true,
"inactive": false,
"tableName": "Tabela",
"values": {},
"canEditValues": false,
"entityType": "Entity"
}
]
}
]
}
- Sending values PUT
/gateway/extra-fields-values/ItemBE/3
{
"values": {
"Tabela.Campo1": "2"
}
}
Last updated: May 14, 2026