Skip to content

Query records – POST /api/v1/records/{entityId}/query

Searches the records of an entity with a filter, sorts them, returns selected fields and pages through the result. The filter has the same building blocks as a query in the Admin Studio – groups, field clauses, related clauses, date part clauses and full text clauses. This page is the reference for the operation.


1. At a glance

Purpose Find records by their values
Method and path POST /api/v1/records/{entityId}/query
Typical use Find a customer by customer number; fetch all orders changed in the last day; export in pages
Permissions Valid token. Only records within the "Read Limits" of the API user are found and counted.
Success 200 OK, a page of records and the total number of hits
Related Queries (the same clauses in the Admin Studio), Fields and values

2. Request

Path parameters

Parameter Meaning Required
entityId ID of the entity that is searched Yes

Body

{
  "query":  { "type": "field", "field": "Status", "operator": "in", "value": ["Open", "InProgress"] },
  "sort":   [ { "field": "CreatedAt", "dir": "desc" } ],
  "fields": [ "OrderNumber", "Status", "CreatedAt" ],
  "page":   { "limit": 100, "skip": 0 }
}
Property Meaning Default
query The filter: one clause (section 3). Use a group clause to combine several. none – all readable records
sort Sort rules, applied in the order given none – the order of the database, which can change
sort[].field Field to sort by required
sort[].dir asc or desc asc
fields The fields to return. The record ID is always returned. none – all fields
page.limit Number of records to return, from 1 to 1000. Larger values are reduced to 1000. 50
page.skip Number of records to skip 0

An empty body {} returns the first 50 readable records.


3. Clauses

Every clause is a JSON object with a type:

type Checks Section
group Combines several clauses with and or or 3.1
field A field against a value or another field 3.2
related How many related records meet conditions 3.3
datePart A part of a date, or a time range relative to now 3.4
fullText Words in full-text-indexed fields 3.5

Important: type must be the first property of the clause object and is written exactly as in the table (fullText, not fulltext). Otherwise the request is rejected with 400 (see Errors, section 4). Operator, gate, date part and unit values, in contrast, ignore upper and lower case: equals, Equals and EQUALS are the same.

3.1 Group

{
  "type": "group",
  "gate": "or",
  "clauses": [
    { "type": "field", "field": "Name", "operator": "like", "value": "%ACME%" },
    {
      "type": "group",
      "gate": "and",
      "clauses": [
        { "type": "field", "field": "IsActive",    "operator": "equals",      "value": true },
        { "type": "field", "field": "CreditLimit", "operator": "greaterThan", "value": 10000 }
      ]
    }
  ]
}
Property Meaning Default
gate and – all clauses must hold; or – one is enough and
clauses The clauses of the group. Groups can be nested to any depth. empty – no condition

3.2 Field clause

{ "type": "field", "field": "CreditLimit", "operator": "greaterThanOrEqual", "value": 10000 }
Property Meaning Default
field The field that is compared (see Fields and values) required
relationshipId ID of a relationship to exactly one record (to-one). field is then a field of the related record, for example the "Country" of the customer of an order. none
operator See the table below required
value The value to compare with, written as for the field type. A JSON array for in and notIn. Not needed for empty and notEmpty. –
valueField Compare with another field of the same record instead of a value. Takes precedence over value. none
operator True when
equals, notEquals The field equals / differs from the value
lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual The field is smaller / greater than the value
like, notLike The field matches / does not match a pattern, ignoring upper and lower case. Add the wildcards yourself: % for any text, _ for one character. "%ACME%" means "contains ACME"; "ACME" only matches exactly "ACME".
empty, notEmpty The field has no value / has a value (see Queries, "Empty values")
in, notIn The field equals one / none of the values of the array, for example ["Open", "New"]

The value is converted to the type of the field. "value": "10000" for a number field is the same as 10000; "abc" for a number field leads to 400 invalid_field_value. An equality comparison on a date and time field compares the exact moment; use a date part clause to compare by day.

Checks the related records of each record, for example "customers with at least two open invoices".

{
  "type": "related",
  "relationshipDefId": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
  "operator": "atLeastXContains",
  "numberRecords": 2,
  "clauses": [
    { "type": "field", "field": "Status", "operator": "notEquals", "value": "Paid" }
  ]
}
Property Meaning Default
relationshipDefId ID of the relationship from the searched entity to the related records required
operator atLeastXContains, atMostXContains, exactlyXContains, notExactlyXContains, allContains, noneContains – see Queries, section 5 required
numberRecords The X of the operators that need one 0
clauses Conditions on the related records. Fields in them are fields of the related entity. empty – every related record counts

3.4 Date part clause

Checks a part of a date, or whether a date lies in a time range relative to now.

{ "type": "datePart", "field": "InvoiceDate", "datePart": "year", "operator": "equals", "value": 2026 }
{ "type": "datePart", "field": "CreatedAt", "operator": "is", "unit": "withInXDays", "number": 7 }
Property Meaning Default
field A date or date and time field required
relationshipId As in a field clause none
datePart date, dateTime, time, day (day of the year), dayOfWeek, dayOfMonth, week, month, quarter, year, hour (0–23) date
operator equals, notEquals, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual compare the part with value. is and isNot check the time range from unit and number. empty and notEmpty check whether the field has a value. required
value The value the part is compared with, for example 2026 for year or "2026-03-04" for date –
valueField Compare with another field of the same record instead none
unit Only for is / isNot: now, withInXMinutes, withInXHours, withInXDays, withInXWeeks, withInXMonths, withInXYears, beforeXMinutes, beforeXHours, beforeXDays, beforeXWeeks, beforeXMonths, beforeXYears required for is / isNot
number The X of the unit 0

