StabisoDocs

API reference

Support

The support desk: queues with an inbox address, service levels and working hours; cases from e-mail, calls and agents, with their customer and contact, the person working them, notes, draft replies a person sends, and when the first reply and the resolution are due or were breached. Nothing here posts.

Operation Summary Scope Idempotency-Key
GET /v1/support/cases List support cases read
POST /v1/support/cases Open a support case draft required
GET /v1/support/cases/{case_id} Get a case read
PATCH /v1/support/cases/{case_id} Triage a case draft
POST /v1/support/cases/{case_id}/notes Add an internal note draft
POST /v1/support/cases/{case_id}/replies Write a reply draft required
PATCH /v1/support/cases/{case_id}/replies/{message_id} Change a draft reply draft
POST /v1/support/cases/{case_id}/replies/{message_id}/discard Discard a draft reply draft
POST /v1/support/cases/{case_id}/replies/{message_id}/send Send a draft reply draft required
POST /v1/support/cases/{case_id}/status Close, reopen or set a case to wait draft
POST /v1/support/inbound Hand over an e-mail to a queue's inbox draft required
GET /v1/support/queues List support queues read
POST /v1/support/queues Add a support queue admin required
PATCH /v1/support/queues/{queue_id} Change a support queue admin

GET /v1/support/cases

List support cases

The cases to work on, the next one due first (the closed ones last, the latest first), each with its service levels: when the first reply and the resolution are due, whether they were met, are running, stand still (waiting on the customer) or are breached.

Required scope read (admin implies every scope)
Operation id list_cases_v1_support_cases_get

Parameters

In Name Type Required Description
query entity string or null Only this company's (code or id).
query queue string or null Only this queue's (code or id; needs entity).
query show "active" | "all" | "closed" | "open" | "waiting" active (open and waiting, the default), open, waiting, closed or all. (default "active")
query assignee string or null me, none (nobody yet) or a person's id (GET /v1/people).
query party_id string (uuid) or null Only this customer's.
query breached boolean Only those with a breached service level. (default false)
query q string or null Text in the number, subject or address. (max length 200)
query limit integer How many. (min 1; max 1000; default 200)

Example request

curl "$ERP_URL/v1/support/cases" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of CaseOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

[
  {
    "created_by": {
      "id": "user:alice",
      "name": "Alice",
      "type": "human"
    },
    "number": "CASE-000001"
  }
]

POST /v1/support/cases

Open a support case

A case from a call, a visit or a form: what the customer asked (description), the queue, priority, customer, contact or requester, and who works it (none: the queue assigns when it does). It gets the company's next number and its service levels. An agent may open one. Needs an Idempotency-Key.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id create_case_v1_support_cases_post

Request body

application/json (required): CaseInput

Field Type Required Description
entity string yes Code (or id) of the company.
queue string yes Code (or id) of the queue.
subject string yes What it is about. (min length 1; max length 300)
description string yes What the customer asked, as they said it. (min length 1; max length 100000)
channel "email" | "other" | "phone" | "web" How it came in. (default "phone")
priority "high" | "low" | "normal" | "urgent" Its priority. (default "normal")
party string or null Code (or id) of the customer.
contact_id string (uuid) or null The person at the customer (GET /v1/contacts).
requester_name string or null Who asked, when they are not a contact yet. (max length 200)
requester_email string or null Their e-mail address, which replies go to.
assignee_user_id string (uuid) or null Who works it (GET /v1/people); none: the queue assigns.

Example request

curl -X POST "$ERP_URL/v1/support/cases" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "phone",
  "description": "Ms Muster called: the invoice went to their old address.",
  "entity": "CH01",
  "party": "C-CH",
  "priority": "normal",
  "queue": "SUPPORT",
  "subject": "Invoice 2026-0042 shows the wrong address"
}'

Responses

Status Meaning Body
201 Created CaseDetail
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created_by": {
    "id": "user:alice",
    "name": "Alice",
    "type": "human"
  },
  "number": "CASE-000001"
}

GET /v1/support/cases/{case_id}

Get a case

