API Keys

Mushu supports two authentication methods: CLI tokens for interactive development, and API keys for server-to-server calls. This guide explains when to use each and how to create and manage API keys.

Authentication Methods

MethodUse CaseExpiryHow to Get
CLI Token Interactive development, CLI commands 12 hours mushu auth login
API Key Backend servers, automated systems Never (until deleted) Dashboard or CLI

When to Use API Keys

Use API keys when:

  • Your backend server calls Mushu APIs
  • You need a credential that doesn't expire
  • You want to avoid token refresh logic
  • You're integrating with CI/CD pipelines

Use CLI tokens when:

  • Running commands from your terminal
  • Testing APIs during development
  • Any interactive, short-lived session

Creating API Keys

Via CLI

mushu api-key create --name "backend-server" --org ORG_ID

Output:

{
  "key_id": "key_abc123",
  "key": "msk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "backend-server",
  "scopes": ["read", "write"],
  "created_at": "2026-01-15T10:30:00Z"
}

Important: The full key (msk_live_...) is only shown once. Copy it immediately and store it securely. You cannot retrieve it later.

Via API

POST /orgs/{org_id}/api-keys
Authorization: Bearer YOUR_CLI_TOKEN
Content-Type: application/json

{
  "name": "backend-server",
  "scopes": ["read", "write"]
}

API Key Scopes

Scopes control what operations an API key can perform:

ScopePermissions
read Read organizations, tenants, devices, media metadata
write Register devices, upload media, send notifications
admin Create/delete tenants, manage API keys, modify settings

By default, keys are created with read and write scopes. Use admin sparingly—only for management tools that need full access.

Creating a Read-Only Key

mushu api-key create --name "analytics" --org ORG_ID --scopes read

Creating an Admin Key

mushu api-key create --name "admin-tool" --org ORG_ID --scopes read,write,admin

Using API Keys

Include the API key in the Authorization header with the ApiKey scheme:

GET /orgs/{org_id}/tenants
Authorization: ApiKey msk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

Or use the X-API-Key header:

GET /orgs/{org_id}/tenants
X-API-Key: msk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

Example: Python (SDK)

import os
import mushu
from mushu.notify.api.push import send_notification
from mushu.notify.models import SendNotificationRequest, Alert

client = mushu.client("notify", api_key=os.environ["MUSHU_API_KEY"])

async def send_push(tenant_id: str, user_id: str, title: str, body: str):
    response = await send_notification.asyncio_detailed(
        tenant_id=tenant_id,
        client=client,
        body=SendNotificationRequest(
            user_id=user_id,
            alert=Alert(title=title, body=body),
        ),
    )
    return response.parsed

Install the SDK: pip install mushu

Example: Node.js

const API_KEY = process.env.MUSHU_API_KEY;

async function uploadMedia(orgId, file) {
  // Get upload URL
  const { media_id, upload_url } = await fetch(
    `https://media.mushucorp.com/media/upload-url`,
    {
      method: 'POST',
      headers: {
        'Authorization': `ApiKey ${API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        org_id: orgId,
        filename: file.name,
        content_type: file.type,
        size_bytes: file.size,
      }),
    }
  ).then(r => r.json());

  // Upload to presigned URL
  await fetch(upload_url, {
    method: 'PUT',
    headers: { 'Content-Type': file.type },
    body: file,
  });

  // Confirm upload
  return fetch(`https://media.mushucorp.com/media/${media_id}/confirm`, {
    method: 'POST',
    headers: { 'Authorization': `ApiKey ${API_KEY}` },
  }).then(r => r.json());
}

Listing API Keys

mushu api-key list --org ORG_ID

Output:

KEY_ID       NAME              SCOPES        CREATED
key_abc123   backend-server    read,write    2026-01-15
key_def456   analytics         read          2026-01-10
key_ghi789   admin-tool        read,write,admin  2026-01-01

Deleting API Keys

If a key is compromised or no longer needed, delete it immediately:

mushu api-key delete key_abc123 --org ORG_ID

All requests using that key will fail after deletion.

Key Rotation

Rotate API keys periodically to limit the impact of potential compromises:

  1. Create a new key with the same scopes
  2. Update your server to use the new key
  3. Deploy and verify the new key works
  4. Delete the old key

Tip: Use environment variables for API keys in your servers. This makes rotation a config change instead of a code change.

Security Best Practices

  1. Never commit keys to source control - Use environment variables or secrets managers
  2. Use the minimum required scopes - A notification service doesn't need admin
  3. One key per service - If one is compromised, only rotate that one
  4. Rotate regularly - Quarterly rotation is a good baseline
  5. Monitor usage - Watch for unusual patterns in your Mushu dashboard

Key Prefixes

Mushu API keys use prefixes to indicate their type:

PrefixEnvironment
msk_live_Production
msk_test_Test/sandbox

Test keys only work against sandbox endpoints and won't affect production data.

FAQ

Can I see my key again after creating it?

No. The full key is only shown once at creation time. If you lose it, delete the key and create a new one.

What happens if my key is compromised?

Delete it immediately using the CLI or dashboard. Then create a new key and update your servers.

Can I use API keys in my iOS app?

Yes, but be aware that keys bundled in apps can be extracted. For device registration this is usually acceptable. For admin operations, use your backend server instead.

How many keys can I create?

There's no limit. Create as many as you need for different services and environments.

Next Steps