withInX… means "within the last X units", beforeX… "more than X units ago". Ranges are measured from the current time of the database server. like, notLike, in and notIn are accepted but add no usable condition. More on weeks, days of the week and ranges: Queries, section 6.

3.5 Full text clause

Searches words in several fields at once.

{ "type": "fullText", "fields": ["Subject", "Description"], "value": "printer toner", "negate": false }
Property Meaning Default
fields The fields that are searched – fields marked "Use in Full Text Search" required, at least one
value The search words. Every word must occur. required, not empty
negate true finds the records that do not contain the words false

Full text clauses need an entity with "Enable Full Text Search" and the full text search of the database (see Entities and fields).


4. Response

200 OK:

{
  "entityDefId": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
  "entityName": "Order",
  "totalRecords": 137,
  "skip": 0,
  "limit": 100,
  "records": [
    {
      "entityDefId": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
      "entityName": "Order",
      "entityRecId": "e5f6a7b8-c9d0-4e1f-a2b3-c4d5e6f7a8b9",
      "fields": [
        { "fieldDefId": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f", "field": "OrderNumber", "storageName": "OrderNumber", "type": "String", "value": "A-20417" },
        { "fieldDefId": "a0b1c2d3-e4f5-4a6b-9c7d-8e9f0a1b2c3d", "field": "Status", "storageName": "Status", "type": "String", "value": "Open" },
        { "fieldDefId": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f7a", "field": "CreatedAt", "storageName": "CreatedAt", "type": "DateTime", "value": "2026-10-19T16:48:03" },
        { "fieldDefId": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f", "field": "RecId", "storageName": "RecId", "type": "Guid", "value": "e5f6a7b8-c9d0-4e1f-a2b3-c4d5e6f7a8b9" }
      ],
      "relationships": null
    }
  ]
}
Property Meaning
totalRecords Number of all hits, independent of paging
skip The applied skip
limit The applied limit – lower than requested if more than 1000 was asked for
records The records of this page, in the form described in Fields and values; only the fields from fields plus the record ID

No hits is not an error: totalRecords is 0 and records is empty.


5. Behaviour

  • The request is turned into a query and evaluated like a query from the Admin Studio, including links to related entities. The "Read Limits" of the API user are added to it.
  • Values in the request are never evaluated as expressions.
  • totalRecords and the page are read in two steps. If records change in between, the count and the page can differ slightly.

Paging through many records

  1. Always send a sort – without it the order is not fixed, and pages can overlap or miss records. Sort by a field that does not change, for example "CreatedAt" and then "RecId".
  2. Start with skip 0 and the limit you want (at most 1000).
  3. Increase skip by limit until skip is equal to or greater than totalRecords.

Example: totalRecords is 2350, limit 1000: requests with skip 0, 1000 and 2000. The last page contains 350 records.


6. Status and error codes

HTTP status error Cause
200 – The query ran
400 field_missing, field_not_found, field_ambiguous A field could not be identified
400 invalid_field_value A value does not fit the field type; in/notIn without an array
400 invalid_operator Unknown or missing operator
400 invalid_gate gate is neither and nor or
400 invalid_sort_direction dir is not asc or desc
400 invalid_date_part, invalid_date_part_unit Unknown datePart or unit
400 relationship_missing, relationship_not_found, relationship_invalid Problem with relationshipDefId / relationshipId
400 value_missing A full text clause without value
400 – (validation details) Invalid JSON, missing or unknown type – see Errors, section 4
401 – No valid token
404 entity_not_found No entity with this ID
500 query_failed The database could not run the query

The text in errorDescription of a 400 lists the allowed values, for example 'between' is not a valid query operator. Allowed values: None, Equals, NotEquals, ....


7. Examples

Find a customer by customer number:

curl -X POST https://nexxcite.example.com/api/v1/records/6a1f0c52-3d4e-4b8a-9c71-2f5e8d0b4a13/query \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "query": { "type": "field", "field": "CustomerNumber", "operator": "equals", "value": "K-1001" },
        "fields": ["CustomerNumber", "Name"], "page": { "limit": 1 } }'

Orders changed within the last 24 hours, newest first, 500 per page:

{
  "query": { "type": "datePart", "field": "LastModifiedAt", "operator": "is", "unit": "withInXHours", "number": 24 },
  "sort": [ { "field": "LastModifiedAt", "dir": "desc" }, { "field": "RecId" } ],
  "page": { "limit": 500, "skip": 0 }
}

Active customers in Germany or Austria – through the to-one relationship "Country":

{
  "query": {
    "type": "group",
    "gate": "and",
    "clauses": [
      { "type": "field", "field": "IsActive", "operator": "equals", "value": true },
      { "type": "field", "relationshipId": "f6a7b8c9-d0e1-4f2a-b3c4-d5e6f7a8b9c0", "field": "IsoCode", "operator": "in", "value": ["DE", "AT"] }
    ]
  }
}

8. Limitations

  • At most 1000 records per request.
  • No aggregations (sum, count per group) – only totalRecords for the whole filter.
  • Fields of related records cannot be returned in fields; use Read a record with relationshipId for single records.
  • Stored queries from the Admin Studio cannot be run by their ID. Rebuild the filter in the request, or run an action that uses the query.