The case with its messages (oldest first, drafts included), the addresses a reply may go to and whether replies can be e-mailed from here.

Required scope read (admin implies every scope)
Operation id get_case_v1_support_cases__case_id__get

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).

Example request

curl "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK CaseDetail
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created_by": {
    "id": "user:alice",
    "name": "Alice",
    "type": "human"
  },
  "number": "CASE-000001"
}

PATCH /v1/support/cases/{case_id}

Triage a case

Change the subject, queue, priority, person, customer, contact or requester (null clears the last four); a new queue or priority sets the due times anew from the case's start. An agent may triage. 409 support_case_closed for a closed case.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id update_case_v1_support_cases__case_id__patch

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).

Request body

application/json (required): CaseUpdate

Field Type Required Description
subject string or null What it is about. (min length 1; max length 300)
queue string or null Code (or id) of another queue.
priority "high" | "low" | "normal" | "urgent" or null low, normal, high or urgent; sets the due times anew.
party string or null Code (or id) of the customer.
contact_id string (uuid) or null A person at the customer.
requester_name string or null Who asked, when not a contact. (max length 200)
requester_email string or null Their e-mail address.
assignee_user_id string (uuid) or null Who works it.

Example request

curl -X PATCH "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "party": "C-DE",
  "priority": "high"
}'

Responses

Status Meaning Body
200 OK CaseDetail
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created_by": {
    "id": "user:alice",
    "name": "Alice",
    "type": "human"
  },
  "number": "CASE-000001"
}

POST /v1/support/cases/{case_id}/notes

Add an internal note

A note for colleagues on the case; it never leaves the system. An agent may add one.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id add_note_v1_support_cases__case_id__notes_post

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).

Request body

application/json (required): NoteInput

Field Type Required Description
body string yes The note; never sent. (min length 1; max length 100000)

Example request

curl -X POST "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b/notes" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "Carrier says the parcel is in Basel."
}'

Responses

Status Meaning Body
201 Created MessageOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "kind": "inbound",
  "status": "discarded",
  "sent_via": "email",
  "from_address": "string",
  "from_name": "string",
  "to": [
    "string"
  ],
  "subject": "string",
  "body": "string",
  "message_id": "string",
  "source": "api",
  "auto": true,
  "at": "2026-09-21T09:30:00Z",
  "sent_by": {},
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "updated_by": {},
  "updated_at": "2026-09-21T09:30:00Z"
}

POST /v1/support/cases/{case_id}/replies

Write a reply

A reply to the customer: draft keeps it for a person (an agent drafts only); send e-mails it now in the company's name, answered to the queue's inbox, with the case number in the subject; record notes it was answered elsewhere. Sending or recording is a person's (403 support_send_agent); it meets the first-reply level, and the case then waits on the customer (or then). 409 in a test copy or without a mail server for send; 422 for an address that is not the requester's, the contact's or the customer's; 429 beyond the hourly limit. Needs an Idempotency-Key.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id add_reply_v1_support_cases__case_id__replies_post

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).

Request body

application/json (required): ReplyInput

Field Type Required Description
body string yes The reply. (min length 1; max length 100000)
to array of string or null Recipients: the requester's, the contact's or the customer's addresses; none: the requester (or the contact). (max items 10)
action "draft" | "record" | "send" draft: keep it for a person to send; send: e-mail it now; record: it was answered elsewhere (phone, another mailbox) and is recorded as sent. Only a person sends or records. (default "draft")
then "closed" | "open" | "waiting" The case's status once sent or recorded. (default "waiting")

Example request

curl -X POST "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b/replies" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "action": "send",
  "body": "Dear Ms Muster,\n\nwe corrected the address and sent the invoice again.\n\nKind regards",
  "then": "waiting"
}'

Responses

Status Meaning Body
201 Created MessageOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "kind": "inbound",
  "status": "discarded",
  "sent_via": "email",
  "from_address": "string",
  "from_name": "string",
  "to": [
    "string"
  ],
  "subject": "string",
  "body": "string",
  "message_id": "string",
  "source": "api",
  "auto": true,
  "at": "2026-09-21T09:30:00Z",
  "sent_by": {},
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "updated_by": {},
  "updated_at": "2026-09-21T09:30:00Z"
}

