Manage members and API keys
Two kinds of access exist side by side: people, who sign in and hold roles, and keys, which authenticate an integration as the person who created them. This guide covers both, and the one rule that connects them.
Add someone to the organization
Open Settings, then Organization. The members list is there, along with your own role and the organization's identity-provider settings.
Add member invites someone by email address. They receive a single-use invitation link, and following it activates their account. If the invitation is lost or expires, re-inviting the same person issues a fresh one and invalidates the old.
An organization member holds one of three roles: owner, admin or member. Ownership transfers explicitly (Transfer ownership), and an organization always has one.
Add someone to a project
Organization membership does not grant access to a project's work. Open the project's dashboard and use the Members tab, then Manage Members.
A project member holds one of four roles.
| Role | Give it to |
|---|---|
owner | Whoever is accountable for the project. The last owner cannot be removed or demoted. |
admin | Someone who manages the project's members and resources. |
developer | Someone who registers models and runs benchmarks. |
viewer | Someone who reads results. |
The distinction that catches people out: devices are organization-scoped, so every project sees the same fleet. Everything else (models, runs, services, artifacts, licenses) belongs to one project and is invisible from the others.
Mint an API key
Open Settings, then Developer access. Create key takes a name (CI pipeline, nightly sweep) and the scope the key should carry.
The key is shown once, at creation. Copy it then; the platform stores only its hash and a short display prefix, so a lost key is replaced rather than recovered.
Use it as a bearer token:
curl -H "Authorization: Bearer clika_your_api_key" \
https://platform.clika.io/api/devices
Or save it to a CLI profile, which prompts without echoing so nothing lands in your shell history:
clika-rt --base-url https://platform.clika.io login --api-key
Scopes, and why a key can never exceed you
A key authenticates as the user who created it, and its scope is an allowlist of capabilities. The permissions a request actually gets are the owner's capabilities intersected with the key's scope, recomputed on every request. Two consequences follow.
- A key can never do something its owner cannot, and demoting the owner narrows every key they own immediately, with no revocation sweep to run.
- A key can do considerably less than its owner, which is the point. A key scoped to reading devices and running benchmarks is a safe thing to put in CI, or to hand to an MCP client, because no prompt and no script can make it edit members or licenses.
An empty scope grants nothing, which is a useful thing to create deliberately. It is not the same as the unrestricted scope some older keys carry.
The three templates
The creation dialog offers three ready-made scopes, expanded server-side from what you yourself hold.
| Template | What it grants |
|---|---|
| viewer | Every read and list capability you hold. A safe default for dashboards, reporting and anything that only observes. |
| worker | The viewer set plus write, cancel and invoke. This is the CI shape: it can register a model, launch a benchmark, cancel one, and call a model deployment. |
| admin | Every capability you hold that a key may carry at all, including delete. |
No template ever includes the sharper verbs: delete outside the admin template, and never exec, tunnel, remote_desktop, the cross-team read_all and manage_all, the storage test probes, or manage. If a key needs one of those, grant it explicitly and know why.
The capabilities a key can carry
Capabilities are named resource:action. What the scope catalogue offers you is bounded by what you hold, so your own list may be shorter than this one.
| Resource | Capabilities | Holding them admits |
|---|---|---|
devices | read, write, delete, exec, tunnel, remote_desktop, read_all, manage_all | Reading and managing the fleet. exec runs arbitrary commands on a device, tunnel opens a TCP tunnel to one, remote_desktop opens an interactive screen and keyboard session, and the two _all forms are the cross-team administrative view. |
jobs | read, write, cancel | Reading, submitting and cancelling jobs, which is what launching a benchmark needs. |
artifacts | read, write, delete | Reading the library, uploading and updating artifacts, and deleting them. |
model_serving | read, write, invoke | Seeing model deployments, managing them, and calling one through the platform proxy. invoke is separate on purpose: seeing a deployment is not the same as spending its GPU. |
services | read, write | Managing the device-side services subsystem. |
metrics | read, write | Reading and writing metric definitions and data points. |
alerts | read, write | Reading and managing alert rules. |
events | read | Reading the organization's event stream: device, job, command, transfer and alert activity. |
projects | read, write, delete | Managing projects and their membership. |
orgs | read, write | Reading and updating the organization record. |
teams | read, write | Managing teams. |
webhooks | read, write | Managing webhooks. |
hosted_devices | read, write, delete | Renting and running on hosted phones. write is the capability that spends money, since hosted devices bill by the minute. |
cloud_credentials, cloud_instances | read, write, delete | Managing stored cloud provider credentials and the instances created with them. |
credentials | read, write, delete | Managing container-registry credentials, which external artifacts use to pull. |
file_storage | read, write, test | Viewing and changing the artifact storage backend. test makes live outbound probes against the configured bucket. |
license | read | Reading the organization's plan and activation codes. |
license_profiles | read, write | Reading and curating entitlement profile templates. |
project_licenses | read | Reading a project's runtime credentials. |
runtime_deployments | read | Reading the runtime deployment plane. |
vpn | read, write, delete | Managing VPN configuration. |
What a key can never carry
Some capabilities are refused to every key, however you scope it, because a credential that holds them can widen itself and the scope would be decorative. They stay available to a signed-in session with the right role.
- Identity and access: creating or editing users, roles, and SSO configuration.
- Platform administration: the
/api/adminsurface, platform settings, and support access. - Minting credentials: issuing a runtime credential or writing the organization's license. Both create new authority, which is exactly what a leaked key must not be able to do.
- Billing: re-planning the organization or starting a payment flow.
Troubleshooting
The browser works, my API key gets 403 on one route. Read the error code. API_KEY_SCOPE_INSUFFICIENT names the capability the route needs and your key does not carry, which you fix by re-scoping the key. API_KEY_ROUTE_NOT_SCOPEABLE means the route declares no capability at all, so no key can reach it while a signed-in session still can; that is a gap in the deployment's route declarations rather than something you can fix from the key, so report the route to whoever runs the deployment.
A member cannot see a project's resources. Check project membership rather than organization membership. A resource in a project you are not a member of answers 404, deliberately, so that probing ids reveals nothing.
An invitation link does not work. Links are single-use and expire. Re-inviting issues a new one and invalidates the previous.
Related pages
- Organization and project: what each container holds.
- Set up MCP for Claude: the main consumer of a scoped key.