API Versioning Policy
Who this document is for
This document is for a developer connecting their own system to the Segmentic API. It says where the version lives, what will break your integration and what will not, how much notice you get before a breaking change, and how your code should be written so that our ordinary changes do not take it down.
This is the English rendering. The Persian version is the authoritative one and governs if the two are ever read differently.
Everything written here is how things are today. Where we have not built something we say so, and say what is used instead. A policy describing machinery that does not exist is worse than no policy, because your integration then waits for a signal that never comes.
--- Note: every call to this API is answered on infrastructure inside Iran, and the data you send with it does not leave the country.
Article 1The version is a path segment
The public API version is one segment of the path and today it is `v1`, for example `/api/v1/events`.
We hold the version nowhere else. A version header and a custom `Accept` are not read, a version query parameter is not read, and there is no date-based revisioning. If you send the version anywhere but the path it is silently ignored.
The reason for that choice is simple: a path segment is visible in a log, in an error report and in a proxy configuration, whereas a header is not, and it gets lost along the way.
--- Note: only one version has been published to date. There is no `v2` and no date has been announced for one.
Article 2When the version changes
Our house rule is one sentence: the version changes only when the shape of a response changes in a way an existing integration would notice.
So the test is not how large the change is on our side. The test is whether code that worked yesterday still works today. A complete rewrite of an internal component does not change the version if the response keeps its shape. Removing one small key does.
Article 3What counts as breaking
These are breaking and are not done without the version changing:
- Removing a key from a response
- Changing the type of a key, for instance from a string to a number or from a
scalar to an object
- Removing an endpoint or changing its path
- Making a field required that was optional yesterday
- Narrowing the accepted values of an input
- Changing the meaning of a key while its name and type stay put
- Changing a parameter's default value in a way that changes the output
- Changing the status code returned for a case that already existed
The most dangerous item on that list is the sixth. Removing a key fails loudly and you find out the same day. Changing the meaning of a key fails silently and may surface in your reporting weeks later. That is why we treat it as equal to a removal.
Article 4What does not count as breaking
These are done at any time, without prior notice and without the version changing:
- Adding a new key to a response
- Adding a new optional field to an input
- Adding a new endpoint
- Adding a new value to the list of allowed values for a field
- Adding a new response header
- Changing the order of keys in a JSON object
- Fixing a defect that brings a response into line with the documentation
- Changing response times and internal implementation detail
Two of those routinely surprise integrations: a new value in an enumerated field, and a new key in a response. We count both as non-breaking, so your code has to tolerate both. The clause on unknown fields below says the same thing.
Article 5A new key beside the old one
When we want to return a fuller answer, we put the fuller answer under a new key beside the old one and leave the shape of the old key alone.
An example: suppose `count` is a number and later it becomes necessary to return a breakdown of that number. What we do not do is turn `count` into an object. What we do is add `count_breakdown` next to it. `count` stays the same number, with the same meaning.
Most of the pressure that looks like "we need a new version" is really "we need to return more", and more fits beside the old. The long life of `v1` is the result of that one rule.
We do not hide what the rule costs. Responses grow larger and busier over time and several keys in them are relics. We have accepted that against breaking a customer's integration.
Article 6The capabilities endpoint
There is a capabilities endpoint that says what this installation supports today: which channels are active, which features are on and which limits apply.
It is our only forward-compatibility mechanism. Rather than hard-coding the list of features in your own code, ask this endpoint for it. A feature added later appears in this response without the version changing, and your integration sees it without a code change.
Two things about it:
- Read it at start-up and hold it for a while. Reading it before every call is needless load.
- It declares capability, not data shape. It is not version negotiation and it does not change the shape of any other endpoint's response.
Article 7Ignore unknown fields
Your integration must ignore an unknown key in a response rather than erroring on it. Because adding a key is not breaking as far as we are concerned, it is done without prior notice. If your JSON parser is strict, a harmless change on our side becomes an outage on yours.
Specifically:
- In Go, do not turn on `DisallowUnknownFields`
- In Java with Jackson, leave `FAIL_ON_UNKNOWN_PROPERTIES` off
- In any other language, keep strict response schema validation off the main path
Three further habits make an integration brittle in ways we cannot compensate for from our side:
- Relying on the order of keys in JSON
- Relying on a key being absent, rather than checking its value
- Reading a date by slicing the string, rather than parsing it properly
--- Note: for enumerated fields an unknown value must go to the default branch. If a new state is added and your code only knows today's states, it must pass over it safely rather than fall over.
Article 8Notice before a breaking change
Every breaking change is announced at least six months before it takes effect.
The announcement goes out two ways: the changelog page in the documentation, and an email to the technical contact of every account that called that endpoint during the period. So if you do not use a part of the API, you do not get an email about it.
--- Note: fixing a security vulnerability may shorten this notice. In that case the reason and the scope of the change are written into the announcement.
Article 9How long an old version lives
After a new version is released, the previous one stays alive and answers calls for at least a year.
During that window the old version receives defect fixes and security corrections only, and no new capability is added to it. New capability arrives only on the current version, and that in itself is the reason to migrate.
After that window, a call to a retired version's path is refused with a `410`. It is deliberately not redirected to the new version, because silently steering an old call to a response with a new shape is worse than an error. You see an error the moment it happens; you may never see malformed data.
Article 10We do not send sunset headers today
Today we send no machine-readable deprecation headers. No `Sunset` header, no `Deprecation` header, and no `Warning` on the response of an endpoint being deprecated.
In their place are the two things said above: the documentation changelog, and an email to the account's technical contact. Beyond those two there is no other signal.
We write this down plainly because the opposite assumption is expensive. If somebody writes code believing the system sends a machine-readable warning before anything is switched off, that warning never arrives and their monitoring never fires.
If those headers are added one day, that is itself an additive change, it is done without the version changing, and this document is updated.
Article 11Changes to this document
Changes to this document are announced at least 60 days before they take effect. Previous versions are archived, so that it is possible to see what our commitment was on the day an integration was written.
--- Note: this document is a public operational commitment and does not take the place of the services contract. Where anything in it conflicts with a signed contract, the contract governs.
Contact
Technical questions about this document: support@segmentic.net
Kargostaran Nasl Javan Bakhtar https://segmentic.net