PATCH /v1/support/cases/{case_id}/replies/{message_id}

Change a draft reply

Change a draft's text or recipients. 409 support_not_draft once it was sent or discarded.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id update_reply_v1_support_cases__case_id__replies__message_id__patch

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).
path message_id string (uuid) yes Id of the message (the case's messages).

Request body

application/json (required): DraftUpdate

Field Type Required Description
body string or null The reply's new text. (min length 1; max length 100000)
to array of string or null Its recipients: the requester's, the contact's or the customer's addresses. (max items 10)

Example request

curl -X PATCH "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b/replies/5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "Dear Ms Muster,\n\nthe parcel left today."
}'

Responses

Status Meaning Body
200 OK MessageOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "kind": "inbound",
  "status": "discarded",
  "sent_via": "email",
  "from_address": "string",
  "from_name": "string",
  "to": [
    "string"
  ],
  "subject": "string",
  "body": "string",
  "message_id": "string",
  "source": "api",
  "auto": true,
  "at": "2026-09-21T09:30:00Z",
  "sent_by": {},
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "updated_by": {},
  "updated_at": "2026-09-21T09:30:00Z"
}

POST /v1/support/cases/{case_id}/replies/{message_id}/discard

Discard a draft reply

Drop a draft: it is kept, discarded, and no longer shown on the case.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id discard_reply_v1_support_cases__case_id__replies__message_id__discard_post

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).
path message_id string (uuid) yes Id of the message (the case's messages).

Example request

curl -X POST "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b/replies/5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d/discard" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK MessageOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "kind": "inbound",
  "status": "discarded",
  "sent_via": "email",
  "from_address": "string",
  "from_name": "string",
  "to": [
    "string"
  ],
  "subject": "string",
  "body": "string",
  "message_id": "string",
  "source": "api",
  "auto": true,
  "at": "2026-09-21T09:30:00Z",
  "sent_by": {},
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "updated_by": {},
  "updated_at": "2026-09-21T09:30:00Z"
}

POST /v1/support/cases/{case_id}/replies/{message_id}/send

Send a draft reply

Send the draft by e-mail (via email) or record that it was answered elsewhere (outside). A person's (403 support_send_agent). Needs an Idempotency-Key.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id send_reply_v1_support_cases__case_id__replies__message_id__send_post

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).
path message_id string (uuid) yes Id of the message (the case's messages).

Request body

application/json (optional): ReplySendInput or null

Example request

curl -X POST "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b/replies/5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d/send" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "via": "email",
  "then": "waiting"
}'

Responses

Status Meaning Body
200 OK MessageOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError
429 A per-organization limit was reached, e.g. messages sent per hour (rate_limited, with retry_after_seconds). ErrorEnvelope

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "kind": "inbound",
  "status": "discarded",
  "sent_via": "email",
  "from_address": "string",
  "from_name": "string",
  "to": [
    "string"
  ],
  "subject": "string",
  "body": "string",
  "message_id": "string",
  "source": "api",
  "auto": true,
  "at": "2026-09-21T09:30:00Z",
  "sent_by": {},
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "updated_by": {},
  "updated_at": "2026-09-21T09:30:00Z"
}

POST /v1/support/cases/{case_id}/status

Close, reopen or set a case to wait

closed (with how it was resolved), waiting (on the customer: the resolution clock stands still) or open again. A person's call: 403 support_status_agent for an agent.

Required scope draft (admin implies every scope)
Idempotency-Key not used
Operation id set_case_status_v1_support_cases__case_id__status_post

Parameters

In Name Type Required Description
path case_id string (uuid) yes Id of the case (GET /v1/support/cases).

Request body

application/json (required): StatusInput

Field Type Required Description
status "closed" | "open" | "waiting" yes open, waiting (on the customer: the resolution clock stands still) or closed.
resolution string or null How it was resolved (closing). (min length 1; max length 2000)

Example request

