API dokumentation - Ärende
The Case Management Read API provides authenticated, read-only access to forms and cases in Classic. It lets you search and list cases, filter them using metadata, and retrieve complete case details. This article describes how the API behaves and how to structure and use its requests.
β The Read API for Case Management is in beta and may contain bugs, limitations, or change before final release!
You can register your interest to join the beta and get early access, test the API in your own environment, and influence how it develops. Participation is free. Pricing for the final version will be communicated closer to general availability.
Learn more here and register your interest here.
💬 This article covers how the API behaves: how requests are structured and what you can do with them. This article does not cover how the feature is enabled in Classic or how the API key is created. You can read more about this in the article: Read-API Case Management
The Case Management Read API provides authenticated, read-only access to the forms and cases in Classic. With it you can list the available forms, read a form's schema, search and list cases, and retrieve full details for an individual case — including its field values and attachments.
The API is intended for integrations where you want to surface information from cases in other systems, reports, or custom applications.
Language and translations
The site’s default language affects some of the names and labels returned through the API. For example, field labels in Case Management are returned based on the default language configured for the site.
This means that if the site’s default language is set to English, the API will return these names and labels in English. If the default language is set to Swedish, the corresponding Swedish names and labels will be returned instead.
This is important to consider when using the API in an external system, report or dashboard.
You can read more about language settings in Classic in the article Manage languages in AM System.
Base URL and requests
https://api.amsystem.com/cases
Every request is authenticated with an API key passed in the Authorization header as a bearer token:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms"
All examples below assume this header is present. Every endpoint is read-only (GET); nothing is created or changed.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET |
/cases/forms |
List the available forms |
GET |
/cases/forms/{formId} |
Retrieve a form's schema (fields, options, statuses) |
GET |
/cases/forms/{formId}/cases |
Search and list cases, with filtering and pagination |
GET |
/cases/forms/{formId}/cases/{caseId} |
Retrieve complete details for a single case |
List forms
GET /cases/forms
Returns the available forms with their ID, name, and abbreviation. Use the form ID to address the other endpoints.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms"
Example response
{
"data": [
{
"id": 68,
"name": "Nonconformity",
"description": "Register and manage internal nonconformities.",
"abbreviation": "NC"
},
{
"id": 166,
"name": "Supplier Nonconformity",
"description": "Register and manage supplier nonconformities.",
"abbreviation": "SNC"
}
]
}
Get a form schema
GET /cases/forms/{formId}
Returns the fields a form has, their types, and the available value-list options and statuses. Use the schema to discover exactly what you can filter and sort on — a field's id from the schema is the same id you use in filter paths (see Search and list cases).
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166"
Example response - form schema
Each option includes the id that can be used for filtering. For person fields, both individual persons and groups are listed. Each value also includes a type, making the numeric ID unambiguous.
When you retrieve a form schema, all fields that use predefined list values include the values that are currently available for selection in the form. The schema may also include values or persons that have been deactivated or deleted if they are still referenced by existing cases.
For example, the Supplier Nonconformity form contains a Supplier field of the type Person. When creating a new case, users can currently select between two suppliers: Nordic Precision Components AB and SteelForm Manufacturing AB.
However, when retrieving the form schema, a third supplier, canHydraulics AB, is also returned. This is because there are existing cases where canHydraulics AB was previously selected and saved. Although this supplier is no longer available when creating new cases, it is still included in the schema because it is referenced by existing data.
{
"id": 166,
"name": "Supplier Nonconformity",
"description": "Register and manage supplier nonconformities.",
"abbreviation": "SNC",
"fields": [
{
"id": "issuer",
"label": "Issuer",
"type": "issuer",
"required": false,
"section": 1
},
{
"id": "metadatagroup",
"label": "Metadata",
"type": "group",
"required": false,
"section": 1
},
{
"id": "supplier",
"label": "Supplier",
"type": "person",
"required": true,
"section": 1,
"options": [
{
"type": "person",
"id": "27",
"label": "Nordic Precision Components AB"
},
{
"type": "person",
"id": "30",
"label": "SteelForm Manufacturing AB"
},
{
"type": "person",
"id": "40",
"label": "ScanHydraulics AB"
}
]
},
{
"id": "supplier-email",
"label": "Supplier Email",
"type": "email",
"required": false,
"section": 1
},
{
"id": "problem-description",
"label": "Problem description",
"type": "varchar",
"required": true,
"section": 1
},
{
"id": "internal-information",
"label": "Internal information",
"type": "varchar",
"required": false,
"section": 1
},
{
"id": "reg-date",
"label": "Reg. date",
"type": "regdate",
"required": false,
"section": 1
},
{
"id": "deviation-type",
"label": "Deviation type",
"type": "valuelistdb",
"required": false,
"section": 1,
"options": [
{
"id": 17,
"label": "Deviation type 3",
"active": true
},
{
"id": 16,
"label": "Deviation type 2",
"active": true
},
{
"id": 15,
"label": "Deviation type 1",
"active": true
}
]
},
{
"id": "ncr-id",
"label": "NCR id.",
"type": "regno",
"required": false,
"section": 1
},
{
"id": "status",
"label": "Status",
"type": "status",
"required": false,
"section": 1
},
{
"id": "part-no",
"label": "Part no.",
"type": "num",
"required": false,
"section": 1
},
{
"id": "add-pictures",
"label": "Add pictures",
"type": "image",
"required": false,
"section": 1
},
{
"id": "add-files",
"label": "Add files",
"type": "file",
"required": false,
"section": 1
},
{
"id": "delivery-date",
"label": "Delivery date",
"type": "date",
"required": false,
"section": 1
},
{
"id": "assigned-to",
"label": "Assigned To",
"type": "person",
"required": false,
"section": 1,
"options": [
{
"type": "group",
"id": "1",
"label": "SNC Review"
},
{
"type": "person",
"id": "12",
"label": "Kim"
}
]
}
],
"statuses": [
{
"id": -1,
"label": "Pending registration",
"color": "#DF5353"
},
{
"id": 0,
"label": "Registered",
"color": "#DF5353"
},
{
"id": 1,
"label": "In progress",
"color": "#7798BF"
},
{
"id": 2,
"label": "Resolved",
"color": "#F7A35C"
},
{
"id": 3,
"label": "Completed",
"color": "#80B69D"
}
]
}
List and search cases
GET /cases/forms/{formId}/cases
Returns a paginated list of cases for a form. Use the query parameters below to filter, sort, and page through the results.
Query parameters
| Parameter | Required | Description |
|---|---|---|
page |
Optional | Page number. Default is 1 |
limit |
Optional | Number of results per page. Default is 100, maximum is 300 |
sort |
Optional | The JSON path to sort on, for example meta.regDate |
order |
Optional | Sort direction: asc or desc |
meta.<path>.<operator> |
Optional | Filter on built-in metadata (see Filtering) |
fields.<fieldId>.<path>.<operator> |
Optional | Filter on a form field (see Filtering) |
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?limit=10"
Filtering
The filtering rule is simple: take the JSON path to the value you see in a response and append <operator> as a query parameter. The same paths are used for sort.
For example, a response contains meta.status.id. To filter on status ID 1, use meta.status.id.eq=1.
When retrieving a list of cases, the response always includes the case metadata, such as the form ID, case number, creator, registration date, and status. In addition to these metadata fields, the response includes the form fields configured under Default fields in API.
Dates and times: all date-times are in Swedish local time (CET/CEST, UTC+1/UTC+2), formatted YYYY-MM-DDTHH:MM:SS without a timezone suffix, and dates (regDate) are plain YYYY-MM-DD. Filters compare against the same clock, so any value you see in a response can be used verbatim as a filter value — meta.completed.cn=2025-05-01 means May 1st in Swedish time.
Operators
| Operator | Meaning |
|---|---|
eq |
Equal to |
ne |
Not equal to |
gt |
Greater than |
gte |
Greater than or equal to |
lt |
Less than |
lte |
Less than or equal to |
cn |
Contains. Send plain text; wildcards are added automatically, so meta.issuer.label.cn=Kim matches any value containing "Kim" |
like |
Pattern matching. You supply the wildcards yourself — % (any sequence) and _ (single character). Important: The % character must be URL-encoded as %25 in query parameters. For example, meta.issuer.label.like=j%25 matches all issuers starting with "j" |
in |
Matches one of several comma-separated values |
Built-in meta fields (always available)
meta.regDate.gte=2025-01-01
meta.regDate.lte=2025-12-31
meta.status.id.in=0,1
meta.issuer.label.cn=Kim
Form fields — find the field's id in the form schema.
|
fields.list.value.id.eq=5 |
# value list, by option ID # value list, by visible label # person field: a person # person field: a group # person or group, by name # text field # date field (YYYY-MM-DD) # number field |
Value validation: A filter value must fit its target's type. Date fields and the meta date paths (regDate, changed, started, resolved, completed) take YYYY-MM-DD (an optional time may follow), .id paths take integers, and numeric fields take numbers. An invalid value returns 400 Bad Request with a message naming the value and the expected type — never an empty or incorrect result. cn and like accept any pattern.
Person fields: When filtering on a person field by ID, you must always specify the type as well. For example, to find cases where a person field references ID 3, use fields.person.value.type.eq=person&fields.person.value.id.eq=3. Omitting the type will result in a 400 Bad Request error. Filtering by name needs no type: fields.person.value.label.cn=Kim matches the displayed label whether it is a person or a group name. Add value.type to restrict the name match to one kind, for example fields.person.value.type.eq=group&fields.person.value.label.cn=Quality.
Filtering examples
Cases with a fault type of "Defect", by value-list label:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?fields.list.value.label.eq=Defect"
Cases registered within a date range:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?meta.regDate.gte=2025-01-01&\
meta.regDate.lte=2025-03-31"
Cases issued by anyone whose name contains "Kim":
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?meta.issuer.label.cn=Kim"
Cases with status 0 or 1, registered on or after a date, newest first:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?meta.status.id.in=0,1&\
meta.regDate.gte=2025-01-01&limit=10&sort=meta.regDate&order=desc"
Cases whose fault type is one of several value-list options 5,6,7, excluding status 1 (In progress):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?fields.list.value.id.in=5,6,7&\
meta.status.id.ne=1"
Cases where a text field contains a term (using like with URL-encoded wildcards):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?\
fields.textfield.value.like=%25Defect%25"
Cases assigned to a specific person (person field — note the required type parameter):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?fields.person.value.type.eq=person&\
fields.person.value.id.eq=3"
Cases assigned to a person field whose name contains "Kim" (no type needed for label filtering):
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?fields.person.value.label.cn=Kim"
Other useful filter expressions:
| meta.regNo.eq=166 meta.status.label.cn=In progress fields.list.value.label.like=Def%25 |
# exact registration number # status label contains "In progress" # value-list label starts with "Def" |
Sorting
Sort the result with sort (the JSON path to sort on) and order (asc or desc). The path uses the same form as a filter path, for example sort=meta.regDate&order=desc.
Pagination
List responses include a pagination object and, when more pages exist, a links object with ready-to-use navigation URLs.
| Field | Description |
|---|---|
pagination.page |
Current page number |
pagination.pageSize |
Number of results per page |
pagination.totalCount |
Total number of matching cases |
pagination.totalPages |
Total number of pages |
links.next |
URL for the next page |
links.prev |
URL for the previous page |
links.first |
URL for the first page |
links.last |
URL for the last page |
To page through a large result set, follow the URL in links.next or repeat the same filters and increase page:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?meta.regDate.gte=2026-07-06&\
limit=1&page=2"
Example response - cases
{
"data": [
{
"id": 2,
"formId": 166,
"meta": {
"regNo": 2,
"link": "https://demo.amsystem.com/case/166/2",
"regDate": "2026-07-08",
"status": {
"id": 1,
"label": "In progress"
},
"issuer": {
"id": 2,
"label": "Kim",
"department": {
"id": 12,
"label": "Quality"
},
"workspace": {
"id": 2,
"label": "Demo Company"
}
},
"changed": "2026-07-08T13:03:14",
"changedBy": {
"id": 43,
"label": "Abigail",
"department": {
"id": 12,
"label": "Quality"
},
"workspace": {
"id": 2,
"label": "Demo Company"
}
},
"started": "2026-07-08T09:51:18",
"resolved": null,
"completed": null
},
"fields": [
{
"id": "supplier",
"label": "Supplier",
"value": {
"type": "person",
"id": 83,
"label": "Nordic Precision Components AB",
"workspace": {
"id": 3,
"label": "Supplier"
}
}
},
{
"id": "deviation-type",
"label": "Deviation type",
"value": {
"id": 15,
"label": "Deviation type 1"
}
}
]
}
],
"pagination": {
"page": 2,
"pageSize": 1,
"totalCount": 4,
"totalPages": 4
},
"links": {
"first": "/cases/forms/166/cases?page=1&limit=1",
"last": "/cases/forms/166/cases?page=4&limit=1",
"prev": "/cases/forms/166/cases?page=1&limit=1",
"next": "/cases/forms/166/cases?page=3&limit=1"
}
}
Get a single case
GET /cases/forms/{formId}/cases/{caseId}
Retrieves complete details for a specific case, including all field values and any attachments. When retrieving a specific case by its case ID, the response includes all available field values except fields configured as Hidden fields. Hidden fields are never exposed through the API, regardless of whether a case is retrieved as part of a list or individually.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases/2"
Putting it together
A common end-to-end flow is to discover a form, see what you can filter on, list the matching cases, and then open one for full details.
1. List forms to find the form ID:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms"
2. Fetch the form schema to see its fields, statuses, and value-list options:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166"
3. List the matching cases with a filter and sort:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases?meta.status.id.in=0,1&\
sort=meta.regDate&order=desc&limit=10"
4. Open one case for full details — take an id from the result:
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.amsystem.com/cases/forms/166/cases/2"
Object reference
Case object
| Field | Description |
|---|---|
id |
Unique case ID |
formId |
ID of the form the case belongs to |
meta |
Built-in metadata for the case (see below) |
fields |
List of the form's field values (see below) |
files |
List of files attached to the case. (see below) |
Meta object
| Field | Description |
|---|---|
regNo |
Registration number |
link |
Permanent, user-facing link to the case |
regDate |
Registration date (when the case was created), as a plain YYYY-MM-DD date |
status |
Case status: id, label |
issuer |
The person who issued/created the case: id, label, and optionally department and workspace objects. Note that the department and workspace values reflect the user’s department and workspace at the time the case was edited. This means that these values may differ from the user’s current department or workspace if they have changed since then. |
changed |
When the case was last modified, as Swedish local time (YYYY-MM-DDTHH:MM:SS, no timezone suffix) |
changedBy |
The person who last modified the case: id, label, and optionally department and workspace objects. Note that the department and workspace values reflect the user’s department and workspace at the time the case was edited. This means that these values may differ from the user’s current department or workspace if they have changed since then. |
started |
When work started on the case, as Swedish local time (may be null) |
resolved |
When the case was resolved, as Swedish local time (may be null) |
completed |
When the case was completed, as Swedish local time (may be null) |
Field object
| Field | Description |
|---|---|
id |
Field ID; matches the field id in the form schema |
label |
The field's visible label |
value |
The field's value. Its shape depends on the field type — for example a value-list option (id, label), a person-field reference (type, id, label, where type is person or group), a sign/issuer person (id, label), a date as a plain YYYY-MM-DD string, or a plain text or number value. For a value list, value.id matches the option id in the schema; for a person field, value.type + value.id do — so a value maps back to its option |
Files object
When a case contains files, they are returned as file objects (for example in a files array). Each file object has the following fields:
| Field | Description |
|---|---|
id |
Files ID |
fieldId |
ID of the field the file belongs to |
filename |
Original file name, including extension |
name |
Optional display name; null when not set |
description |
Optional description; null when not set |
extension |
File extension, for example jpeg or pdf |
mime |
MIME type, for example image/jpeg or application/pdf |
size |
File size in bytes, returned as a string |
repeating |
Row reference when the file sits in a repeating section; null otherwise |
downloadUrl |
Relative URL used to download the file |
Repeating fields
A repeating section appears as a single field with "repeating": true, whose value is a list of rows. Each row carries its own fields list with the same field shape as above:
{
"id": "repeating-field",
"label": "Repeating field",
"repeating": true,
"value": [
{
"row": 1,
"fields": [
{
"id": "p-description",
"label": "Part description",
"value": "Pipe"
},
{
"id": "p-number",
"label": "Part number",
"value": 123456789
}
]
}
]
}
Child fields inside a repeating section are filtered with their own field id, exactly like top-level fields — fields.p-description.value.cn=Pipe matches every case that has a row whose value contains "Pipe".
Error handling
Three behaviors are specific to how filtering works:
- A filter never broadens the result set. If a label or name matches nothing, the response is empty — not the full list.
- A malformed filter returns
400 Bad Requestrather than being ignored (which would silently return the full list). This includes an unknown field, a selector that doesn't fit the field type, filtering a person field byvalue.idwithoutvalue.type, a missing or unrecognized trailing operator — for examplefields.list.value.id=5instead offields.list.value.id.eq=5— and a filter-shaped parameter that omits thefields.ormeta.root, for examplelist.value.id.eq=5. - A value that cannot be what the target expects also returns
400 Bad Request: a malformed date on a date path, a non-integer on an.idpath, or a non-number on a numeric field. The message names the offending value and the expected type.
| HTTP status | Meaning |
|---|---|
200 |
Successful request |
400 |
Bad request, for example an invalid filter expression |
401 |
Invalid or missing API key |
404 |
Form or case not found |
500 |
Internal server error |
Example error responses
{ "error": "Bad request", "message": "Invalid filter:\
Unknown or unsupported filter path 'meta.status.value'" }
{ "error": "Bad request", "message": "Invalid filter:\
Invalid value 'abc' for filter 'meta.status.id.eq' — expected an integer id" }
Best practices
Fetch the schema first. The form schema tells you which fields, statuses, and value-list options exist, so you know exactly what you can filter and sort on.
GET /cases/forms/166
Use pagination. Keep response sizes manageable with page and limit.
?limit=50&page=1
Filter as specifically as possible. Tighter filters mean better performance and smaller responses.
?meta.status.id.in=0,1&meta.regDate.gte=2025-01-01
Filter by ID rather than label when you can. Labels and names must match exactly to return results, so a value-list option ID (fields.list.value.id.eq=5) is more robust than its visible label.