SMLL Docs

Authentication

Create, use, scope and revoke API keys, and how they differ from CLI and dashboard tokens.

Every request under /api/v1 carries a bearer token:

Authorization: Bearer <token>

There is no cookie or session auth on the API, and no unauthenticated write path.

Token types

TokenFormatLifetimeCreated by
API keysk- + 64 hex charsUntil revoked, or an optional expiryYou, per workspace
CLI session tokenHex string, no dotsUntil revoked or expiredsmll login
Dashboard JWTThree dot-separated partsShort, auto-refreshedSupabase Auth

The API tells them apart by shape: an sk- prefix means an API key, a token containing dots is parsed as a JWT, and anything else is looked up as a CLI session. All three resolve to the same thing (a user), so any endpoint accepts any of them.

For scripts, CI and integrations, use an API key. The other two exist for interactive use and are tied to a login.

Create an API key

From the dashboard: Settings > API Keys > Create key.

From the CLI:

smll api-keys create --name "GitHub Actions" --expires 90d

Over the API, creating a key needs the Owner or Admin role:

curl -s -X POST \
  -H "Authorization: Bearer $EXISTING_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"GitHub Actions","expires_in_days":90}' \
  https://api.smll.io/api/v1/workspaces/$WORKSPACE_ID/api-keys
FieldTypeRequiredNotes
namestringYesMust be unique in the workspace, else 409
expires_in_daysintegerNoOmit for a key that never expires
scopesstring[]NoRecorded on the key, see Scopes below

The response is the key record plus the secret itself:

{
  "id": "b4c1...",
  "workspace_id": "acaa...",
  "name": "GitHub Actions",
  "key_prefix": "sk-3f9c1a2b4",
  "scopes": [],
  "expires_at": "2026-11-18T12:00:00Z",
  "created_at": "2026-08-20T12:00:00Z",
  "key": "sk-3f9c1a2b4..."
}

key is returned once, at creation. Only a SHA-256 hash is stored, so a lost key cannot be recovered or re-displayed. Create a replacement and revoke the old one.

Afterwards, listing keys shows key_prefix (the first 12 characters) so you can tell them apart, never the full value.

Use a key

curl -s -H "Authorization: Bearer sk-..." \
  https://api.smll.io/api/v1/workspaces/$WORKSPACE_ID/vpcs

Each accepted request updates the key's last_used_at, which the dashboard shows. That is the quickest way to find keys nothing uses any more.

What a key can do

A key acts as the user who created it, and inherits that user's role in the workspace at the time each request is made:

  • A key created by an Owner or Admin can create, update and delete.
  • A key created by a Developer or Viewer is read-only, and gets 403 insufficient workspace permissions on writes.
  • If the user's role is later downgraded, the key loses that access too. If the user is removed from the workspace, the key stops working there.

A key is not confined to the workspace it was created in. It authenticates the user, so it reaches every workspace that user belongs to, with whatever role they hold in each. Treat a key as equivalent to that person's account access, and give CI its own key on a least-privileged user rather than sharing one.

Scopes

The scopes field is accepted and stored on the key, and shows up when you list keys, but it does not currently restrict anything. Do not rely on it as a security boundary. Until scope enforcement ships, limit a key's reach by choosing the role of the user that creates it.

Expiry and revocation

A key stops working the moment it is revoked, and at the instant expires_at passes. Either way the next request gets:

{ "error": "invalid or expired API key" }

with status 401. There is no grace period and no warning email.

Revoke from the dashboard, with smll api-keys revoke <id>, or:

curl -s -X DELETE \
  -H "Authorization: Bearer $EXISTING_TOKEN" \
  https://api.smll.io/api/v1/workspaces/$WORKSPACE_ID/api-keys/$KEY_ID

A successful revoke returns 204 with no body. Revocation is permanent: keys are not un-revoked, and the same secret is never reissued.

Rotating a key

Because the secret is only shown at creation, rotation is create-then-revoke, in that order:

  1. Create the replacement key.
  2. Update the consumer (CI secret, deployment config) to the new value.
  3. Confirm the new key's last_used_at has moved.
  4. Revoke the old key.

Doing it the other way round means downtime between the revoke and the redeploy.

Endpoints

MethodPathRole
GET/api/v1/workspaces/{workspaceID}/api-keysAdmin
POST/api/v1/workspaces/{workspaceID}/api-keysAdmin
DELETE/api/v1/workspaces/{workspaceID}/api-keys/{keyID}Admin

Listing and creating keys both require Owner or Admin, so a Developer cannot enumerate a workspace's keys.

Using the CLI in CI

The CLI has no environment-variable login. To use it in a job, write its two config files yourself:

mkdir -p ~/.smll
jq -n --arg t "$SMLL_API_KEY" \
  '{api_url:"https://api.smll.io", token:$t}' > ~/.smll/credentials.json
jq -n --arg w "$WORKSPACE_ID" --arg v "$VPC_ID" \
  '{workspace_id:$w, vpc_id:$v}' > ~/.smll/config.json
chmod 600 ~/.smll/*.json

For most CI work, calling the API with curl is simpler. See Deploying from GitHub Actions for a complete workflow.

On this page