curl -X POST "$ERP_URL/v1/support/cases/3e4f5a6b-7c8d-4e9f-8a0b-1c2d3e4f5a6b/status" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "resolution": "Address corrected.",
  "status": "closed"
}'

Responses

Status Meaning Body
200 OK CaseDetail
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "created_by": {
    "id": "user:alice",
    "name": "Alice",
    "type": "human"
  },
  "number": "CASE-000001"
}

POST /v1/support/inbound

Hand over an e-mail to a queue's inbox

For a mail service or an integration that receives the inbox's mail: the e-mail becomes a case of the queue whose inbox it was sent to, or a message of the case it answers (by In-Reply-To, References or the case number in the subject), which it reopens. Kept once per Message-ID (duplicate). null for an automatic message that answers no case. 422 support_inbox_unknown when no active queue has an address it went to. A linked Google mailbox that receives the inbox's mail hands it over by itself. Needs an Idempotency-Key.

Required scope draft (admin implies every scope)
Idempotency-Key required
Operation id receive_mail_v1_support_inbound_post

Request body

application/json (required): InboundInput

Field Type Required Description
to array of string yes The addresses it was sent to (To and Cc). (min items 1; max items 50)
from_address string yes The sender's address.
from_name string or null The sender's name. (max length 200)
subject string The subject. (max length 1000; default "")
body string yes The text of the message. (max length 100000)
message_id string or null Its Message-ID: handed over twice, kept once. (max length 500)
in_reply_to string or null In-Reply-To. (max length 500)
references array of string The Message-IDs of References. (max items 100)
received_at string (date-time) or null When it arrived.
auto boolean An automatic message (out of office, a bounce): kept on its case, but it opens no case and reopens none. (default false)

Example request

curl -X POST "$ERP_URL/v1/support/inbound" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "Hello, our order 2026-0107 has not arrived yet.",
  "from_address": "anna.muster@kunde.example",
  "from_name": "Anna Muster",
  "message_id": "<CAF1234@mail.kunde.example>",
  "subject": "Delivery missing",
  "to": [
    "support@example.ch"
  ]
}'

Responses

Status Meaning Body
200 OK InboundOut or null
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "case": {
    "created_by": {
      "id": "user:alice",
      "name": "Alice",
      "type": "human"
    },
    "number": "CASE-000001"
  },
  "message_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "created": true,
  "duplicate": true
}

GET /v1/support/queues

List support queues

The support queues by code: inbox address, service levels, working hours, members and how many cases are open.

Required scope read (admin implies every scope)
Operation id list_queues_v1_support_queues_get

Parameters

In Name Type Required Description
query entity string or null Only this company's (code or id).

Example request

curl "$ERP_URL/v1/support/queues" \
  -H "Authorization: Bearer $ERP_KEY"

Responses

Status Meaning Body
200 OK array of QueueOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "entity": "string",
    "code": "string",
    "name": "string",
    "inbound_address": "string",
    "sla": {},
    "business_hours": {
      "days": [
        null
      ],
      "start": "string",
      "end": "string"
    },
    "time_zone": "string",
    "auto_assign": true,
    "active": true,
    "members": [
      {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "email": "string",
        "name": null
      }
    ],
    "open_cases": 1,
    "created_by": {},
    "created_at": "2026-09-21T09:30:00Z",
    "updated_by": {},
    "updated_at": "2026-09-21T09:30:00Z"
  }
]

POST /v1/support/queues

Add a support queue

A queue of a company: its code and name, the address customers write to (its inbox), the service levels per priority in working minutes, the working hours (none: around the clock) in the company's time zone, its members and whether it assigns new cases to them. 409 support_queue_exists for a code in use, support_address_taken for an inbox another queue has. Needs an Idempotency-Key.

Required scope admin (admin implies every scope)
Idempotency-Key required
Operation id create_queue_v1_support_queues_post

Request body

application/json (required): QueueInput

