The version is in the path
Every endpoint lives under /api/public/v1. There is no version header and no content negotiation: the URL you called is the contract you get, which means a deployment of ours can never quietly move you to a different one.
What we may add, without warning
- New fields in a response. Your client must ignore keys it does not know.
- New optional request fields.
- New endpoints, and new optional query parameters on existing ones.
- New values of a descriptive field — a new
progress.step, a new language code, a newfailure_reason. Handle an unknown value by falling through to a default rather than throwing.
What will not change in v1
- The four statuses.
queued,processing,completed,failed— and no fifth. That is the reason they are decoupled from our internal pipeline in the first place. - The error envelope and the meaning of every code in the catalogue. Codes may be added; an existing one will not change meaning or disappear.
- Field names and types of everything documented, and the shape of the cursor pagination.
- Authentication. A key issued today keeps working on v1 for as long as v1 exists.
What a breaking change looks like
Removing or renaming a field, changing a type, changing what a status or an error code means, or making an optional request field required. None of these happen inside v1. They happen in /v2, which is a different URL that you move to when you are ready.
Deprecation and sunset
If v1 is ever retired, it is retired slowly and audibly: at least twelve months between the announcement and the switch-off, email to every account holding a key, and two standard headers on every v1 response for the whole period.
Deprecation: Sat, 01 Aug 2026 00:00:00 GMT
Sunset: Mon, 03 Aug 2026 00:00:00 GMT
Link: <https://heartotext.com/api/docs>; rel="deprecation"Log a warning when you see Deprecation on a response. It is the earliest possible notice that a migration is coming, and it arrives in your monitoring rather than in an inbox somebody has stopped reading.
Writing a tolerant client
- Ignore unknown response fields rather than failing to parse.
- Treat an unknown
status,failure_reasonorprogress.stepas “something new”, not as an error. - Branch on
error, never onmessage. - Do not parse a
cursoror anid. Both are opaque and both may change shape. - Generate your client from the OpenAPI document and regenerate it now and then: it is the same file this documentation and our own tests are built from.
