# API versioning & deprecation policy

Apogee's public API is versioned at the URL path level. Every current
endpoint lives under `/v1/`.

## Contract

1. **Every breaking change ships on a new major version.** We will
   never alter the shape of a `/v1/` response in a way that breaks
   an existing client.

2. **Non-breaking additions** can happen on `/v1/` at any time:
   - New optional request fields
   - New response fields (existing fields stay unchanged)
   - New endpoints
   - New error codes (must be opt-in — i.e. only fire for new input
     your client hasn't sent before)
   - Loosening validation (accepting values we previously rejected)

3. **Breaking changes** ship on `/v2/` with the following guarantees:
   - `/v1/` and `/v2/` run side by side for a **minimum of 180 days**
   - Deprecation announcement is emailed to every merchant 30 days
     before the new version goes live
   - Removal of `/v1/` is announced again 30 days before cutoff
   - A migration guide is published at `docs/MIGRATE-v1-to-v2.md`
     covering every changed field

4. **Removal of an endpoint** is always a breaking change even if the
   replacement is a simple rename. It gets the full 180-day window.

## What counts as "breaking"?

| Change | Breaking? |
|---|---|
| Removing a response field | ✅ |
| Renaming a response field | ✅ |
| Changing a field's type (e.g. `integer → string`) | ✅ |
| Changing the meaning of an existing field | ✅ |
| Adding a new required request field | ✅ |
| Removing an endpoint | ✅ |
| Changing URL path (e.g. `/v1/sessions` → `/v1/gameSessions`) | ✅ |
| Changing authentication scheme | ✅ |
| Tightening rate limits below current levels | ✅ |
| Tightening validation (rejecting values we used to accept) | 🟡 usually breaking, but case-by-case |
| Adding a new optional request field | ❌ |
| Adding a new response field | ❌ |
| Adding a new endpoint | ❌ |
| Adding a new error code the client doesn't encounter yet | ❌ |
| Loosening validation | ❌ |
| Loosening rate limits (larger burst) | ❌ |
| Performance optimisations | ❌ |
| Security patches to the signature algorithm | 🟡 we'll announce but may not wait 180 days for critical vulns |

## Current versions

| Version | Status | Sunset date |
|---|---|---|
| **v1** | Current | — |
| v2 | Not planned | — |

## Version header (optional)

Every response carries `X-Apogee-API-Version: 1` so your client
libraries can assert they're talking to the version they expect:

```
HTTP/1.1 200 OK
Content-Type: application/json
X-Apogee-API-Version: 1
X-Apogee-Env: production
X-Cloud-Trace-Context: req_...
```

You can pin your client to a version by adding
`Accept-Version: 1` to your requests. We'll return `406 Not Acceptable`
if we can't satisfy it. As of v1 this is equivalent to the URL path
version.

## Deprecation signalling

When we deprecate an endpoint, the response carries:

```
X-Apogee-Deprecation: This endpoint will be removed 2027-01-01. See docs/MIGRATE-v1-to-v2.md.
Deprecation: Sun, 01 Jan 2027 00:00:00 GMT
Sunset: Sun, 01 Jul 2027 00:00:00 GMT
Link: <https://apogeetech.net/docs/MIGRATE-v1-to-v2.md>; rel="deprecation"
```

Clients should log these headers and alert ops when a 30-day sunset
window is detected. Apogee emails the primary contact on file for
every merchant hitting a deprecated endpoint at sunset-30d and
sunset-7d.

## Changelog

We publish a complete changelog at
`https://apogeetech.net/docs/CHANGELOG.md` (planned — for now the
source of truth is `git log` on this repo). Every semver-significant
release gets an entry with:

- Added (new endpoints, fields)
- Changed (non-breaking modifications)
- Deprecated (marked for removal but still working)
- Removed (gone — only happens on major version bumps)
- Fixed (bug fixes)
- Security (patches, never with reproduction details)

## Client SDK policy

Apogee doesn't ship official client SDKs yet. We ship an
[OpenAPI 3.1 spec](./openapi.yaml) that you can feed into
`openapi-generator-cli` to generate clients in any language:

```bash
# Node.js / TypeScript client
npx openapi-typescript-codegen --input docs/openapi.yaml --output ./src/apogee-client

# Python client
openapi-generator-cli generate -i docs/openapi.yaml -g python -o ./apogee_client
```

When we do ship SDKs, each one will be versioned independently and
support the full contract of whatever API version it was generated
against. SDK deprecation follows the API's 180-day window.

## Questions

Email `api@apogeetech.net`. Breaking change proposals get posted to
the operator slack `#apogee-api-changes` at least 14 days before any
decision.