Field Type Required Description
entity string yes Code (or id) of the company (entity).
code string yes Its code, e.g. SUPPORT; never changes. (pattern ^[A-Z0-9][A-Z0-9_-]{0,19}$)
name string yes Its name. (min length 1; max length 80)
inbound_address string or null The address customers write to (the shared inbox): e-mail to it becomes cases of this queue, and replies sent from here ask to be answered to it. One queue per address in the organization.
sla map of SlaTarget The service levels by priority (urgent, high, normal, low): the working minutes to the first reply and to the resolution. A priority left out has no target.
business_hours BusinessHours or null When the clock runs; none: around the clock.
auto_assign boolean A new case without a person goes to the member with the fewest open cases. (default false)
members array of string (uuid) The people who work it (GET /v1/people). (max items 200)

Example request

curl -X POST "$ERP_URL/v1/support/queues" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "auto_assign": true,
  "business_hours": {
    "days": [
      1,
      2,
      3,
      4,
      5
    ],
    "end": "17:00",
    "start": "08:00"
  },
  "code": "SUPPORT",
  "entity": "CH01",
  "inbound_address": "support@example.ch",
  "members": [],
  "name": "Customer support",
  "sla": {
    "normal": {
      "first_response_minutes": 480,
      "resolution_minutes": 2700
    },
    "urgent": {
      "first_response_minutes": 60,
      "resolution_minutes": 480
    }
  }
}'

Responses

Status Meaning Body
201 Created QueueOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "code": "string",
  "name": "string",
  "inbound_address": "string",
  "sla": {},
  "business_hours": {
    "days": [
      1
    ],
    "start": "string",
    "end": "string"
  },
  "time_zone": "string",
  "auto_assign": true,
  "active": true,
  "members": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "email": "string",
      "name": "string"
    }
  ],
  "open_cases": 1,
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "updated_by": {},
  "updated_at": "2026-09-21T09:30:00Z"
}

PATCH /v1/support/queues/{queue_id}

Change a support queue

Change what the request names: name, inbox ("" removes it), service levels (the whole set), working hours (null: around the clock), members (the whole list), automatic assignment, or active (false: no new case goes to it). New targets apply to the cases opened, or moved to another priority or queue, from then on.

Required scope admin (admin implies every scope)
Idempotency-Key not used
Operation id update_queue_v1_support_queues__queue_id__patch

Parameters

In Name Type Required Description
path queue_id string (uuid) yes Id of the queue (GET /v1/support/queues).

Request body

application/json (required): QueueUpdate

Field Type Required Description
name string or null Its name. (min length 1; max length 80)
inbound_address string or null The shared inbox address; "" removes it.
sla map of SlaTarget or null The service levels by priority (urgent, high, normal, low): the working minutes to the first reply and to the resolution. A priority left out has no target. Replaces the whole set.
business_hours BusinessHours or null When the clock runs; null: around the clock.
auto_assign boolean or null Assign new cases automatically.
active boolean or null false: no new case goes to it; the cases in it stay.
members array of string (uuid) or null The people who work it; replaces the list. (max items 200)

Example request

curl -X PATCH "$ERP_URL/v1/support/queues/4f5a6b7c-8d9e-4f0a-9b1c-2d3e4f5a6b7c" \
  -H "Authorization: Bearer $ERP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "auto_assign": true,
  "sla": {
    "urgent": {
      "first_response_minutes": 30,
      "resolution_minutes": 240
    }
  }
}'

Responses

Status Meaning Body
200 OK QueueOut
401 Missing or invalid API key (unauthorized). ErrorEnvelope
403 The caller lacks the required scope (missing_right, with scope), the key belongs to no person where a person is needed (forbidden), or the approval policy denies the action (policy_denied, with action and rule_id). ErrorEnvelope
404 The resource does not exist, or belongs to another organization (not_found). ErrorEnvelope
409 The request conflicts with the data: an Idempotency-Key reused with a different request, a closed period, or an integrity rule of the database (conflict, integrity_violation). ErrorEnvelope
422 Validation failed: the error envelope (validation_failed). For a malformed body or parameter its message is in sentences ("Line 2: the quantity must be above zero") and fields lists each error with pydantic's loc, type and msg beside its sentence (message) and its parts, to word it in another language: items (name and number from 1: line 2), field (its name as sent) and the rule it breaks with its limit, count and choices (none for a validator's own sentence); FastAPI's own detail list stays beside the envelope. HTTPValidationError

