Skip to content
Gujo Developers Sign in

Authentication and API keys

When to sign in (OAuth) and when to use an account API key, what a key looks like, its abilities, product-scoped keys, limits, revocation and error codes.

View as Markdown

Request header

Every call authenticates with Authorization: Bearer <key>. The canonical host of the public API is api.gujo.ai.

curl https://api.gujo.ai/api/products \
  -H "Authorization: Bearer $GUJO_API_KEY"

Older clients call gujo.ai/api/..., which is forwarded to api.gujo.ai, but that path only passes the authorization, content-type, accept, accept-language and user-agent headers plus X-* headers. New code should always call api.gujo.ai.

Signing in (OAuth) or an API key

To connect an agent to the customer MCP, sign in first. Use a key where nobody can sign in through a browser.

Signing in (OAuth) Account API key
Works with The customer MCP (https://api.gujo.ai/api/mcp) only The whole account API and the customer MCP
Use it for MCP clients people use, such as Claude Code, Codex, Cursor, VS Code and Claude.ai CI, scripts on a server, headless agents and direct calls such as curl
How you get it Give your client the server URL, then sign in and approve its permissions in the browser Create it in Developer settings and put the value, shown once, into an environment variable
Permissions What you approved (by default mcp.read and products.read) The abilities you picked at creation
Lifetime Access token one hour, refreshed by the client (expires after 30 days without use) Until the expiry you set (or until revoked)
Disconnect Connected apps in your account security settings Revoke it in the key list in Developer settings

Both use the same permission names and the same checks, so the ability table below applies to sign-in permissions too. Tokens you get by signing in are accepted only by the customer MCP, so calling other account API endpoints with them returns 401 invalid_api_key. Connection steps and token lifetimes are in Connect MCP.

If you build your own MCP client, follow the standard OAuth flow (MCP 2025-11-25 authorization). Start from the protected resource metadata at https://api.gujo.ai/.well-known/oauth-protected-resource/api/mcp and the authorization server metadata at https://account.gujo.ai/.well-known/oauth-authorization-server. Only the authorization code flow with PKCE (S256) is accepted. Register your app with a client ID metadata document (CIMD) or dynamic registration (POST /oauth/register). Send resource=https://api.gujo.ai/api/mcp in the authorization and token requests.

What a key looks like

  • Keys start with gujo_.
  • The server stores only a SHA-256 hash of the key. The plain value is shown once at creation, and after that not even Gujo can show it again.
  • The key list on the Developer settings page shows each key's name, its first 14 characters (the prefix) and its abilities. Use the prefix to tell keys apart.

Abilities

Each key lists the abilities it may use. The ability each endpoint needs is in the ability column of the API reference. When it is empty, any valid key will do.

Ability Opens Keys that have it from the start
products.read Library, product list and detail, update checks, install plans, setup progress, product license Keys you create, device sign-in keys
orders.read Your orders, invoices and payment methods None (pick it when you create a key)
subscriptions.read Your subscriptions None (pick it when you create a key)
mcp.read Customer MCP (POST /api/mcp) Keys you create
setup-progress.write Recording product setup progress None (pick it when you create a key)
device.install Install records, app distribution feeds and downloads Keys you create, device sign-in keys
device.entitlements Owned products, license checks, Pass checks Device sign-in keys
device.activate Bulk app activation Device sign-in keys
device.usage Product usage upload Device sign-in keys
support.report App problem reports Device sign-in keys
  • A key you create starts with products.read, mcp.read and device.install.
  • A key from device sign-in in gujoctl or Gujo Cloud Apps gets six: products.read, device.entitlements, device.activate, device.install, device.usage and support.report. If you need orders.read, subscriptions.read or mcp.read, create a separate key on the Developer settings page.
  • support.staff, commerce.staff and design.staff are abilities for Gujo operators. They do nothing on an ordinary account's key.

Product-scoped keys

Most keys cover the whole account. Some are bound to one product, such as the key Gujo Cloud Apps receives when it activates an app.

  • GET /api/library with a product-scoped key returns only that product.
  • Calling another product's path returns 403 product_api_key_scope_required.

Limits and expiry

  • You can hold up to 3 live keys per scope. Account-wide keys and the keys bound to each product are counted separately.
  • If there is no free slot when you create a key, issuing fails and the page shows the limit. Revoking a key frees a slot.
  • Device sign-in with no free slot revokes the least recently used key of the same client and issues a new one.
  • A key you create works until the expiry date you set (or until you revoke it, if you set none). A device sign-in key expires after 90 days without use, and each use pushes that date back.

Revocation

  • Revoke a key at any time from the key list on the Developer settings page.
  • gujoctl logout revokes the gujoctl key on the server, then deletes it from the device.
  • A revoked or expired key gets 401 invalid_api_key from the next request on.

If you think a key has leaked, revoke it first, then create a new one.

Errors

Authentication and permission errors have the body {"message": "...", "error": "<code>"}. /api/* never redirects to a sign-in page. It always answers with JSON.

Status error Meaning
401 missing_api_key No Authorization header
401 invalid_api_key Unknown, revoked or expired key
403 missing_api_key_ability The key lacks the ability this endpoint needs
403 product_entitlement_required You have no entitlement to that product
403 product_api_key_scope_required A key bound to one product called another product
404 — The target does not exist
422 — Validation failed. The body is {message, errors}
429 — Rate limit exceeded. The whole API allows 60 requests a minute, and some endpoints add a tighter limit of their own

The ability check runs before the target is looked up, so a key without the ability cannot learn whether an id exists (it gets 403, not 404).

Handling keys

  • Send keys only in the header. Never put them in a URL query or path.
  • Keep environment variable names, not key values, in config files and repositories. Every key config in Connect MCP points at GUJO_API_KEY.
  • Don't send the key to the signed download URL an install plan returns. Keys go to the API host only.
  • For an MCP client a person uses, connect by signing in instead of using a key. Then no key needs to sit in a config at all.