Skip to content

REST API ​

The interface talks to Qorekit only through its JSON API, under /api/v1, so everything the interface does, the API can do.

Signing in

For now the API uses the same session as the interface: sign in with POST /api/v1/auth/login and send the session cookie and the X-XSRF-TOKEN header with every request, as a browser does. Tokens for other programs are planned.

Conventions ​

  • Requests and responses are JSON. Send Accept: application/json.
  • Responses wrap their content in data; lists add meta.
  • Keys, not ids, name modules, entities, fields and choice lists in addresses: /api/v1/records/customers.
  • Dates and times are ISO 8601. Times are returned in UTC (2026-11-13T07:00:00Z); a time sent without a zone is refused.
  • Decimal numbers and money are strings ("1250.50"), so no precision is lost.
  • Errors follow RFC 9457 problem details, as application/problem+json.

Records ​

RequestDoes
GET /records/{entity}A page of records
POST /records/{entity}Adds a record
GET /records/{entity}/{id}One record
PATCH /records/{entity}/{id}Changes the fields in the body
DELETE /records/{entity}/{id}Moves the record to the trash
POST /records/{entity}/{id}/restoreBrings it back from the trash
POST /records/{entity}/{id}/revealThe whole value of a sensitive field: {"field": "iban"}

Listing ​

http
GET /api/v1/records/contacts?page=2&per_page=50&sort=-created_at&search=ada
ParameterMeaning
page, per_pagePaging; per_page is 50 by default, 200 at most
sortA field key, or -key for descending; also created_at and updated_at
searchText to look for in the searchable fields
search_inComma-separated field keys to search instead; _title is the heading
fieldsComma-separated field keys to return, for smaller responses
trashed=onlyRecords in the trash instead
count=falseSkip counting, for speed
json
{
  "data": [
    {
      "id": 42,
      "name": "Ada",
      "email": "ada@example.com",
      "company": { "id": 7, "label": "Acme" },
      "tags": [{ "id": 16, "key": "finance", "label": { "en": "Finance", "tr": "Finans" }, "color": null }],
      "_meta": {
        "title": "Ada",
        "version": 3,
        "created_at": "2026-11-14T14:04:06Z",
        "updated_at": "2026-11-14T15:30:00Z",
        "deleted_at": null,
        "created_by": 1,
        "updated_by": 2,
        "created_by_name": "Demo Admin",
        "updated_by_name": "Sam Seller"
      }
    }
  ],
  "meta": { "page": 2, "per_page": 50, "total": 1234, "total_capped": false }
}

A search counts up to 1000 matches; beyond that total stops at 1000 and total_capped is true.

Writing ​

Send field keys and values. Related records and users are written as ids ("company": 7, or [7, 9] when several are allowed) and read as {id, label}. Choices are written by item key (or id) and read as {id, key, label, color}. A field with several values also takes {"add": [...], "remove": [...]}, to change some without sending them all.

_meta.title is the record's heading.

Conflicting edits ​

Every record has a version. Send it back as If-Match when changing a record:

http
PATCH /api/v1/records/contacts/42
If-Match: "3"
Content-Type: application/json

{"email": "ada@acme.example"}

If someone changed the record in between, the answer is 409 Conflict with the code version_mismatch and the record as it is now in current. Without If-Match, the change is applied whatever the version.

Errors ​

json
{
  "type": "https://qorekit.com/problems/validation-failed",
  "title": "The given data was invalid",
  "status": 422,
  "detail": "This value is already used by another record.",
  "errors": {
    "email": [{ "code": "taken", "message": "This value is already used by another record." }]
  }
}

Each field error has a stable code (required, taken, not_integer, invalid_choice, …) to act on, and an English message to show.

StatusMeaning
401Not signed in
403Signed in, but not allowed
404No such thing, or one you may not see
409A conflicting edit
422Invalid input; see errors
429Too many requests; wait and try again

Other endpoints ​

AreaEndpoints
Signing inPOST auth/login, POST auth/logout, GET/PATCH auth/me, PUT auth/me/password
Buildingmeta/modules, meta/entities, meta/entities/{entity}/fields, meta/choice-lists, meta/field-types, meta/trash
FilesPOST files (upload), GET files/{file}
Peopleusers, users/lookup, roles
Installationsettings, system/status, system/report, system/updates

GET /api/v1/system/status needs no sign-in, and says whether the installation works and which version it runs.

Qorekit is free software under the GNU GPL, version 3 or later.