Example response (shape)

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "entity": "string",
  "code": "string",
  "name": "string",
  "inbound_address": "string",
  "sla": {},
  "business_hours": {
    "days": [
      1
    ],
    "start": "string",
    "end": "string"
  },
  "time_zone": "string",
  "auto_assign": true,
  "active": true,
  "members": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "email": "string",
      "name": "string"
    }
  ],
  "open_cases": 1,
  "created_by": {},
  "created_at": "2026-09-21T09:30:00Z",
  "updated_by": {},
  "updated_at": "2026-09-21T09:30:00Z"
}

Schemas

BusinessHours

Field Type Required Description
days array of integer yes ISO weekdays the clock runs: 1 Monday ... 7 Sunday. (min items 1; max items 7)
start string yes When the working day starts, HH:MM where the company is.
end string yes When it ends, HH:MM, after the start.

CaseDetail

Field Type Required Description
id string (uuid) yes The case's id.
entity string yes Code of the company.
number string yes Its number, CASE-000001.
queue string yes Code of the queue.
queue_name string yes Name of the queue.
subject string yes What it is about.
status "closed" | "open" | "waiting" yes open, waiting (on the customer) or closed.
priority "high" | "low" | "normal" | "urgent" yes low, normal, high or urgent.
channel "email" | "other" | "phone" | "web" yes How it came in: email, phone, web or other.
party_id string (uuid) or null yes Id of the customer.
party_code string or null yes Code of the customer.
party_name string or null yes Name of the customer.
contact_id string (uuid) or null yes Id of the person at the customer.
contact_name string or null yes Their name.
requester_name string or null yes Who asked, when not a contact.
requester_email string or null yes Their address, where replies go.
assignee Person or null yes Who works it; none: nobody yet.
first_response SlaOut yes The service level for the first reply.
resolution SlaOut yes The service level for the resolution.
breached boolean yes A service level is breached.
resolution_note string or null yes How it was resolved.
drafts integer yes Replies drafted and not sent yet.
last_message_at string (date-time) yes When the last message came or went (UTC).
closed_at string (date-time) or null yes When it was closed (UTC).
closed_by object or null yes Who closed it (actor object).
created_by object yes Who opened it (actor object).
created_at string (date-time) yes When (UTC).
updated_by object or null yes Who changed it last.
updated_at string (date-time) or null yes When (UTC).
messages array of MessageOut yes What was said, the oldest first.
recipients array of string yes The addresses a reply may go to.
sending_configured boolean yes Replies can be e-mailed from here (false in a test copy, or without a mail server: record a reply sent elsewhere).
test_copy boolean yes This is a test copy: it never sends e-mail.
customer_context CustomerContext or null Cross-function context (open/overdue invoices, active subscriptions, open opportunities) when the case is linked to a customer.

CaseInput

Field Type Required Description
entity string yes Code (or id) of the company.
queue string yes Code (or id) of the queue.
subject string yes What it is about. (min length 1; max length 300)
description string yes What the customer asked, as they said it. (min length 1; max length 100000)
channel "email" | "other" | "phone" | "web" How it came in. (default "phone")
priority "high" | "low" | "normal" | "urgent" Its priority. (default "normal")
party string or null Code (or id) of the customer.
contact_id string (uuid) or null The person at the customer (GET /v1/contacts).
requester_name string or null Who asked, when they are not a contact yet. (max length 200)
requester_email string or null Their e-mail address, which replies go to.
assignee_user_id string (uuid) or null Who works it (GET /v1/people); none: the queue assigns.

CaseOut

