Versioning

@geopera/sdk follows Semantic Versioning, and its package version is deliberately independent of the API version carried in the /v1 path prefix — the two move on their own schedules, and you should never assume they match.

Two version numbers, two meanings

When you depend on @geopera/sdk there are two distinct version numbers in play. Conflating them is the most common source of confusion, so it is worth fixing them in your mind up front.

NumberWhere it livesCurrent valueWhat it describesCadence
Package versionpackage.json version2.1.0A release of the npm clientSemVer, moves often
API surface versionURL path prefix/v1The calling convention for every operationChanges only on a surface break

The package version describes a client release. It moves whenever the npm package changes — a runtime fix, a new typed operation flowing in from an updated contract, a typing correction, a dependency bump. You select it with npm (@geopera/[email protected], @geopera/sdk@^2.1.0, @geopera/sdk@latest).

The API surface version lives in the path prefix. Every operation is invoked as POST /v1/op/{operation_id} against https://api.geopera.com (overridable via the baseUrl client option). The SDK targets /v1; it does not pin or send a separate spec version in a header, query string, or body field — /v1 is structural, baked into the URL of every request. See Concepts and Operations.

These two numbers are decoupled on purpose. The /v1 segment is a coarse, long-lived contract marker; the package number moves much faster, advancing through many patch and minor releases while /v1 stays put, because nearly all contract changes are additive and do not break the calling convention. For the full cross-client picture — including the Python client and the CLI — see the API-wide Versioning page.

How the package uses SemVer

The package follows Semantic Versioning: MAJOR.MINOR.PATCH.

  • PATCH (2.1.x) — backward-compatible fixes with no surface change: build fixes, typing corrections, dependency bumps, runtime bug fixes. Safe to take automatically.
  • MINOR (2.x.0) — backward-compatible additions, typically new typed operations or new optional fields flowing in from an updated API contract. Existing code keeps compiling and running unchanged; the new surface is simply available.
  • MAJOR (x.0.0) — a breaking change to the package’s own public API: a renamed namespace or method, a changed input/output type, a dropped export, or adoption of a breaking contract change. Read the changelog and re-run your typecheck before upgrading.

Because operation inputs and outputs are fully typed, an upgrade that changes an operation’s body or response shows up at compile time. Run tsc --noEmit after upgrading and every affected call site surfaces immediately as a type error rather than failing at runtime:

bash
npm install @geopera/sdk@latest
npx tsc --noEmit

This is the single most useful property of the typed client during an upgrade: the type checker is your migration checklist.

What “breaking” means for the package version

A package MAJOR bump signals a change to the client surface you write against. Concretely, any of these triggers a major release:

  • A namespace or method is renamed or removed (for example client.catalog.search moving or changing shape).
  • A typed input or output model gains a required field, drops a field, or changes a field’s type in a backward-incompatible way.
  • A top-level export is renamed or removed (for example GeoperaClient, GeoperaError, callOperation, DEFAULT_BASE_URL, or an exported type such as GeoperaClientOptions or OperationId).
  • The client adopts a breaking change in the underlying API contract.

Additive changes — a new operation, a new optional input field, a new field on a response, a new enum value — are minor, not major. They cannot break code that compiled against the previous version, so they never force a major bump.

What “breaking” means for the /v1 surface

The /v1 segment is the most stable thing in the API. It changes only for a surface-incompatible break — a change to the calling convention shared by all operations, such as the request method or path shape (moving away from POST /v1/op/{id}), the authentication model (see Authentication), the error envelope (see Errors), or the shared pagination or idempotency contract (see Pagination and Idempotency).

If such a break ever ships, it arrives at a new prefix (/v2/op/...) and /v1 continues to serve existing clients in parallel. You will never have an existing /v1 request silently change shape underneath you. A future /v2 surface would ship as a new major of @geopera/sdk that targets the new prefix; until then, every release of the package keeps speaking /v1.

