Turnover Report
Returns aggregated turnover, groupable by treating user, insurance service, cost center, customer, billing status, and time period.
The data basis and limitations of this section are described in the section overview — in particular, that these endpoints report on fee note services, not invoices.
Request
GET /api/oauth/v2/resource/fee-note-services/turnover
Header
| Header | Value |
|---|---|
Authorization | Bearer {access_token} |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string (ISO date) | Yes | Start of the time range |
until | string (ISO date) | Yes | End of the time range |
groupBy | string | No | Comma list from treatingUser, insuranceService, costCenter, customer, billStatus, day, week, month, year. At most one time token. Default: insuranceService,month |
billStatus | string | No | Comma-separated list of open, invoiced, ignore, unknown (OR). Any other value returns 400 validation_error |
treatingUserId | string (UUID) | No | Filters by treating user |
customerId | string (UUID) | No | Filters by customer. Additionally requires the customers scope |
offset | integer | No | Start position (default: 0) |
limit | integer | No | Number of results (default: 50, max: 200) |
Note:
groupBy=customeror a setcustomerIdadditionally require thecustomersscope. Without it, the endpoint responds with403 insufficient_scope.
Note on sorting: Rows come in a stable order — a repeated call with the same filter and page returns the same order. A requested time bucket (
day,week,month,year) sorts first, so time series come out chronologically.
Note on deleted patients: Fee note services of deleted patients are not included in turnover.
Response
Success (200 OK)
{
"data": [
{
"period": "2026-03",
"treatingUser": "6f1c1a2b-3c4d-5e6f-7890-abcdef123456",
"insuranceService": "3a8b1c2d-3e4f-5061-7283-94a5b6c7d8e9",
"costCenter": null,
"customer": null,
"billStatus": "invoiced",
"gross": 4820.00,
"net": 4820.00,
"quantity": 62.000,
"count": 58
},
{
"period": "2026-03",
"treatingUser": "6f1c1a2b-3c4d-5e6f-7890-abcdef123456",
"insuranceService": null,
"costCenter": null,
"customer": null,
"billStatus": "open",
"gross": 310.00,
"net": 310.00,
"quantity": 4.000,
"count": 4
}
],
"meta": { "total": 143, "offset": 0, "limit": 50 }
}"insuranceService": null is either a dimension you didn't request, or the collective bucket for free-text services without a linked insurance service.
Response fields
| Field | Type | Description |
|---|---|---|
data | Array | List of aggregated turnover rows |
data[].period | string | null | Time bucket, format depends on the time token in groupBy (e.g. 2026-03 for month), null if no time token was requested |
data[].treatingUser | string (UUID) | null | ID of the treating user, null if not requested. Loadable via Get User |
data[].insuranceService | string (UUID) | null | ID of the service. null if not requested or the collective bucket for free-text services. No OAuth endpoint to load it, see Conventions |
data[].costCenter | string | null | Cost center of the service — the "category" of these reports, see terminology. null if not requested |
data[].customer | string (UUID) | null | ID of the customer, null if not requested. Loadable via Get Customer |
data[].billStatus | string | null | Billing status: open, invoiced, ignore, unknown, null if not requested |
data[].gross | float | Gross amount |
data[].net | float | Net amount |
data[].quantity | float | Summed quantity |
data[].count | integer | Number of underlying fee note services |
meta.total | integer | Total number of groups |
meta.offset | integer | Current start position |
meta.limit | integer | Number of returned entries |
curl -X GET "https://my.offisy.at/api/oauth/v2/resource/fee-note-services/turnover?from=2026-01-01&until=2026-12-31&groupBy=insuranceService%2Cmonth&billStatus=beispiel&treatingUserId=b2c3d4e5-f6a7-8901-bcde-f01234567890&customerId=b2c3d4e5-f6a7-8901-bcde-f01234567890&offset=0&limit=50" \
-H "Authorization: Bearer {access_token}"Possible errors
| Status | Code | Description |
|---|---|---|
| 400 | validation_error | Missing or invalid from/until, invalid dimension, more than one time token, or time range too long |
| 400 | validation_error | treatingUserId or customerId is not a valid UUID |
| 400 | invalid_request | The API access is not assigned to a user — assign a user to it in the Offisy settings |
| 401 | invalid_client | Invalid or missing access token |
| 403 | insufficient_scope | Scope reports (with groupBy=customer/customerId, additionally customers) missing |
| 403 | access_denied | The owning user of your API access lacks the Abrechnungsleistungen (Verrechnung): Journaling permission |
| 403 | access_denied | Tenancies add-on is active, but no tenancy is accessible to the owning user of your API access (error_description: No tenancy is accessible to this user.) |
| 404 | not_found | treatingUserId or customerId does not reference an existing record |