Field Type Required Description
id string (uuid) yes The case's id.
entity string yes Code of the company.
number string yes Its number, CASE-000001.
queue string yes Code of the queue.
queue_name string yes Name of the queue.
subject string yes What it is about.
status "closed" | "open" | "waiting" yes open, waiting (on the customer) or closed.
priority "high" | "low" | "normal" | "urgent" yes low, normal, high or urgent.
channel "email" | "other" | "phone" | "web" yes How it came in: email, phone, web or other.
party_id string (uuid) or null yes Id of the customer.
party_code string or null yes Code of the customer.
party_name string or null yes Name of the customer.
contact_id string (uuid) or null yes Id of the person at the customer.
contact_name string or null yes Their name.
requester_name string or null yes Who asked, when not a contact.
requester_email string or null yes Their address, where replies go.
assignee Person or null yes Who works it; none: nobody yet.
first_response SlaOut yes The service level for the first reply.
resolution SlaOut yes The service level for the resolution.
breached boolean yes A service level is breached.
resolution_note string or null yes How it was resolved.
drafts integer yes Replies drafted and not sent yet.
last_message_at string (date-time) yes When the last message came or went (UTC).
closed_at string (date-time) or null yes When it was closed (UTC).
closed_by object or null yes Who closed it (actor object).
created_by object yes Who opened it (actor object).
created_at string (date-time) yes When (UTC).
updated_by object or null yes Who changed it last.
updated_at string (date-time) or null yes When (UTC).

CaseUpdate

What changes; a field sent as null is cleared (the customer, contact, requester, person).

Field Type Required Description
subject string or null What it is about. (min length 1; max length 300)
queue string or null Code (or id) of another queue.
priority "high" | "low" | "normal" | "urgent" or null low, normal, high or urgent; sets the due times anew.
party string or null Code (or id) of the customer.
contact_id string (uuid) or null A person at the customer.
requester_name string or null Who asked, when not a contact. (max length 200)
requester_email string or null Their e-mail address.
assignee_user_id string (uuid) or null Who works it.

CustomerContext

Cross-function customer summary shown on a support case.

Field Type Required Description
open_invoices integer Number of open posted documents for this customer. (default 0)
overdue_invoices integer Number of overdue posted documents for this customer. (default 0)
active_subscriptions integer Number of active recurring subscriptions for this customer. (default 0)
open_opportunities integer Number of open sales pipeline deals for this customer. (default 0)

DraftUpdate

Field Type Required Description
body string or null The reply's new text. (min length 1; max length 100000)
to array of string or null Its recipients: the requester's, the contact's or the customer's addresses. (max items 10)

InboundInput

Field Type Required Description
to array of string yes The addresses it was sent to (To and Cc). (min items 1; max items 50)
from_address string yes The sender's address.
from_name string or null The sender's name. (max length 200)
subject string The subject. (max length 1000; default "")
body string yes The text of the message. (max length 100000)
message_id string or null Its Message-ID: handed over twice, kept once. (max length 500)
in_reply_to string or null In-Reply-To. (max length 500)
references array of string The Message-IDs of References. (max items 100)
received_at string (date-time) or null When it arrived.
auto boolean An automatic message (out of office, a bounce): kept on its case, but it opens no case and reopens none. (default false)

InboundOut

Field Type Required Description
case CaseOut yes The case the message is on.
message_id string (uuid) yes Id of the message on the case.
created boolean yes A new case was opened.
duplicate boolean yes The message was there already: nothing changed.

MessageOut

Field Type Required Description
id string (uuid) yes The message's id.
kind "inbound" | "note" | "reply" yes inbound (from the customer), reply (to them) or note (internal).
status "discarded" | "draft" | "received" | "saved" | "sent" yes received (inbound), saved (note), draft, sent or discarded.
sent_via "email" | "outside" or null yes A sent reply: email from here, or outside (answered elsewhere).
from_address string or null yes The sender's address.
from_name string or null yes The sender's name.
to array of string yes The recipients.
subject string or null yes The subject.
body string yes The text.
message_id string or null yes The e-mail's Message-ID.
source "api" | "google_mail" or null yes How an inbound message came: a linked Gmail inbox or the API.
auto boolean yes An automatic message (out of office, bounce).
at string (date-time) yes When it was received or sent (UTC).
sent_by object or null yes Who sent the reply (actor object).
created_by object yes Who wrote or recorded it (actor object).
created_at string (date-time) yes When (UTC).
updated_by object or null yes Who changed the draft last.
updated_at string (date-time) or null yes When (UTC).

