JSON Representation
Objects are exchanged as flat JSON objects: one property per field, keyed by the field's name. Each data type has a fixed encoding, which is the same in request bodies (Create, Patch) and in responses (Get one, list rows). Relations are not embedded objects; they are URIs.
Data types
| Data type | JSON | Example |
|---|---|---|
TEXT | string | "Acme B.V." |
LONGTEXT | string | "Line one\nLine two" |
TEXTBLOCK | string of HTML | "<p>Signed on <b>1 March</b>.</p>" |
EMAIL | string | "jane.smith@example.com" |
INTEGER | number | 42 |
DECIMAL | number | 1234.5678 |
PERCENTAGE | number | 0.21 |
BOOLEAN | boolean | true |
DATE | string, yyyy-MM-dd | "2019-03-01" |
DATETIME | string, ISO-8601 with offset | "2026-09-24T09:12:31Z" |
TIME | string, ISO-8601 local time | "14:30" |
LIST | string, the list key | "bv" |
CURRENCY | object | { "currency": "EUR", "amount": 1250.50, "decimals": 2 } |
HYPERLINK | object | { "name": "Website", "href": "https://www.example.com" } |
MULTILINGUAL | object | { "defaultLanguage": "en", "translations": { "en": "Invoice", "nl": "Factuur" } } |
FILE, IMAGE | object | See Files. |
JSON | object or array | See JSON. |
SECRET | string, write-only | See SECRET. |
Text types
TEXT, LONGTEXT and TEXTBLOCK are plain strings.
TEXTBLOCKis HTML. On input it is sanitised: only a basic set of formatting tags and attributes is kept, and anything else, such as<script>, is removed.EMAILis checked against an e-mail address pattern. A value that doesn't match is rejected with400 Bad Request.
Numbers
INTEGER, DECIMAL and PERCENTAGE are JSON numbers in responses. On input, a numeric string ("42") is accepted as well.
INTEGERrejects a value with a fractional part (42.5).42.0is accepted and stored as42.DECIMALkeeps the precision it was sent with. There is no rounding and no floating-point conversion.PERCENTAGEis a fraction, not the percentage itself:1means 100%,0.21means 21%. The name refers to how the value is interpreted for display, not its scale — the generated UI formats it asvalue * 100with a%suffix.
Booleans
BOOLEAN is true or false. On input, true and the string "true" are true; any other value is stored as false, including "yes" and 1.
Dates and times
| Type | Input | Output |
|---|---|---|
DATE | yyyy-MM-dd | Same. |
DATETIME | ISO-8601 with an offset or Z: "2026-09-24T11:12:31+02:00", "2026-09-24T09:12:31Z". A value without an offset is rejected. | Always in UTC, with Z. |
TIME | HH:mm or HH:mm:ss, optionally with fractions of a second | Same format, without a time zone. |
A value in another format is rejected with 400 Bad Request. A DATE has no time zone.
Lists
A LIST field holds the key of an entry in the field's list, not its translated label. A key that is not in the list is rejected with 400 Bad Request (Unknown list value). Responses also return the key; the labels in each language come from the metadata.
Currency
{ "currency": "EUR", "amount": 1250.50, "decimals": 2 }
| Property | Required | Meaning |
|---|---|---|
currency | Yes | ISO 4217 currency code. |
amount | Yes | The amount as a number. An object whose amount is null or missing counts as an empty value, which clears the field. |
decimals | No | The number of decimals to keep. If you set it, the amount is rounded to that number of decimals (half up); if you leave it out, the amount is stored as sent. Responses always include it, as null when it isn't set. |
Hyperlinks
{ "name": "Website", "href": "https://www.example.com" }
href must be a valid absolute URL, or the value is rejected with 400 Bad Request. name is optional; when it is missing, responses show the href as the name.
Multilingual text
{
"defaultLanguage": "en",
"translations": { "en": "Invoice", "nl": "Factuur", "de": "Rechnung" }
}
translations maps a language code to the text in that language, and defaultLanguage names the main language. Both properties are required, and the request always replaces the whole value — to change one translation, send all of them.
Files
FILE and IMAGE fields have the same encoding. In responses they are an object with a download link:
{
"contentType": "application/pdf",
"fileName": "signed-contract.pdf",
"size": 48213,
"href": "/data/2f9c6e1a-7b34-4d58-9c21-0a5e8f1b2c3d/download/c4a9e2f7-1b6d-4e38-9f05-8a3d7b2c6e91/3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
On input, the value is the object returned by the upload, with a /binaries/{id} href. A file that is already attached may also be sent back as just its href string. The whole flow is described in Files.
JSON
A JSON field holds structured data written by the platform itself, such as the output of an AI task or a gateway. In responses it is returned as the JSON object or array it contains; a value that isn't valid JSON is returned as a string. See Data Types › JSON.
SECRET
A SECRET field is write-only. You send it as a string in a create or patch. It is never included in a response, not even masked — the property is simply absent. Only scripts can read the stored value. See Data Types › SECRET.
Multiple values
A field with multiple: true is a JSON array of values of its data type, in both directions:
{ "tags": ["urgent", "tax", "2026"] }
On input, null entries are skipped and duplicate values are stored only once. An empty array clears the field.
Fields with history
A field with historyEnabled: true keeps its earlier values, each with the date until which it was valid. Such a field is an object in responses:
{
"legalName": {
"current": "Acme Holding B.V.",
"history": [
{ "value": "Acme B.V.", "until": "2024-06-30" }
]
}
}
On input you can send either form:
- The full object:
currentandhistoryare both stored as sent. Use this to add or correct a history entry: read the field, change it, and send the whole object back. - A plain value (
"legalName": "Acme Group B.V."): it becomes the newcurrent, and the stored history is discarded. To change a field with history without losing its history, send the full object with the old value added tohistory.
Relations
Relations are set and read as URIs. The key is the REST name of the relation's class — singular for a single-valued relation, plural for a multi-valued one (see Qualified names and URLs):
| Request body | Response | |
|---|---|---|
| Single-valued | "country": "/data/{tenant}/countries/{id}" | _links.country: { "href": "...", "name": "Netherlands" } |
| Multi-valued | "employees": ["/data/{tenant}/persons/{id}", ...] | _links.employees: { "href": "<related list>", "values": [{ "href": "...", "name": "..." }] } |
In responses, relations appear only under _links, never as top-level properties. When you send them back, send the href strings, not the { href, name } objects. See Get one and Patch for the details, including how a multi-valued relation is replaced as a whole.
Empty values
| Direction | Rule |
|---|---|
| Request | null and "" (also a string of only spaces) clear a field. A key that is left out leaves the field unchanged. For a multi-valued field, [] clears it. |
| Response | An empty field is left out. Responses never contain "field": null; a missing property means "no value". |
A property in a request that is not a field or relation of the object is ignored without an error — see Request body.