> ## Documentation Index
> Fetch the complete documentation index at: https://docs.upwell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Field shapes and JSON values

> How to read field definitions, send reference numbers and JSON metadata, and construct filters.

The API reference describes the JSON value for each field, including nested objects and arrays. Send the representation documented for the field in the request body. A JSON object and a string containing serialized JSON are distinct values; some legacy fields support both.

## Reference numbers

Customer invoices and shipments support an object keyed by the purpose of each reference:

```json theme={null}
{
  "referenceNumbers": {
    "billOfLadingNumber": "BOL-123",
    "customerPoNumber": "PO-456",
    "otherReferenceNumbers": [
      { "name": "Booking", "value": "BK-789" }
    ]
  }
}
```

Keep identifiers as strings to preserve leading zeros. Additional source-specific keys may be present. Source integrations also use `additionalReferenceNumbers`, whose entries contain `name`, `value`, and optionally `normalizedName` (for example, `customerPoNumber`). These collections are not interchangeable in every workflow; use the field documented for the receiving entity.

Customer invoices also support a top-level array of named references, such as `[{ "name": "Customer PO", "value": "PO-456" }]`. Invoice reference resolution uses this array shape. Preserve the shape used by the source and receiving workflow when reading and updating references.

Invoices and shipments can also contain arrays of plain reference strings, such as `["REF-001", "REF-002"]`. These identifiers have no separate label. An invoice's `additionalReferenceNumbers` collection can be null when no named references are available.

Legacy invoice clients also send JSON-encoded reference objects, such as `"referenceNumbers": "{\"reference\":\"123\"}"`, and the API can return that string unchanged. Preserve this representation when round-tripping existing records; it is distinct from an unstructured comma-separated string.

Dedicated fields such as `customerPoNumber`, `billOfLadingNumber`, and `carrierProNumber` remain separate fields. Setting a key inside `referenceNumbers` does not automatically update its top-level counterpart.

Purchase-order and vendor-invoice `referenceNumbers` use an array of named references, such as `[{ "name": "Customer PO", "normalizedName": "customerPoNumber", "value": "PO-123" }]`. These parsed-document fields use the array directly, without an `otherReferenceNumbers` wrapper.

Stop references additionally support lists of `{ "name": "PO", "value": "PO-123" }` entries. Older sources may return a JSON-encoded string for stop references. Prefer an object or array for new integrations. A plain comma-separated string is not the documented invoice reference-number shape.

Shipments from sources such as Tai/Metafora can instead use a top-level array:

```json theme={null}
{
  "referenceNumbers": [
    { "value": "CONT-123", "referenceType": "Container Number" }
  ]
}
```

Preserve the source's labels and shape when round-tripping these records. Shipment matching recognizes specific identifier labels, including `Container Number`, `Custom Reference Number`, `Custom Reference Number 2`, `Delivery Number`, `Rail Pickup Number`, `Load Release Number`, and `Tracking Reference Number`; arbitrary labels are not a promise of matching behavior.

## Custom JSON values

In the API reference, **`{key}` means a property name you choose**. It is a placeholder for additional keys, not a literal property to send and not a requirement to invent a key. The type selector shows the alternatives allowed for that custom value.

For `referenceNumbers`, prefer a standard string property such as `customerPoNumber`, or a named entry in `otherReferenceNumbers`. Custom keys are useful for preserving source-specific data. These are three different examples:

```json Standard reference theme={null}
{
  "referenceNumbers": {
    "customerPoNumber": "PO-456"
  }
}
```

```json Custom text value theme={null}
{
  "referenceNumbers": {
    "bookingReference": "BK-789"
  }
}
```

```json Custom object value theme={null}
{
  "referenceNumbers": {
    "bookingReference": {
      "number": "BK-789",
      "source": "TMS"
    }
  }
}
```

In the object example, `bookingReference`, `number`, and `source` are illustrative names chosen by the sender. The object has no required keys. Its values can be strings, numbers, booleans, null, arrays, or further objects. For example, `"bookingReference": { "numbers": ["BK-789", "BK-790"] }` is also a JSON object value.