NoteInput

Field Type Required Description
body string yes The note; never sent. (min length 1; max length 100000)

QueueInput

Field Type Required Description
entity string yes Code (or id) of the company (entity).
code string yes Its code, e.g. SUPPORT; never changes. (pattern ^[A-Z0-9][A-Z0-9_-]{0,19}$)
name string yes Its name. (min length 1; max length 80)
inbound_address string or null The address customers write to (the shared inbox): e-mail to it becomes cases of this queue, and replies sent from here ask to be answered to it. One queue per address in the organization.
sla map of SlaTarget The service levels by priority (urgent, high, normal, low): the working minutes to the first reply and to the resolution. A priority left out has no target.
business_hours BusinessHours or null When the clock runs; none: around the clock.
auto_assign boolean A new case without a person goes to the member with the fewest open cases. (default false)
members array of string (uuid) The people who work it (GET /v1/people). (max items 200)

QueueOut

Field Type Required Description
id string (uuid) yes The queue's id.
entity string yes Code of the company.
code string yes Its code.
name string yes Its name.
inbound_address string or null yes The shared inbox address; none: no inbox.
sla map of SlaTarget yes The service levels by priority (urgent, high, normal, low): the working minutes to the first reply and to the resolution. A priority left out has no target.
business_hours BusinessHours or null yes When the clock runs; none: around the clock.
time_zone string yes The company's time zone, in which the hours run.
auto_assign boolean yes New cases go to the member with the fewest open.
active boolean yes false: no new case goes to it.
members array of Person yes The people who work it.
open_cases integer yes Its cases open or waiting on the customer.
created_by object yes Who set it up (actor object).
created_at string (date-time) yes When (UTC).
updated_by object or null yes Who changed it last.
updated_at string (date-time) or null yes When (UTC).

QueueUpdate

Field Type Required Description
name string or null Its name. (min length 1; max length 80)
inbound_address string or null The shared inbox address; "" removes it.
sla map of SlaTarget or null The service levels by priority (urgent, high, normal, low): the working minutes to the first reply and to the resolution. A priority left out has no target. Replaces the whole set.
business_hours BusinessHours or null When the clock runs; null: around the clock.
auto_assign boolean or null Assign new cases automatically.
active boolean or null false: no new case goes to it; the cases in it stay.
members array of string (uuid) or null The people who work it; replaces the list. (max items 200)

ReplyInput

Field Type Required Description
body string yes The reply. (min length 1; max length 100000)
to array of string or null Recipients: the requester's, the contact's or the customer's addresses; none: the requester (or the contact). (max items 10)
action "draft" | "record" | "send" draft: keep it for a person to send; send: e-mail it now; record: it was answered elsewhere (phone, another mailbox) and is recorded as sent. Only a person sends or records. (default "draft")
then "closed" | "open" | "waiting" The case's status once sent or recorded. (default "waiting")

ReplySendInput

Field Type Required Description
via "email" | "outside" email: send it from here; outside: it was answered elsewhere. (default "email")
then "closed" | "open" | "waiting" The case's status afterwards. (default "waiting")

SlaOut

Field Type Required Description
due_at string (date-time) or null yes When it is due (UTC); none: no target.
met_at string (date-time) or null yes When it was met (UTC).
state "breached" | "met" | "none" | "paused" | "running" yes none (no target), running, paused (waiting on the customer or closed), met or breached (late, or met late).
minutes_left integer or null yes Working minutes until it is due while it runs (negative: overdue).

SlaTarget

Field Type Required Description
first_response_minutes integer or null Working minutes to the first reply. (min 1; max 525600)
resolution_minutes integer or null Working minutes to the resolution; the time a case waits on the customer or is closed does not count. (min 1; max 525600)

StatusInput

Field Type Required Description
status "closed" | "open" | "waiting" yes open, waiting (on the customer: the resolution clock stands still) or closed.
resolution string or null How it was resolved (closing). (min length 1; max length 2000)
Stabiso, the Enterprise System of Record · generated from the code and its guides · release 6f03a5e846b3