API keys
Create, list, and inspect Topolab API keys. Keys carry permission-and-resource grants; the secret is shown once at creation, capture it then.
API keys
Manage the API keys that authenticate machine and data access. These management endpoints use a Bearer JWT (the signed-in user), while the keys themselves are sent as X-API-Key on data requests. See Authentication.
You cannot mint an API key with an API key. Key management is a portal-session operation, so every request on this page is authenticated with a Authorization: Bearer <session JWT>, never with X-API-Key.
Key model
- Format:
tlb_{env}_{32 chars}, for exampletlb_prod_3f9a2c7e8b1d4056a1c2e3f4a5b6c7d8. - Secret: shown once in the create response. It is not retrievable afterward.
- Grants: a key carries one or more grants, each a permission on a resource (see below). A data call is allowed only when the key holds the grant that call requires.
Personal keys belong to you within an organization.
Permissions and resources
Each grant pairs a permission with the resource it applies to.
| Permission | Grants |
|---|---|
READ |
Read/download that resource. |
WRITE |
Create or modify that resource. |
ADMIN |
Full control of that resource. |
| Resource | Covers |
|---|---|
DATASET |
Dataset file downloads. |
COORDINATES |
Coordinate extraction and OGC features. |
DATA |
The PostGIS SQL proxy. |
ARCHIVES |
Archive (historical month) downloads. |
BILLING |
Credits, usage, and invoices. |
USERS, ORDERS, SUBSCRIPTIONS, ACTIVITY, ORGANIZATION, PLATFORM, SYSTEM |
Account, commerce, and platform resources. |
So a dataset download needs READ + DATASET, OGC features need READ + COORDINATES (plus the organization's GIS access), and the SQL proxy needs READ + DATA. Grant only what a workload needs.
Create a key
There are two kinds of key. A personal key is scoped to your own organization; an organization key is owned by the organization as a whole.
Personal key
POST /v1/api-keys/personal
curl -X POST \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json" \
-d '{
"name": "etl-nightly",
"permissions": [{ "permission": "READ", "resource": "DATASET" }],
"expiresAt": "2026-12-31T23:59:59Z"
}' \
"https://api.topolab.nl/v1/api-keys/personal"
The response includes the full secret. This is the only time it is returned, store it now.
{
"id": "key_9a2c7e8b",
"name": "etl-nightly",
"permissions": [
{ "permission": "READ", "resource": "DATASET" }
],
"secret": "tlb_prod_3f9a2c7e8b1d4056a1c2e3f4a5b6c7d8",
"expiresAt": "2026-12-31T23:59:59Z",
"createdAt": "2026-05-01T09:14:00Z"
}
| Field | Description |
|---|---|
id |
Key identifier, used in the per-key endpoints below. |
secret |
The full tlb_... key. Shown once. Send it as X-API-Key. |
permissions |
The permission-and-resource grants the key carries. |
expiresAt |
Optional expiry; omit for a non-expiring key. |
Organization key
POST /v1/api-keys/organization/:organizationId
Creates a key owned by the organization rather than by you. The request body is the same as a personal key. Resolve organizationId from Organization.
curl -X POST \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json" \
-d '{
"name": "shared-ingest",
"permissions": [{ "permission": "READ", "resource": "DATASET" }]
}' \
"https://api.topolab.nl/v1/api-keys/organization/org_8f3a2c7e"
As with a personal key, the response carries the secret once, capture it then.
List keys
GET /v1/api-keys/my-keys
Your personal keys.
curl -H "Authorization: Bearer eyJhbGci..." \
"https://api.topolab.nl/v1/api-keys/my-keys"
{
"data": [
{
"id": "key_9a2c7e8b",
"name": "etl-nightly",
"prefix": "tlb_prod_3f9a2c7e",
"permissions": [
{ "permission": "READ", "resource": "DATASET" }
],
"expiresAt": "2026-12-31T23:59:59Z",
"createdAt": "2026-05-01T09:14:00Z"
}
]
}
The secret is never returned by any list endpoint, only the prefix is shown for identification.
GET /v1/api-keys/organization/:organizationId
The keys owned by an organization.
GET /v1/api-keys/accessible?includeExpired=&scope=
Every key you can see, personal and organization, in one response.
| Parameter | Type | Description |
|---|---|---|
includeExpired |
boolean | Include expired keys. Defaults to excluding them. |
scope |
string | Narrow to a scope, for example personal or organization. |
Get a key
GET /v1/api-keys/:id
Returns a single key's metadata (never its secret).
curl -H "Authorization: Bearer eyJhbGci..." \
"https://api.topolab.nl/v1/api-keys/key_9a2c7e8b"
Update a key
PATCH /v1/api-keys/:id
Change a key's label, its permission-and-resource grants, or its expiry. Send only the fields you want to change.
curl -X PATCH \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json" \
-d '{
"name": "etl-nightly-readonly",
"permissions": [{ "permission": "READ", "resource": "DATASET" }],
"expiresAt": "2027-06-30T23:59:59Z"
}' \
"https://api.topolab.nl/v1/api-keys/key_9a2c7e8b"
Updating grants does not change the secret. To replace the secret, rotate the key.
Rotate a key
POST /v1/api-keys/:id/rotate
Mints a new secret and immediately revokes the old one. The old value stops working the moment this returns. The response carries the new secret, shown once, so update your callers before the previous value is retired.
curl -X POST \
-H "Authorization: Bearer eyJhbGci..." \
"https://api.topolab.nl/v1/api-keys/key_9a2c7e8b/rotate"
{
"id": "key_9a2c7e8b",
"name": "etl-nightly",
"secret": "tlb_prod_a1b2c3d4e5f60718293a4b5c6d7e8f90",
"expiresAt": "2026-12-31T23:59:59Z"
}
Revoke a key
POST /v1/api-keys/:id/revoke
Disables the key so it can no longer authenticate, while keeping the record for audit. This cannot be undone, rotate instead if you only need a fresh secret.
curl -X POST \
-H "Authorization: Bearer eyJhbGci..." \
"https://api.topolab.nl/v1/api-keys/key_9a2c7e8b/revoke"
Delete a key
DELETE /v1/api-keys/:id
Permanently removes the key and its record.
curl -X DELETE \
-H "Authorization: Bearer eyJhbGci..." \
"https://api.topolab.nl/v1/api-keys/key_9a2c7e8b"
Per-key usage
GET /v1/api-keys/:id/usage?startDate=&endDate=
Returns the calls and credits attributed to one key over an ISO 8601 date range. Use the id from the create or list response.
curl -H "Authorization: Bearer eyJhbGci..." \
"https://api.topolab.nl/v1/api-keys/key_9a2c7e8b/usage?startDate=2026-05-01&endDate=2026-05-31"
For organization-wide reporting see Usage stats.
Errors
| Status | Meaning |
|---|---|
401 |
Missing or invalid Bearer token (or you tried to authenticate with X-API-Key). |
403 |
You lack the permission required to manage keys. |
404 |
The key does not exist. |
429 |
Rate limited, see Rate limits & credits. |
Good practice
- Capture the secret at creation or rotation; it is shown once and cannot be retrieved later.
- Grant only the permission-and-resource pairs a workload needs.
- Set an
expiresAtfor keys that should not live forever. - Rotate to replace a secret with zero-downtime cutover; revoke when a key should stop working but its history must stay.
- Manage keys from a portal session, not with an API key.
- Need more keys or higher limits? Contact us.