API versioning and deprecation policy
How we change the API without breaking your code
The OpenSense API surface is small but it is the contract you write your devices and integrations against. We commit to a deprecation policy that is more conservative than what a startup typically does.
Semantic versioning
The API is versioned in the URL path:
/v1/...— the current stable surface./v2/...— a future major version, when we ship one.
Changes inside v1:
- Additive only. New endpoints, new optional fields on existing endpoints, new enum values whose absence preserves old behaviour.
- Never rename a field, change a type, or remove a value from an
enum. Such changes go to
/v2.
Changes that bump to /v2:
- Removal of a field.
- Type change of a field.
- Different meaning of an enum value.
- Different request semantics (e.g. a previously synchronous endpoint becomes asynchronous).
Deprecation window
When a feature is deprecated:
- It continues to work for 12 months from the announcement date.
- The HTTP response includes a
Deprecationheader with the sunset date, per RFC 8594. - An email is sent to all account holders who have used the deprecated feature in the last 90 days. The email includes the migration path.
- The changelog records the deprecation as a discrete entry.
After 12 months the feature is removed; calls return 410 Gone with
a body explaining the replacement.
What is not covered by the policy
- Internal data formats — the shape of the
_payload.jsonfiles served by the dashboard, the shape of the audit-log entries we store internally, the cookie names — are not part of the public API and can change at any time. The customer-visible features they back (the dashboard chart, the audit-log export) honour the same policy as everything else. - Rate limits can be raised at any time. Lowering them requires a 30-day notice in the same channel as deprecations.
- New error codes can appear at any time. Removing an error code
is treated as a v2-level change. (You should branch on
codedefensively — see the error codes table.) - New required fields in optional features. We can require a new field in a freshly-added feature; we cannot require a new field in an existing one without a v2 bump.
What you should write to make this easy
- Branch on
code, not onmessage. Messages are human; codes are machine. - Tolerate unknown enum values. If we add
severity: "info"next year, your client should not crash on it. - Ignore unknown JSON fields. Standard advice; we add fields routinely.
- Send
User-Agent. When we email about deprecations we filter by User-Agent prefix to scope the audience. If your User-Agent is generic Pythonrequests, you may not get the notice.
v1 and the foreseeable future
We have no plan to ship /v2 before 2028. The data model is stable
and we have not yet found a v1-design decision worth a forced
migration. We will ship /v2 when one of the following is true:
- A regulatory change requires a payload schema change that cannot be additive.
- A storage migration forces a measurement-format change.
- We adopt a third-party standard (e.g. OCF or a similar IoT framework) that supersedes our hand-rolled schema.
Until then, treat /v1 as forever.