Authentication
Every MIOSA API request carries a single Authorization: Bearer <token> header.
The token is either an API key (prefix msk_) or a JWT from POST /auth/login.
One key covers the entire platform - computers, desktop, files, exec, CUA agent, OSA, credits, and (with the right role) admin. No separate keys for AI, no per-product configuration.
Credential hierarchy
API Keys
Key format
msk_<role>_<random> | Prefix | Role | Capabilities |
|---|---|---|
msk_u_... | user | Compute, desktop, files, CUA, OSA, credits |
msk_a_... | admin | Everything above + /api/v1/admin/* |
msk_p_... | platform | Tenant-wide automation issued by the MIOSA platform |
The public self-service endpoint creates normal API-purpose keys. Specialized operator or intelligence credentials use separate controlled flows.
Creating an API key
curl -X POST https://api.miosa.ai/api/v1/api-keys
-H "Authorization: Bearer YOUR_JWT_TOKEN"
-H "Content-Type: application/json"
-d '{
"name": "Production SDK Key",
"key_type": "user"
}' {
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "msk_u_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"key_prefix": "msk_u_a1b2c3",
"name": "Production SDK Key",
"key_type": "user",
"key_purpose": "api",
"rate_limit_rpm": 600,
"status": "active",
"created_at": "2026-04-17T00:00:00Z"
}
} Users can mint personal user keys.
Tenant owners and administrators can also mint platform keys for backend automation.
Admin keys remain operator-internal and are not created through the public self-service endpoint.
Using an API key
Pass the key in the Authorization header:
curl https://api.miosa.ai/api/v1/computers
-H "Authorization: Bearer msk_u_a1b2c3d4e5f6..." All five SDKs read MIOSA_API_KEY from the environment by default:
Managing keys
| Action | Endpoint |
|---|---|
| List your keys | GET /api/v1/api-keys |
| Create a key | POST /api/v1/api-keys |
| Revoke a key | DELETE /api/v1/api-keys/{id} |
Revoking a key flips its status to revoked. The change is cached and
enforced within seconds - subsequent requests return 401 Unauthorized.
Revocation is irreversible; create a new key if you need access restored.
Admin keys
msk_a_* keys unlock operator-admin endpoints. msk_p_* keys are trusted tenant automation credentials, but they do not automatically make a caller a MIOSA operator.
User-role callers hitting an admin endpoint receive 403 Forbidden.
Admin endpoints are operator-internal and not documented publicly.
Preview tokens
Preview tokens (mp_<base64url>) are short-lived signed tokens for embedding a sandbox preview in an <iframe> without exposing an msk_* key to the browser.
Your backend mints a preview token server-side and passes it to the <MiosaPreview> UI component. The component includes it automatically - no Authorization header needed in browser code.
Minting a preview token
curl -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_abc123/preview-token
-H "Authorization: Bearer msk_u_..."
-H "Content-Type: application/json"
-d '{"expires_in": 3600}' {
"data": {
"token": "mp_eyJhbGciOiJFZERTQSIs...",
"expires_at": "2026-05-25T13:00:00Z",
"sandbox_id": "sbx_abc123"
}
} In the browser, pass the token to the <MiosaPreview> component:
<MiosaPreview token="mp_eyJhbGciOiJFZERTQSIs..." sandboxId="sbx_abc123" />
See <MiosaPreview> and other UI components and the Preview Tokens API reference for the full component API and token validation spec.
- Format:
mp_<base64url>- signed, not opaque; do not attempt to decode. - TTL: Default 1 hour; configurable via
expires_in(max 24 hours). - Scope: Read-only access to the specific sandbox’s preview port. Cannot create or mutate resources.
- Revocation: Preview tokens cannot be individually revoked. Destroying the sandbox invalidates all outstanding tokens for it.
Share tokens
Share tokens (ms_<base64url>) turn a sandbox preview into a public read-only URL that anyone with the link can visit - no MIOSA account required.
Minting a share URL
curl -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_abc123/shares
-H "Authorization: Bearer msk_u_..."
-H "Content-Type: application/json"
-d '{"expires_in": 86400}' {
"data": {
"token": "ms_eyJhbGciOiJFZERTQSIs...",
"url": "https://sbx-abc123.sandboxes.miosa.ai?ms=ms_eyJhbGciOiJFZERTQSIs...",
"expires_at": "2026-05-26T00:00:00Z",
"sandbox_id": "sbx_abc123"
}
} - Format:
ms_<base64url>- the token IS the URL query parameter (?ms=ms_...). - Access: Public, read-only, unauthenticated - anyone with the URL can view the preview.
- TTL: Set via
expires_inin seconds. No maximum enforced; omit for a non-expiring share. - Revocation:
DELETE /api/v1/sandboxes/:id/shares/:share_idrevokes immediately.
See the Sandbox Shares API reference and Integrations: Preview Tokens.
Token comparison
msk_* API key | JWT | Browser token | mp_ Preview token | ms_ Share token | |
|---|---|---|---|---|---|
| Scope | Full workspace | User session | Single sandbox | Single sandbox preview | Single sandbox preview |
| TTL | Until revoked | ~1 h (refresh 7 d) | Configurable (default 1 h) | Configurable (default 1 h) | Configurable |
| How to mint | Dashboard or POST /api/v1/api-keys | POST /api/v1/auth/login | POST /api/v1/browser-tokens | POST /api/v1/sandboxes/:id/preview-token | POST /api/v1/sandboxes/:id/shares |
| Who uses it | Server | Server / browser (UI) | Browser | Browser / iframe | Anyone (unauthenticated) |
| Can revoke | Yes | No (short TTL) | No (short TTL) | No | Yes |
| Creates resources | Yes | Yes | No | No | No |
White-label auth note
The tenant.preview_domain.* and tenant.branding.* configuration endpoints accept both msk_* API keys and JWTs. These are the only tenant-level config routes accessible with an API key - all other tenant administration routes require a JWT from an admin session.
# Setting a preview domain with an API key (allowed)
curl -X PUT https://api.miosa.ai/api/v1/tenant/preview-domain
-H "Authorization: Bearer msk_a_..."
-H "Content-Type: application/json"
-d '{"domain": "preview.yourdomain.com"}'
# Fetching tenant branding with an API key (allowed)
curl https://api.miosa.ai/api/v1/tenant/branding
-H "Authorization: Bearer msk_a_..." See the Tenant Preview Domain and Tenant Branding API references for the full configuration spec.
JWT Tokens
JWT tokens are used by the MIOSA web UI and SSE ticket flows. They are issued on login and carry user identity + tenant context.
Obtaining a token
curl -X POST https://api.miosa.ai/api/v1/auth/login
-H "Content-Type: application/json"
-d '{"email": "user@example.com", "password": "your_password"}' {
"token": "eyJhbGciOiJIUzUxMiIs...",
"refresh_token": "eyJhbGciOiJIUzUxMiIs...",
"user": { "id": "...", "email": "user@example.com" }
} Token lifecycle
| Token | Lifetime | Refresh |
|---|---|---|
| Access token | ~1 hour | Use refresh token |
| Refresh token | 7 days | Re-login required |
curl -X POST https://api.miosa.ai/api/v1/auth/refresh
-H "Content-Type: application/json"
-d '{"refresh_token": "eyJhbGciOiJIUzUxMiIs..."}' SSE streams
Server-Sent Event endpoints (CUA session events) cannot use a standard Authorization header because EventSource does not support custom headers.
Instead, mint a one-time ticket first:
# 1. Ask for a ticket (Bearer-authed - API key or JWT both work)
curl -X POST
https://api.miosa.ai/api/v1/computers/{id}/cua/sessions/{session_id}/sse-ticket
-H "Authorization: Bearer msk_u_..."
# {"ticket":"sset_abc123","expires_in":3600,"session_id":"..."}
# 2. Open the stream with the ticket as a query param
curl https://api.miosa.ai/api/v1/computers/{id}/cua/sessions/{session_id}/events?ticket=sset_abc123 The ticket is single-use and expires after one hour.
Rate limits
| Scope | Current default | Notes |
|---|---|---|
| User API key | 600 requests per minute | Tenant and endpoint-family policy can lower it |
| Platform API key | 30,000 requests per minute | Restricted to tenant owners and administrators |
| Public auth endpoints | 60 requests per minute per IP | Individual auth actions may have separate controls |
When rate limited, the API returns 429 Too Many Requests with a Retry-After header.
Rate-limit status is surfaced in every response:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
X-RateLimit-Reset: 1712700060 Error codes
| Status | Code | Meaning |
|---|---|---|
| 401 | UNAUTHORIZED | Missing / invalid / revoked credential |
| 403 | FORBIDDEN | Valid credential but insufficient role |
| 429 | RATE_LIMITED | Too many requests |
Security best practices
- Never commit API keys to version control.
- Use environment variables or a secrets manager.
- Rotate keys on exposure - revoke and create a new one.
- Scope by role - hand out
msk_u_*keys to most callers; reservemsk_a_*/msk_p_*for operational tooling. - Separate keys for dev and prod - easier to revoke blast radius.
- Restrict by IP (admin keys) - pass
allowed_ipswhen minting viaPOST /admin/api-keysto reject traffic from unexpected sources.