> For the complete documentation index, see [llms.txt](https://docs.agilecase.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.agilecase.com/developer-documentation/case-data-api/response-format.md).

# Response Format

The shape of the JSON returned by the Case Data API, and how errors are reported.

Every request returns the same envelope: a status, a message, and a `data` object holding the results grouped by kind.

```json
{
  "status": "success",
  "message": "",
  "data": {
    "caseFields": [
      {
        "name": "CaseReference",
        "value": "CASE-1042",
        "type": "Text",
        "originalName": "case.CaseReference"
      }
    ],
    "customFields": [
      {
        "id": 6364,
        "name": "Customer Rating",
        "value": "75",
        "type": "Textbox",
        "originalName": "custom.CustomerRating"
      }
    ]
  }
}
```

## Which group a value lands in

Results are grouped by the kind of data, not by the order you asked for them.

<table><thead><tr><th width="230">Requested as</th><th>Appears in</th></tr></thead><tbody><tr><td><code>custom.</code>, <code>client.custom.</code>, <code>source.custom.</code></td><td><code>data.customFields</code></td></tr><tr><td><code>case.</code>, <code>contact.</code></td><td><code>data.caseFields</code></td></tr><tr><td><code>casetable.</code></td><td><code>data.customTables</code></td></tr></tbody></table>

{% hint style="warning" %}
A group is left out of the response entirely when it holds nothing, rather than being returned as an empty array. Code such as `data.data.customFields[0].value` therefore throws when nothing matched, which is a common cause of a script that works until a field is renamed. Check the group exists before reading from it.
{% endhint %}

## Fields on a value

<table><thead><tr><th width="180">Property</th><th>What it holds</th></tr></thead><tbody><tr><td><code>value</code></td><td>The value as text. Always a string, even for numbers and dates.</td></tr><tr><td><code>name</code></td><td>The field's real name, as configured.</td></tr><tr><td><code>id</code></td><td>The custom field's numeric ID. Not present for case or contact fields.</td></tr><tr><td><code>type</code></td><td>The field type, such as <code>Textbox</code> or <code>DatePicker</code>. Case and contact fields report <code>Text</code>, or <code>DateTime</code> for the two case date fields.</td></tr><tr><td><code>originalName</code></td><td>The token you asked for, echoed back.</td></tr><tr><td><code>error</code></td><td>Present only when that value could not be provided.</td></tr></tbody></table>

Any property that has no value is left out rather than returned as `null`.

### Matching results to what you asked for

`originalName` is the reliable way to find a value, because it echoes your own token. Position is not reliable, since results are grouped and a single custom field name can match more than one field.

```javascript
function valueOf(response, token) {
    var groups = [response.data.customFields, response.data.caseFields];
    for (var g = 0; g < groups.length; g++) {
        var items = groups[g] || [];
        for (var i = 0; i < items.length; i++) {
            if (items[i].originalName.toLowerCase() === token.toLowerCase()) {
                return items[i].error ? null : items[i].value;
            }
        }
    }
    return null;
}
```

Compare case-insensitively. The echoed token does not always preserve the capitalisation you used.

## How values are formatted

<table><thead><tr><th width="230">Field type</th><th>What you get</th></tr></thead><tbody><tr><td>Dates, dropdowns and checkbox lists</td><td>The value as displayed to a user, rather than the raw stored value.</td></tr><tr><td>Calculated fields</td><td>Evaluated at the moment you ask, so the value is current.</td></tr><tr><td>Everything else</td><td>The stored value, with any surrounding brackets or quotation marks removed.</td></tr></tbody></table>

A field that exists but has no value on this case returns its configured default, or an empty string if it has none.

## Tables

A table comes back with all of its rows, and each row with all of its columns:

```json
{
  "status": "success",
  "message": "",
  "data": {
    "customTables": [
      {
        "id": 1176,
        "name": "Risk Assessments",
        "rows": [
          {
            "id": 1,
            "author": "Jane Smith",
            "dateCreated": "2026-03-14T09:21:00",
            "items": [
              { "name": "Assessed On", "value": "14/03/2026", "type": "DatePicker" },
              { "name": "Outcome", "value": "Low", "type": "Dropdown" }
            ]
          }
        ]
      }
    ]
  }
}
```

Rows carry who created them and when. Note that the items inside a row have no `id` or `originalName`, so columns are identified by `name` only, and they appear in the order the columns are configured.

## Errors

There are two kinds, and they are reported differently. Both come back with an HTTP status of 200, so a failed request still looks successful to code that only checks the status code.

### A problem with one value

The rest of the request still succeeds. The failing entry appears with an `error` and usually no `value`:

```json
{
  "status": "success",
  "message": "",
  "data": {
    "customFields": [
      { "name": "CustomerRatng", "originalName": "custom.CustomerRatng",
        "error": "CustomField with name 'CustomerRatng' not found." }
    ]
  }
}
```

Note that `status` is still `success`. Per-value problems do not change it, so checking `status` alone is not enough. You have to check each value for an `error`.

<table><thead><tr><th width="330">Error</th><th>Cause</th></tr></thead><tbody><tr><td><code>CustomField with name '…' not found.</code></td><td>No custom field of that name exists.</td></tr><tr><td><code>CustomField with id … not found.</code></td><td>No custom field with that ID is available on this case type.</td></tr><tr><td><code>… is invalid field name.</code></td><td>A <code>case.</code> or <code>contact.</code> field name that is not in the <a href="/developer-documentation/case-data-api/field-reference.md">Field Reference</a>, including one whose capitalisation is wrong.</td></tr><tr><td><code>… is empty or null.</code></td><td>The field is valid but holds nothing on this case.</td></tr><tr><td><code>Contact field with name '…' not found.</code></td><td>No contact is linked to the case with that relationship.</td></tr><tr><td><code>CustomTableField with name or id … not found.</code></td><td>No table group of that name or ID, or the group exists but is not a table.</td></tr></tbody></table>

### A problem with the whole request

Nothing is returned. `status` becomes `fail` and `message` explains why:

```json
{
  "status": "fail",
  "message": "Case with id 1042 not exist in DB or you don't have permission;",
  "data": {}
}
```

<table><thead><tr><th width="380">Message</th><th>Cause</th></tr></thead><tbody><tr><td><code>You are not authorized;</code></td><td>No signed-in session. Usually means the session expired while the page was open.</td></tr><tr><td><code>Property getValues is empty or null;</code></td><td><code>getValues</code> was missing or empty.</td></tr><tr><td><code>Case with id … not exist in DB or you don't have permission;</code></td><td>No such case, or the signed-in user cannot see it. The two are deliberately not distinguished.</td></tr></tbody></table>

## Checking a response properly

Because failures arrive with a 200 and a partial success keeps `status` as `success`, a robust script checks both levels:

```javascript
$.get('/api/case/' + caseid + '/data?getValues=custom.CustomerRating', function (data) {
    if (data.status !== 'success') {
        console.log('Case Data API request failed: ' + data.message);
        return;
    }

    var fields = data.data.customFields || [];
    if (!fields.length || fields[0].error) {
        console.log('Rating unavailable: ' + (fields.length ? fields[0].error : 'not returned'));
        return;
    }

    // safe to use fields[0].value
});
```