The two breaking definitions are independent. A package major can ship without any /v1 change (for example, renaming a method for ergonomics). And a /v1 → /v2 surface break would necessarily come with a package major, but the reverse does not hold.

Installing and upgrading

Always install the published package from npm. The package is @geopera/sdk; it is ESM-first with a CommonJS fallback and requires Node 18 or newer.

bash
npm install @geopera/sdk
# or: pnpm add @geopera/sdk
# or: yarn add @geopera/sdk

Upgrade to the latest release and re-run your typecheck:

bash
npm install @geopera/sdk@latest
npx tsc --noEmit

Pin an exact version when you want fully reproducible installs (your lockfile already does this; an exact spec in package.json makes it explicit):

bash
npm install @geopera/[email protected]

Choosing a version range

Pin the package the way you pin any dependency: allow minors and patches, cap the major, and upgrade across a major deliberately after reading the changelog.

bash
# Allow 2.1.0 up to (but not including) 3.0.0 — recommended
npm install @geopera/sdk@^2.1.0

The caret range ^2.1.0 resolves to the newest 2.x.y and refuses 3.0.0, so you automatically receive new operations and fixes while staying behind any breaking major. If you need tighter control during a freeze, a tilde range pins to patch level:

bash
# Allow only 2.1.x patches
npm install @geopera/sdk@~2.1.0

Expressed directly in package.json:

json
{
	"dependencies": {
		"@geopera/sdk": "^2.1.0"
	}
}

Reading the version at runtime

The version you actually resolved is recorded in your lockfile and queryable from the toolchain. Use these rather than hard-coding a number in your application:

bash
# The version installed in this project
npm ls @geopera/sdk

# The latest version published to npm
npm view @geopera/sdk version

# Every published version, to see the release history
npm view @geopera/sdk versions

If you need the version inside a Node program (for example to include it in a support log), read it from the package’s own manifest rather than maintaining a separate constant:

typescript
import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);
const { version } = require('@geopera/sdk/package.json');

console.log(`@geopera/sdk ${version}`); // -> @geopera/sdk 2.1.0

Worked example: a new operation flows through

Suppose the API gains a new operation. Here is how each version number responds, so you can see why the package version moves but /v1 does not.

  1. /v1 surface — unchanged. The new operation is invoked at POST /v1/op/... exactly like every existing one. Adding an operation is additive.
  2. @geopera/sdk — released as a minor bump (for example 2.1.0 → 2.2.0). The new operation appears as a typed namespace method; existing code is untouched.
  3. Your code — keeps compiling and running. To use the new operation you bump the dependency within your ^2.x range; you never change baseUrl or the path prefix.
typescript
import { GeoperaClient } from '@geopera/sdk';

const client = new GeoperaClient({ token: 'gpra_...' });

// Existing call — identical before and after the upgrade.
const results = await client.catalog.search({
	collections: ['sentinel-2-l2a'],
	limit: 10
});

The escape hatch behaves the same way across versions. client.invoke("catalog.search", body) dispatches to POST /v1/op/catalog.search regardless of which 2.x package you are on; a new operation just becomes a new valid OperationId literal once you upgrade.

Changelog

Release notes for each version are published with the package and in the source repository. Check the changelog before any major upgrade to see which namespaces, methods, or types changed.

Watch the package changelog rather than the API’s spec version — the changelog is where breaking-vs-additive is called out for this client specifically. For the relationship between this package, the geopera Python client, the CLI, and the /v1 surface, see the API-wide Versioning page.

Guidance

  • Build against /v1 and treat it as permanent for the life of your integration; a successor surface would ship at a new prefix and a new package major, never replace /v1 in place.
  • Pin with ^2.1.0 (minors and patches allowed, major capped), commit your lockfile, and upgrade across a major deliberately.
  • Run tsc --noEmit after every upgrade — the typed client turns contract changes into compile errors at your call sites.
  • Keep the two numbers separate in your head: the package SemVer (2.1.0) and the API surface (/v1) move independently.

See Operations and the TypeScript quickstart for usage, and Client reference for the exported surface that SemVer protects.