This flexibility applies to **custom keys**. It does not change the types of the named properties: `customerPoNumber` is documented as a string, so do not replace it with `{ "number": "PO-456" }`. Saving a custom object does not make its keys searchable reference types or trigger matching automatically. Use the documented standard properties or named-reference collections for those workflows.

For a JSON type selector, the example belongs to the selected type: text appears in quotes, an object uses `{ ... }`, and an array uses `[ ... ]`. An empty object `{}` means an object with no keys; it is not a definition of which business keys you should send.

## Metadata and other JSON fields

JSON-valued `metadata` and `sourceSystemMeta` fields support objects with source/caller-defined keys. They can contain nested objects, arrays, strings, numbers, booleans, and null. Legacy source metadata also supports JSON-encoded object strings, such as `"sourceSystemMeta": "{\"source\":\"test\"}"`. They do not have a universal set of business keys. Preserve the existing representation and keys when sending a replacement value.

Stop `metadata` is a text field: send a string such as `"{}"`, or serialize a JSON object into that string. Check the entity's schema before using the object example below.

```json theme={null}
{
  "metadata": {
    "externalBatchId": "BATCH-123",
    "labels": ["priority"],
    "reviewed": false
  }
}
```

Other JSON fields have specific shapes in the reference. For example, contact `email` is an object such as `{ "email": "billing@example.com", "type": "default" }`, while an email field on a different entity may be a plain string. Purchase-order `schedules` is an array of delivery-date/quantity entries; it is not an arbitrary scheduling configuration.

Rule action values depend on the selected action. Exception details and downstream response payloads depend on the event/service that produced them. Their schemas explicitly allow JSON values rather than inventing a fixed set of keys.

## Required, omitted, and null

* **Required** means the request must include the field. Create and update schemas can differ.
* **Omitted on update** generally leaves the field unchanged. Omitted on create uses a server default if one exists; it does not imply a default of zero or today's date.
* **Null** is an explicit value. It clears a nullable field where the endpoint permits that; it can fail a database constraint on other fields.
* **Nested data** inserts related records during creation. An object relation uses `{ "data": { ... } }`; an array relation uses `{ "data": [ ... ] }`.

Update inputs set the supplied JSON column value; they do not recursively merge a partial JSON object with the old value. Read and preserve the keys you want to keep. An empty object, an empty array, an empty string, and null are different values.

## Query filters

Search endpoints accept objects keyed by selectable fields. Scalar fields contain comparison objects; related records contain another filter object. The API key's permissions still determine which fields are accepted.

```json theme={null}
{
  "where": {
    "sourceSystem": { "_eq": "YOUR_TMS" },
    "issueDate": { "_gte": "2026-10-01", "_lte": "2026-10-31" },
    "_or": [
      { "number": { "_ilike": "INV-%" } },
      { "customerPoNumber": { "_eq": "PO-123" } }
    ]
  },
  "orderBy": { "createdAt": "desc" },
  "limit": 50,
  "offset": 0
}
```

`_and` requires every expression, `_or` requires at least one, and `_not` negates an expression. Multiple comparisons on a field are combined with AND. `_isNull` checks null without comparing it to a string. `_in` and `_nin` take arrays. String `_like` and `_ilike` use SQL LIKE wildcards; `%` matches any sequence of characters. JSON `_contains` takes a JSON value, not serialized JSON text.

Aggregate relationship filters use a function envelope. For example, where an endpoint exposes `invoiceLineItemsAggregate`, `{ "count": { "predicate": { "_gt": 0 } } }` tests whether at least one related line exists. Availability depends on that relationship and your API key's aggregate permissions.

Sort values are `asc`, `desc`, `asc_nulls_first`, `asc_nulls_last`, `desc_nulls_first`, and `desc_nulls_last`. Related-record sorting uses a nested sort object. Match the outer `orderBy` object/array wrapper shown by the specific endpoint.

See [Dates and timestamps](/conventions/dates-and-times) for the business meaning of each date, and [Money and payloads](/conventions/money-and-payloads) for monetary units and request wrappers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.