Published: September 8, 2026 · Last updated: September 8, 2026 · Author: Softix
API versioning for SaaS is not a bike-shed about /v1/ versus headers. For US SMB founders and product/ops leaders, it is an operating promise: how clients discover change, how long old behavior remains available, and how you retire paths without surprise outages.
Softix’s default for teams under roughly fifty engineers is Path–Pin–Sunset: start with a clear URI path (/v1/) for debuggability; adopt date or header pinning when the API is the product and breaking changes are frequent; publish a twelve-month deprecation policy; and signal retirement with Sunset/Deprecation headers when paths go dark.
This brief sits beside Softix’s REST vs GraphQL product-engineering scorecard, modular monolith Bound–Enforce–Extract, feature-flag release discipline, and multi-tenant Postgres Pool–Policy–Escape. API style, deployable shape, release control, and tenancy are related decisions. Versioning and deprecation are a different operating model—the one that keeps partners and mobile clients alive while you evolve the product.
Softix did not build Stripe’s or Shopify’s platforms. Softix cites public vendor documentation and IETF RFCs as teaching references for SMB SaaS teams designing their own contracts.
Why “just don’t break anything” fails
Additive-only APIs sound virtuous until reality arrives: a field that meant “optional” becomes required for fraud checks; a list endpoint that returned ten items grows into thousands; a webhook payload that assumed one currency must support more. If you never version and never deprecate, you either freeze the product or break silent integrators.
OpenAPI helps you describe and test the surface; it does not choose your compatibility policy. Softix treats OpenAPI as the contract artifact inside Path–Pin–Sunset—not a deprecation calendar. Feature flags can stage behavior (Softix feature-flag guide), but partners cannot pin to an internal flag the way they pin /v1/invoices or a dated version.
Path — Make the version visible where humans debug
Path means URI versioning: https://api.example.com/v1/customers. Softix recommends this as the starting default for most SMB SaaS products under ~50 engineers.
Why path first:
- Debuggability. Support and engineering can see the version in access logs, screenshots, and
curlpastes without hunting headers. - Gateway simplicity. Rate limits, WAF rules, and CDN caches can key on a path prefix.
- Mental model. Partners understand “we are on v1; v2 is a migration project.”
- Honest cost. Path versions encourage fewer, larger compatibility windows—which is usually what a small team can staff.
Path rules Softix uses with clients:
- Prefer additive changes inside
/v1/(new optional fields, new endpoints). - Treat renames, type changes, authz tightening that rejects previously accepted calls, and removed fields as breaking—they need a new path major (
/v2/) or a Pin strategy (below), plus a migration window. - Document the default: “unversioned URLs are not supported” so you never inherit three accidental versions.
- Keep
/v1/as one coherent surface; do not invent/v1.1/every sprint.
Path is not sacred forever. It is the clearest on-ramp while the API is still mostly an extension of your product UI—not yet a standalone platform with weekly breaking churn.
Pin — Date/header versions when the API is the product
Pin means clients (or SDKs) select a specific compatibility snapshot—often via a request header—so the server can evolve defaults without mass-breaking every integrator on the same day.
Stripe’s public API versioning is a well-documented example (Softix reads the docs; Softix did not build Stripe). Per Stripe’s versioning documentation, major releases can include non-backward-compatible changes; monthly releases within a major stay backward-compatible. As of Softix’s 8 Sep 2026 review, the current version is illustrated as 2026-08-26.dahlia. Clients can override the account default with the Stripe-Version header; the account default lives in Workbench. Webhook endpoints can pin an API version at creation so payloads stay stable across later account upgrades.
Stripe’s upgrades guide lists additive changes (new resources, optional parameters, response properties) as backward-compatible, and describes testing with Stripe-Version before a Workbench account upgrade—with a limited rollback window afterward.
When Softix recommends Pin for SMB SaaS:
- The API is the product (partners, ISVs, or many external automations depend on it).
- Breaking changes are frequent enough that a new
/v2/every quarter would exhaust your migration staffing. - You can ship SDKs or generated clients that pin a version, and you can test webhooks against pinned versions.
- You will invest in a changelog, compatibility tests, and Workbench-like “default version” controls—not just a header name.
Softix caution: Header/date pinning without product discipline becomes invisible fragmentation—ten live compatibility modes, none owned. Pin only when you will measure which versions are still in use and fund their retirement.
Sunset — Retire with a published policy and HTTP signals
Sunset is the operating close of the loop: announce, measure, help migrate, then turn the old surface off.
Publish a twelve-month deprecation policy (Softix default for SMB B2B SaaS unless contracts require longer):
- Announce the deprecation date and replacement path/version in docs and email/status channels partners actually read.
- Instrument usage of the deprecated path or version (request counts by customer, not vanity totals).
- Assist top consumers with migration notes, dual-write periods if needed, and SDK bumps.
- Enforce after the window: return clear errors, not silent wrong behavior.
Use HTTP signals when retiring paths or resources. RFC 8594 defines the Sunset response header field: an HTTP-date hint that a URI is expected to become unresponsive at a future time (example form: Sunset: Sat, 31 Dec 2027 23:59:59 GMT). The RFC treats Sunset as a hint, not a hard guarantee, and notes that for APIs, Sunset is appropriate for the decommission stage—when a version will become unresponsive—not merely for “no longer preferred.” Pair Sunset with your own Deprecation documentation and, where useful, a Link with rel="sunset" pointing at migration policy (as RFC 8594’s sunset link relation allows). Softix also recommends a human-readable deprecation banner in docs and changelog entries dated in the customer timezone you support.
Sunset without measurement is theater. Softix expects dashboards: which customers still hit /v1/legacy-thing this week, and who owns the outreach list.
Comparison: Path vs Header/Date vs Query
| Dimension | URI path (/v1/...) |
Header / date pin (e.g. Stripe-Version) |
Query (?version=1) |
|---|---|---|---|
| Visibility in logs & support | Excellent | Good if you log the header | Mediocre; easy to omit |
| CDN / gateway rules | Straightforward prefix rules | Need header-aware routing | Cache-key pollution risk |
| Client ergonomics | Obvious in every URL | Requires SDK or disciplined clients | Easy to forget; looks optional |
| Fine-grained evolution | Coarse majors | Strong (many dated snapshots) | Weak governance signal |
| Webhook alignment | Path per webhook API | Explicit endpoint version (Stripe pattern) | Awkward |
| Softix default for <~50 eng | Start here | Adopt when API-is-product + frequent breaks | Avoid as primary strategy |
| Main failure mode | Too many majors too fast | Too many live pins forever | Silent clients on wrong default |
Query parameters are the weakest primary strategy: they look optional, fragment caches, and train clients to ignore compatibility. Softix does not recommend query versioning as the system of record.
Softix Path–Pin–Sunset decision framework
Use this in order:
- Path if you are early, the API mostly serves your first-party apps plus a handful of partners, and you can keep
/v1/additive for a year. - Add Pin when external clients multiply, breaking changes become monthly, and you can staff a changelog + usage metrics + SDK pins (learn from Stripe’s public model; do not cargo-cult every detail).
- Sunset on a calendar: twelve months default, shorter only for security/compliance breaks with explicit customer communication.
- Keep OpenAPI (or equivalent) as the source of truth for each live version; generate consumer tests for top partners.
- Align release flags with internal rollout; never make a flag the partner’s version contract (feature flags).
A modular monolith can still expose a clean versioned HTTP edge—splitting services does not invent a deprecation policy.
Implementation checklist (SMB SaaS)
- [ ] Choose Path
/v1/as the public default unless Pin criteria are already met. - [ ] Write the compatibility rules (what is additive vs breaking) in one page partners can find.
- [ ] Store OpenAPI (or GraphQL schema, if that is your public contract) per live version in git; fail CI on accidental breaking diffs.
- [ ] Log version identifier on every request (path major and/or pin header).
- [ ] Publish a 12-month deprecation policy with owners and escalation.
- [ ] Emit
Sunset(RFC 8594) and clear Deprecation messaging when a path/version has a retirement date. - [ ] Build a usage report of deprecated surface area by customer.
- [ ] Version webhooks independently when payloads can break consumers (pin at endpoint creation, Stripe-style).
- [ ] Provide migration guides before the Sunset date, not on the day of cutover.
- [ ] After retirement, return 410/404 with a stable error body—not a subtly different 200.
Risks and honest limits
- Path inflation: Shipping
/v3/because naming was lazy creates permanent tax. Prefer additive/v1/longer than your ego wants. - Pin sprawl: Supporting every dated snapshot forever is a hidden platform team. Cap supported pins; publish the support window.
- Security exceptions: Authz holes and data-exposure fixes may need accelerated Sunset; say so in the policy.
- Multi-tenant footguns: Versioning does not replace tenant isolation (Postgres Pool–Policy–Escape).
- No fake maturity: Citing Stripe’s headers does not mean your three-person team can run Stripe’s upgrade machinery next week. Steal the ideas (pin, changelog, Workbench-like default, webhook version), size the ops to your headcount.
FAQ
What is the best API versioning strategy for SaaS startups?
Softix’s default is Path–Pin–Sunset: start with URI /v1/ for clarity, move to header/date pinning when the API is the product and breaks are frequent, and always retire with a published policy plus Sunset signals.
Is URI versioning outdated compared to Stripe-style headers?
No. URI versioning remains the most debuggable default for small teams. Stripe’s dated versions and Stripe-Version header (docs) fit a high-churn, API-as-product surface with strong SDK and Workbench support—not every SMB’s first public API.
How long should an API deprecation window be?
Softix’s default recommendation for SMB B2B SaaS is twelve months, unless contracts, regulated change windows, or security incidents require a different timeline. Measure usage; do not rely on the calendar alone.
What is the Sunset header (RFC 8594)?
RFC 8594 defines an HTTP response header that advertises when a URI is expected to become unresponsive, using an HTTP-date. It is a hint for clients and intermediaries, appropriate when an API version is headed toward decommission—not merely “discouraged.” See RFC 8594.
Should we put the version in the query string?
Softix advises against query-string versioning as the primary strategy. Prefer path majors or header/date pins so caches, gateways, and support tooling stay honest.
How does this relate to REST vs GraphQL?
Versioning is orthogonal to protocol style. Softix’s REST vs GraphQL brief covers style; this post covers the compatibility operating model either style still needs.
A practical next step
If your SaaS API is about to meet partners, mobile clients, or automations, Softix can help you turn Path–Pin–Sunset into a concrete contract, OpenAPI workflow, and deprecation calendar sized for a small engineering team. Explore custom software development or let’s talk when you want a scoped, platform-neutral review—without pretending Softix ran Stripe’s upgrade train.
Share


