Migration guide, release 0.5.0
Release 0.5.0 replaces the monitoring API server. The functional model does not change: same artworks, same monitorings, same events, same lifecycle. What changes is a small number of contract details, listed here so that an integration can be adapted in one pass rather than discovered at runtime.
This page is for the teams calling the API directly, the StaRT mobile application first of all.
Versions: nothing to change
Section titled “Versions: nothing to change”The addresses keep their current form, with no version segment:
https://api.smach.science/artworksThe contract evolves compatibly, so a client keeps working as new fields and endpoints
appear. Should a later release ever need an incompatible version, it will be asked for
with an optional Api-Version request header. Without the header, a request is served
as version 1, which is the contract described here. There is nothing to send today.
API reference
Section titled “API reference”The API has its own portal, at the root of the API host: the reference of the whole API, every endpoint with its parameters and schemas, and getting-started guides.
| Environment | API portal | Reference |
|---|---|---|
| Production | api.smach.science | api.smach.science/reference |
| Development | api.dev.smach.science | api.dev.smach.science/reference |
Signing in with a SmaCH account of the environment lets you send requests from the page
itself, with your own token and the X-Organization header of your choice. The
OpenAPI description can be downloaded from the same page.
It replaces the Swagger UI of the previous server, which goes away with it.
What does not change
Section titled “What does not change”- Hosts.
https://api.dev.smach.scienceandhttps://api.smach.science. - Authentication. OAuth2 against Keycloak,
Bearertoken, same client and scopes. The realm changes on the development environment only, see below. - Organization context. The
X-Organizationheader, with the same resolution rules: optional for a member of a single organization, required beyond, free for a super-admin. - Resource paths and payloads.
/artworks,/monitorings,/inventories, the event structure, the status values and the ISO 8601 date format are unchanged. The one exception is the format of theidfield, see “Identifiers become UUIDs”.
Endpoints called by StaRT
Section titled “Endpoints called by StaRT”Read from the application’s source code on 2026-10-13 (branch dev, last changed on
2026-07-09). The application calls five endpoints:
| Endpoint | Phase | Changes |
|---|---|---|
GET /me |
login | same payload, served by another service, one role fixed, see below |
GET /artworks?status=ready |
artwork selection | pagination |
GET /artworks/{reference} |
artwork detail | none |
POST /artworks/{reference}/monitorings |
setup | unknown equipment refused, id format |
POST /artworks/{reference}/monitorings/events |
start, events, stop | none |
It does not call the inventory, the event list nor the event stream, which the StaRT API workflow also describes. The changes to those endpoints below concern any other integration.
Release 0.5.0 asks nothing of the application as it stands. Three choices of this
release exist for that reason, each one listed under its change below: the setup and the
push keep answering 200, the position of a gateway is read from the label the application
sends, and an error carries its text in message as well.
Changes
Section titled “Changes”Creating a resource answers 201
Section titled “Creating a resource answers 201”A successful POST now answers 201 Created with a Location header pointing at the
created resource, instead of 200. The response body is unchanged.
Impact: none if the client treats any 2xx as a success, a code change if it compares the status to 200 exactly.
Exception, for now: the setup (POST /artworks/{reference}/monitorings) and the event
push (POST /artworks/{reference}/monitorings/events) keep answering 200. The mobile
application compares their status to 200 exactly, and on any other success it would do
nothing. They move to 201 once a release of the application accepts it; the date will be
given here beforehand.
Collections are paginated
Section titled “Collections are paginated”A list endpoint returns 50 items by default, 200 at most, where the previous server returned the whole collection. The payload is still a plain JSON array, so nothing changes in parsing, but a caller that reads the array and stops will silently miss anything beyond the first page.
Two response headers carry the navigation:
Link(RFC 8288) withfirst,prev,nextandlastrelations. Followingnextopaquely is the recommended way to walk a collection.X-Total-Count, the total number of items matching the filters.
Request parameters: page (0-indexed), size, search, sort. They are documented per
endpoint in the OpenAPI description.
Impact: none as long as a collection holds fewer than 50 items, then silent truncation.
Following the Link header removes the problem for good.
The /count payload
Section titled “The /count payload”A <resource>/count endpoint now answers {"count": 42}. It previously answered
{"value": 42, "previous": null, "trend": null}, a shape meant for dashboard statistics.
Errors
Section titled “Errors”Errors are returned as RFC 9457 problem details, with the application/problem+json
content type and a detail field carrying the message.
The same text is also given in a message field, which is what the mobile application
displays. detail is the field of the contract; message will be withdrawn once the
application reads detail, announced here beforehand.
The inventory requires the administrator role
Section titled “The inventory requires the administrator role”Reading /inventories/* now requires the administrator role in the organization, or a
super-admin account. A member holding the viewer role receives a 403.
This matches the documented perimeter of the user roles: a viewer browses collections, artworks and their monitorings, and does not see the equipment. It has no effect on StaRT if the application signs in with an administrator or super-admin account, which is the documented usage.
Identifiers become UUIDs
Section titled “Identifiers become UUIDs”The id of every resource becomes a UUID, for example
0198c5a0-7c3e-7b1a-9d2f-4e6a8b0c1d2e, where the previous server returned a 24-character
hexadecimal string. It is still a JSON string.
This matters for monitorings and events, which have no other key: the id returned by a
setup is what the start and stop events carry as source, and what
/monitorings/{id} names. Artworks are still named by their reference and equipment by
its identity, which do not change.
Impact: none if the client stores and sends back the id as an opaque string, a code
change if it validates its length or its format. See also “Going to production” for the
monitorings that exist at the time of the switch.
The equipment named at setup must exist in the inventory
Section titled “The equipment named at setup must exist in the inventory”POST /artworks/{reference}/monitorings now answers 400 when a datalogger names a
logger, a sensor or a gateway that the inventory of the organization does not hold. The
message names the unknown equipment. The previous server accepted any value.
The comparison is exact: 8 and 08 are two different identities. The existing data
shows why it matters. The mobile application names a logger in decimal (18, 8), a
sensor as s followed by two hexadecimal digits (s12, s08) and a gateway on eight
digits (01000001), while the inventory was entered by hand as 12, 08 and GWR-001.
The devices do not carry a real IMEI yet.
The form the mobile application sends today becomes the identity, so nothing changes on its side. The inventory is aligned on it during the transfer, see “Going to production”. From 0.5.0 on, an equipment added to the inventory is entered in that same form, or the application will not find it at setup.
The position of a gateway is optional
Section titled “The position of a gateway is optional”At setup, the position of a gateway (cabin or trailer) may be omitted. The labels
the mobile application sends are understood, in English and in French: Cabin or
Cabine for the cabin, trailer or Remorque for the trailer. Any other value, such as
Non disponible, records the gateway without a position rather than refusing the setup.
An identity has no leading nor trailing space
Section titled “An identity has no leading nor trailing space”Creating or updating a logger, a sensor, a gateway or a packaging whose identity starts
or ends with a space answers 400. The previous server stored it as sent, which made two
items look alike and a reference miss its target.
An update cannot rename an equipment
Section titled “An update cannot rename an equipment”PUT /inventories/<kind>/{identity} answers 400 when the identity of the body differs
from the one in the URL. The previous server wrote the identity of the body, which renamed
the item under whatever referenced it.
Deleting an artwork deletes its history
Section titled “Deleting an artwork deletes its history”DELETE /artworks/{reference} now removes the artwork with its monitorings and their
events. The previous server removed the artwork alone and left the rest unreachable.
Archiving (status: archived) stays the ordinary way to retire an artwork and keeps
everything.
The deletion answers 409 while the artwork has a monitoring set up or in progress
(standby or monitoring): that history is still being written.
What a request may write on an artwork
Section titled “What a request may write on an artwork”Four rules the previous server did not hold. They concern the web application; the mobile application does not write artworks.
- The
organizationof an artwork is the one the request is made for, never the one in the body. The previous server stored the body as sent. PUT /artworks/{reference}answers 400 when thereferenceof the body differs from the one in the URL. An artwork is not renamed by an update.standbyandmonitoringfollow the monitoring of the artwork. A request that sets one of them, or moves an artwork out of one of them, answers 409; a creation acceptsdraftandreadyonly (400 otherwise). APUTwithout astatuskeeps the stored one.inclosureandcratemust name a packaging the inventory of the organization holds, of that kind: an unknown identity, or a crate given as inclosure, answers 400 with a message naming it.
Equipment in use cannot be deleted
Section titled “Equipment in use cannot be deleted”Deleting a logger, a sensor or a gateway that appears in a monitoring, even an ended one, and deleting a packaging still assigned to an artwork, answer 409 with a message naming what holds it. The web application already prevented it on its side; the rule now holds for every caller.
/me moves, /me/organizations is dropped
Section titled “/me moves, /me/organizations is dropped”GET /me keeps its payload: the account, its organizations and the role held in each,
all read from the token. Only the service answering it changes, from the monitoring API
to the identity service. The host and the address are the same.
One value is answered differently, and it is a correction rather than a change of
contract. The role field carries the realm-wide role, and it used to be filled with
the first role the token happened to list. Keycloak does not promise an order there, so
an account holding several could be reported as a viewer in one token and a super-admin
in the next. It now reports the highest role held, which is what every caller already
assumed. Nothing to adapt, unless an integration worked around the old behaviour.
Unchanged in the same payload: an organization the account belongs to without holding a
role there appears in organizations and not in roles.
GET /me/organizations is dropped before being built. It appeared in the StaRT API
workflow as a v1.0.0 addition for super-admin
accounts and was never implemented, in any version. It has no caller to migrate.
What it was meant to solve is real, and answered elsewhere. A super-admin belongs to no
organization, so their token lists none, and /me therefore returns an empty list for
them. It also returns a super-admin flag, and an account carrying that flag reads the
full list from GET /organizations, which already exists and is already restricted to
super-admins. One case, one endpoint, rather than a third path to the same answer.
Note for completeness: a super-admin account may also be an explicit member of an
organization, a residual situation in the directory. /me then lists that membership,
since it reports what the token says and nothing else.
Keycloak realm, development environment only
Section titled “Keycloak realm, development environment only”In place. The development environment has its own realm, smach-dev, so that test
accounts and organizations no longer live alongside production ones. The token endpoint
of the development environment is:
https://id.smach.science/realms/smach-dev/protocol/openid-connect/tokenThe client is still start. The development API accepts tokens of this realm only: a
token of realms/smach gets a 401 there. Accounts are not shared between the two realms,
so a development account is asked for separately.
Production keeps realms/smach, unchanged.
To fix in the mobile application, independently of this release
Section titled “To fix in the mobile application, independently of this release”Found while reading the application’s source code (branch dev), in
formatSensorsConfig (services/dataloggerBackground.js). Neither comes from release
0.5.0: the API sends the same values before and after it. They are listed here so they
are fixed in the same pass.
The accelerometer range falls back to 2g
Section titled “The accelerometer range falls back to 2g”The range is looked up in a table keyed ±2g, ±4g, ±8g and ±16g, and any other
value silently becomes 2g. The API writes the range without the sign (2g, 4g, 8g,
16g), which is the form of the contract and the one the web application saves. The
previous server already answered that form, and so does the new one.
As a result, a range other than 2g never reaches the device. Measured in production on 2026-10-19: of 72 monitorings, two were set up at 8g, both test transports in September 2026, and were most likely recorded at 2g. Their thresholds, written for an 8g scale, then stood for a quarter of the intended acceleration. This is deduced from the code and not read from the devices.
Fix: read both spellings, with and without ±, and refuse an unknown range rather than
fall back.
16g is encoded 0x16
Section titled “16g is encoded 0x16”The same table maps ±16g to 0x16 (22), where the frame description in the same file
gives 0x10 for 16g. Once the lookup above is fixed, a 16g range would be sent to the
device as an invalid value.
Going to production
Section titled “Going to production”Done on 2026-10-20, in production and on the development environment.
- All existing data is transferred, in production and on the development environment: artworks, monitorings, events and inventory. Nothing is sorted out nor dropped by the transfer.
- Equipment identities are aligned on what the mobile application sends. Inventory
loggers are re-keyed from hexadecimal to decimal (
12becomes18) and gateways from their label to their eight digits (GWR-001becomes01000001), the former value moving to thename. Monitorings recorded before April 2026, which named their loggers in hexadecimal, are rewritten the same way with their events. Equipment that appears in a monitoring and nowhere in the inventory is added to the inventory, marked as imported. - Every monitoring receives a new
id. Events follow their monitoring, so no history is lost. Consequence for the mobile application: a monitoring set up or started before the switch cannot be started or stopped after it, since the application holds the formerid. The switch therefore takes place at a time when no monitoring is pending or in progress, agreed beforehand. - Links to
/monitorings/<former id>saved from the web application stop working.
Open questions
Section titled “Open questions”Answers to these determine whether anything has to change in the mobile application at all:
Does the HTTP client treat any 2xx response as a success?Answered by the source code: the setup and the push compare the status to 200, which is why they keep it.- Which account does the application sign in with during a setup: administrator, super-admin, or something else?
Is the endpoint list above complete?Answered by the source code: five endpoints.Is the identity form the rule for every device?Answered by the source code: the logger is the device number, the sensor issfollowed by that number in two hexadecimal digits, the gateway is the label the device reports.Is theAnswered by the source code: yes, no format is checked.idof a monitoring kept as an opaque string?
Status
Section titled “Status”| Subject | State |
|---|---|
| Endpoints called by StaRT | read from the source code |
| 201 on creation | decided, setup and push excepted for now |
| Pagination | decided |
/count payload |
decided |
| Error format | decided, with message for now |
| Inventory role | decided |
| UUID identifiers | decided |
| Unknown equipment refused at setup | decided |
| Gateway position optional, read from the label | decided |
| Identity form: the one the mobile application sends | decided, confirmed by the source code |
| Trimmed identities | decided |
| No rename through an update | decided |
| Artwork deletion removes its history | decided |
| Equipment in use cannot be deleted | decided |
| Data transfer and production switch | done on 2026-10-20 |
| Development realm | in place, smach-dev |
| API reference | published on both environments, production since 2026-10-28 |