Scopes and tenancy
Scopes
A scope is <resource>.<verb> where verb is read, write or delete:
operations.read workforce.write safety.delete
write covers create and update. delete is separate because it is
destructive.
write does not imply read
This is intentional and worth designing around. A key scoped operations.write can
submit production logs but cannot read the dataset back. For an ingestion
integration that is exactly right: a leaked write-only credential cannot be used to
exfiltrate your operational history.
Grant both explicitly when a workload genuinely needs both.
Wildcards
operations.* grants every verb on that resource. There is no tenant-facing global
wildcard — a key that silently acquires every future scope defeats the point of
scoping.
Discovering scopes
Always read the registry rather than hardcoding:
const groups = await client.developer.listScopes();
Each entry carries a label, description, group and whether it is recommended for a first key. The portal's scope picker renders from this same endpoint, so the two can never disagree.
Tenancy
Your API key carries its tenant. There is no tenant header, and no way to address another tenant's data — every query is scoped server-side before it runs.
A resource belonging to another tenant returns 404, not 403. That is deliberate:
403 would confirm the record exists to someone not entitled to know it does.
Platform scopes
platform.* scopes cover cross-tenant administration and can only be held by a
platform-scoped key, which only a MineTech super-admin can issue. Those endpoints
appear in this reference for completeness, but an ordinary tenant key cannot reach
them regardless of what scopes it is granted.
Least privilege in practice
One key per workload. Rotation stays cheap and a compromise is contained.
Start from the recommended read scopes, then add what you actually get a 403
on. Broad-then-narrow rarely gets narrowed.
Set an expiry. A key that expires is one you cannot forget about.
Add an IP allowlist for anything running from fixed infrastructure.