Authentication

Every request to the Geopera API carries a Bearer token in the Authorization header:

Authorization: Bearer <token>

There are two ways to get one — an OAuth2 / OIDC flow for human users and service clients, and an API key for machine-to-machine integrations. Both resolve to a principal with a set of scopes, and every operation checks the scope it needs before running.

OAuth2 / OIDC token endpoint

The platform exposes a standards-compliant OpenID Connect token endpoint, so most OAuth2 client libraries and existing geospatial tooling work without modification:

POST https://api.geopera.com/realms/public/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

Tokens are short-lived JWTs (5 minutes), with a longer-lived refresh token (30 minutes). The discovery document, JWKS, userinfo, introspect, revoke, and logout endpoints live under the same /realms/public/protocol/openid-connect/ base.

Grant: password

Exchange a user’s credentials for a token:

bash
curl -X POST https://api.geopera.com/realms/public/protocol/openid-connect/token \
  -d grant_type=password \
  -d username='[email protected]' \
  -d password='••••••••'

Grant: client_credentials (machine-to-machine)

Exchange an API key (as the client secret) for a token — the right flow for backend services and automation:

bash
curl -X POST https://api.geopera.com/realms/public/protocol/openid-connect/token \
  -d grant_type=client_credentials \
  -d client_id=geopera \
  -d client_secret='<your-api-key>'

Grant: refresh_token

Exchange a refresh token for a fresh access token without re-sending credentials:

bash
curl -X POST https://api.geopera.com/realms/public/protocol/openid-connect/token \
  -d grant_type=refresh_token \
  -d refresh_token='<refresh-token>'

Token response

json
{
  "access_token": "eyJhbGciOiJIUzI1Ni
...",
  "token_type": "Bearer",
  "expires_in": 300,
  "refresh_token": "...",
  "refresh_expires_in": 1800,
  "scope": "..."
}

API keys

API keys are issued per organization and are ideal for integrations that act on behalf of the organization rather than a single user. An organization administrator creates a key with the api_keys.create operation; the key is shown once at creation time — store it securely.

A key can be presented two ways:

  • As the client_secret in the client_credentials grant above (recommended — you get a short-lived JWT back), or
  • Directly as a Bearer token / X-API-Key header for SDK and tooling conventions.

Each key carries a permission set (read / write / process) that maps to the scopes its requests are allowed to use. Keys can be revoked at any time with api_keys.revoke.

Scopes

Authorization is expressed in a single currency: resource:action scopes. Each operation declares the one scope it requires, and the check runs identically no matter how the operation is invoked. Examples:

ScopeGrants
catalog:readSearch the imagery catalog
orders:read / orders:writeView / place and manage orders
items:read / items:writeRead / create, update, delete STAC items & assets
processing:processCreate and dispatch processing jobs
billing:read / billing:writeView balance & history / top up, manage payment methods
uploads:writeUpload bring-your-own data
shares:writeCreate and revoke share links

A wildcard form is honoured where appropriate: items:* grants every action on items, and *:read grants the read action across resources. The Operations Reference lists the exact scope each operation requires.

Scope is the coarse gate. Within an operation, fine-grained ownership is still enforced — e.g. you can only read items in projects your organization is a member of, regardless of holding items:read.

Principals

Every authenticated request resolves to a principal of one kind. The kind determines how scopes are derived:

KindUsed byAuthority
humanA logged-in user (OIDC password grant)The self-serve scope set for the user’s organization
api_keyAn organization API keyThe key’s read / write / process permissions
serviceInternal/system callersFull trust (not customer-facing)
workerProcessing workersA narrow, job-bound scope — register their own job’s outputs and nothing else

All actions are attributed to a principal, and every write is recorded with its principal for audit and provenance.

Errors

  • 401 Unauthenticated — missing or invalid token.
  • 403 Forbidden — authenticated, but the principal lacks the operation’s scope.

Both are returned as application/problem+json.