Download OpenAPI specification:
The Losys Customer API lets you read your company's construction project references (photos, location, description, services rendered) and generate PDF documents from them — directly from your own website or backend.
A runnable, public reference implementation is available in the
losys-demo repository. When in
doubt about a concrete request, that demo is the canonical example.
All endpoints are relative to a single fixed base URL that already includes
the /api/customer path prefix:
https://api.referenz-verwaltung.ch/api/customer/
So the project list, for example, is
GET https://api.referenz-verwaltung.ch/api/customer/project. The same base
URL is shown under Servers above and is used for the interactive
examples.
The Customer API uses OAuth 2.0 with the client_credentials grant.
You receive a client_id and a client_secret from Losys. Each client is
bound to exactly one company — that company is pinned into the issued
token. As a result, none of the endpoints below take a company id in the
path: every call automatically operates within your company's scope.
If you are new to OAuth 2.0, these are good starting points:
Obtain an access token:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<your-client-id>
&client_secret=<your-client-secret>
The response contains an access_token. Send it as a Bearer token with
every request:
Authorization: Bearer <access_token>
Accept: application/json
Accept-Language: en
Almost all responses can be localized via the Accept-Language request
header. Supported languages: de, fr, it, en.
The API can return gzip-compressed responses. Send
Accept-Encoding: gzip
and responses that are large enough to benefit (currently from ~4 KB of
payload) are returned compressed, indicated by a Content-Encoding: gzip
response header (smaller responses are sent uncompressed). Any standard HTTP
client handles the decompression transparently. Using compression is
recommended for the (potentially large) project list responses.
List endpoints are paginated via limit and start (offset). When paging
through a result set you must send exactly the same filter parameters on
every request (only start and limit may change) — otherwise the
results are inconsistent. To enforce this, every response returns an
X-Paginator-Hash header; send it back on the next request and the API
verifies your filter parameters did not change. This is strongly recommended.
Every paginated response carries a set of X-Paginator-* headers describing
the current page and the full result set:
| Header | Meaning |
|---|---|
X-Paginator-Start |
Offset of the first returned record (echoes your start). |
X-Paginator-Limit |
Page size in effect (echoes your limit). |
X-Paginator-Count |
Number of records actually returned in this response. |
X-Paginator-Total |
Total number of records matching your filter across all pages. |
X-Paginator-Has-Previous-Page |
1 if a previous page exists, otherwise 0. |
X-Paginator-Has-Next-Page |
1 if a next page exists, otherwise 0. |
X-Paginator-Hash |
Filter fingerprint — send it back as a request header on the next page (see above and below). |
X-Paginator-Hash headerProject lists are served through a cache. This has two practical consequences when paging:
The first page may take a moment longer when its cache is still cold — the result has to be computed (and, in the background, the following pages are pre-warmed).
Subsequent pages are then served much faster from the warm cache — but
only if you send the X-Paginator-Hash header you received with the
previous page back on the next request. The hash both guards filter
consistency and lets the API hit the pre-warmed cache entry for the next
page. Omitting it forfeits the speed-up.
So the recommended loop is: read X-Paginator-Hash from each response and
send it back (unchanged) on the request for the next page, changing only
start (and keeping all filter parameters identical).
Every response carries an X-Request-Id header. Please include it when
contacting support about a specific request.
Read project references.
These are the very same projects you can browse and edit interactively in
the web GUI under
https://referenz-verwaltung.ch/company/<your-company-id>/dashboard.
Two rules govern which projects the API returns:
Projects endpoints return the projects of
all companies in that group, not only your own company's.Returns a paginated list of your company's project references. Use the
query parameters to filter, sort and page the result, and expand to
include related entities.
Only "API-visible" projects are returned, and — for companies that belong to a company group — projects of all companies in the group (see the Projects section intro above).
Discovering valid filter values: the concrete values you may pass to
the filter parameters (type-of-work / type-of-building / type-of-construction
ids, category ids, cantons, languages, years, project-attribute ids …)
can be retrieved from the
Available filter values endpoint
(GET /project/filter_multiple_choice_values). That endpoint only ever
returns values that actually occur in projects you have access to, so it
is the canonical source for populating a filter UI.
| projectId | integer Restrict to a single project id. | ||||||||||||||||||||||||||||
| projectIds | Array of integers <= 4000 items Restrict to these project ids. | ||||||||||||||||||||||||||||
| companyId | integer Restrict to a single company id (subject to access checks). | ||||||||||||||||||||||||||||
| companyIds | Array of integers <= 400 items Restrict to these company ids (subject to access checks). | ||||||||||||||||||||||||||||
| groupId | integer Restrict to projects of the member companies of a single group. | ||||||||||||||||||||||||||||
| groupIds | Array of integers <= 100 items Restrict to projects of the member companies of these groups. | ||||||||||||||||||||||||||||
| yearFrom | integer Earliest year of completion (inclusive). | ||||||||||||||||||||||||||||
| yearTo | integer Latest year of completion (inclusive). | ||||||||||||||||||||||||||||
| language | string Single language short name, e.g. A language can only be used to retrieve projects if your company has
actually configured that language — projects only exist in the languages
the company maintains. The languages available to you are listed under
| ||||||||||||||||||||||||||||
| languages | Array of strings <= 10 items Language short names, e.g. Only languages your company has configured can be requested (see the
single | ||||||||||||||||||||||||||||
| categoryId | integer Restrict to a single category id. | ||||||||||||||||||||||||||||
| categoryIds | Array of integers <= 400 items | ||||||||||||||||||||||||||||
| canton | string Single Swiss canton short name, e.g. | ||||||||||||||||||||||||||||
| cantons | Array of strings <= 75 items Swiss canton short names, e.g. | ||||||||||||||||||||||||||||
| typeOfWorkId | integer Restrict to a single "type of work" id. | ||||||||||||||||||||||||||||
| typeOfWorkIds | Array of integers <= 400 items Restrict to these "type of work" ids. | ||||||||||||||||||||||||||||
| typeOfConstructionId | integer Restrict to a single "type of construction" id. | ||||||||||||||||||||||||||||
| typeOfConstructionIds | Array of integers <= 400 items Restrict to these "type of construction" ids. | ||||||||||||||||||||||||||||
| typeOfBuildingId | integer Restrict to a single "type of building" id. | ||||||||||||||||||||||||||||
| typeOfBuildingIds | Array of integers <= 400 items Restrict to these "type of building" ids. | ||||||||||||||||||||||||||||
| withImage | boolean Only projects that have at least one image. | ||||||||||||||||||||||||||||
| searchText | string <= 400 characters Full-text search phrase. Multiple words are combined per | ||||||||||||||||||||||||||||
| searchTextIn | Array of strings <= 4 items Items Enum: "project" "companies" "typeOfWork" Where to search. Defaults to all of them when omitted. Ignored when | ||||||||||||||||||||||||||||
| concatenation | string Default: "and" Enum: "and" "or" "fuzzy" How multiple search words are combined. | ||||||||||||||||||||||||||||
| orderBy | Array of strings <= 25 items [ items^!?(yearOfCompletion|hasImage|id|zipcode|city... ] Sort criteria, applied in order. Allowed values:
| ||||||||||||||||||||||||||||
| status | string Enum: "1" "0" "true" "false" "on" "off" "active" "inactive" "null" Filters projects by their visibility flag. By default the API already
restricts results to API-visible projects (see the Projects section
intro); Accepted values (a wide range of truthy/falsy spellings is supported):
Examples: | ||||||||||||||||||||||||||||
Array of objects (AttributeFilter) Advanced filter on project attributes (the configurable project
properties / custom fields a company defines). Each entry of the array
selects one or more attributes — by numeric The
Example — projects whose attribute named
See
| |||||||||||||||||||||||||||||
| limit | integer [ 0 .. 501 ] Maximum number of projects to return. Keep constant while paging. The server caps this at 501; values above are clamped. | ||||||||||||||||||||||||||||
| start | integer [ 0 .. 5000 ] Offset of the first project to return (for pagination). | ||||||||||||||||||||||||||||
| expand | Array of strings Items Enum: "project_images" "project_videos" "parent" "children" "project_properties" "project_categories" "project_type_of_works" "project_type_of_constructions" "project_type_of_buildings" "project_address_contact_persons" "project_participating_companies" "company" "language" "*" Related entities to include in the response. For every expand value
you pass, the corresponding sub-entity is embedded — under a key of the
same name — inside each project of the response. Pass several values
comma-separated or repeated, or Without
|
| Accept-Language | string Enum: "de" "fr" "it" "en" Language to localize the response into. One of |
| X-Paginator-Hash | string Send back the |
[- {
- "id": 0,
- "title": "string",
- "description": "string",
- "yearOfCompletion": 0,
- "address": "string",
- "zipcode": "string",
- "city": "string",
- "canton": "string",
- "country": "string",
- "geolocationX": "string",
- "geolocationY": "string",
- "projectWebsite": "string",
- "priority": 0,
- "companyId": 0,
- "languageId": 0,
- "parentId": 0,
- "status": "0",
- "visibility": [
- true
], - "project_images": [
- { }
], - "project_videos": [
- { }
], - "parent": { },
- "children": [
- { }
], - "project_properties": [
- { }
], - "project_categories": [
- { }
], - "project_type_of_works": [
- { }
], - "project_type_of_constructions": [
- { }
], - "project_type_of_buildings": [
- { }
], - "project_address_contact_persons": [
- { }
], - "project_participating_companies": [
- { }
], - "company": { },
- "language": { }
}
]| projectId required | integer Numeric id of the project. |
| expand | Array of strings Items Enum: "project_images" "project_videos" "parent" "children" "project_properties" "project_categories" "project_type_of_works" "project_type_of_constructions" "project_type_of_buildings" "project_address_contact_persons" "project_participating_companies" "company" "language" "*" Related entities to include in the response. For every expand value
you pass, the corresponding sub-entity is embedded — under a key of the
same name — inside each project of the response. Pass several values
comma-separated or repeated, or Without
|
{- "id": 0,
- "title": "string",
- "description": "string",
- "yearOfCompletion": 0,
- "address": "string",
- "zipcode": "string",
- "city": "string",
- "canton": "string",
- "country": "string",
- "geolocationX": "string",
- "geolocationY": "string",
- "projectWebsite": "string",
- "priority": 0,
- "companyId": 0,
- "languageId": 0,
- "parentId": 0,
- "status": "0",
- "visibility": [
- true
], - "project_images": [
- { }
], - "project_videos": [
- { }
], - "parent": { },
- "children": [
- { }
], - "project_properties": [
- { }
], - "project_categories": [
- { }
], - "project_type_of_works": [
- { }
], - "project_type_of_constructions": [
- { }
], - "project_type_of_buildings": [
- { }
], - "project_address_contact_persons": [
- { }
], - "project_participating_companies": [
- { }
], - "company": { },
- "language": { }
}Discover available filter values. The returned values are not the full set of values defined in the system — only those actually used by projects the caller has access to are returned.
Returns the values you can offer in a filter UI (type of work, type of
building, type of construction, categories, cantons, languages, years,
project attributes …), already localized. Optionally pass the same
filters as on /project/ to restrict the returned options.
Only values actually in use are returned. The endpoint does not list every value defined in the system — it returns only those values that are actually used by projects the caller has access to. A type of work, category, canton, language, etc. that no accessible project uses will not appear here. This keeps the filter UI free of options that would yield no results.
| displayLocale | string Language to localize the returned values into (e.g. |
{- "languages": [
- { }
], - "canton": [
- { }
], - "category": [
- { }
], - "quickFilter": [
- { }
], - "typeOfWork": {
- "property1": { },
- "property2": { }
}, - "typeOfBuilding": {
- "property1": { },
- "property2": { }
}, - "typeOfConstruction": {
- "property1": { },
- "property2": { }
}, - "attribute": [
- { }
], - "attributeByName": {
- "property1": { },
- "property2": { }
}, - "year": {
- "property1": 0,
- "property2": 0
}
}Starts an asynchronous PDF generation job for the projects matching
the given filters. Returns a job_uuid you can poll for completion via
/project/pdf/{jobUuid}/status.
Filter parameters are passed with a filter_ prefix (e.g.
filter_companyIds[]=1, filter_yearFrom=2020) and mirror the
parameters of /project/.
| printlayout | string PDF template id, or one of |
| mode | string Default: "extern" Enum: "extern" "intern" Which data variant to render:
|
| orientation | string Enum: "portrait" "landscape" Page orientation. Defaults depend on the chosen layout/template. |
| format | string Enum: "a4" "a3" Paper format of the generated PDF. When omitted, the format from the chosen layout/template is used ( |
| quality | string Default: "regular" Enum: "regular" "low" Image rendering quality of the generated PDF:
|
| displayLocale | string Language to render the PDF content in (e.g. |
| companycover | integer Company id to render a cover sheet for. |
| usercover | integer Employee id to render on the cover sheet. |
| secondusercover | integer Optional second employee id to render on the cover sheet. |
{- "job_uuid": "de25c4df-6d4e-439f-9d5f-a4c55d30f26e",
- "message": "string"
}Returns a ready-to-embed, interactive HTML widget (with built-in search,
map and PDF controls). Requires Accept: text/html.
| hide | Array of strings Items Enum: "search" "map" "pdf" UI components to hide. |
| skip_includes | Array of strings Items Enum: "jquery" "bootstrap" "popper" "select2" "polyfill" External libraries the widget should not load itself. |
{- "type": "string",
- "code": 0,
- "message": "string",
- "field_errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}