Authentication

Snipara supports multiple authentication methods: API keys for programmatic access, OAuth for interactive flows, and device flow for CLI tools.

Overview

MethodUse CaseFormat
Project API KeySingle project accesssnp-...
Team API KeyMulti-project accesssnp-team-...
OAuth TokenDevice flow / CLIsnipara_at_...

Header Formats

# API Key (recommended for scripts)
X-API-Key: snp-your_key_here
# OAuth Token (for device flow)
Authorization: Bearer snipara_at_your_token_here

API Keys

Project API Keys

Access a single project via MCP or REST API.

Access LevelDescriptionRepresentative ToolsPlan Requirement
VIEWERRead-only accesssnipara_context_query, snipara_ask, snipara_searchCore query tools are Free; semantic/hybrid and memory recall can require Pro+
EDITORRead + Write (default)All VIEWER + snipara_remember, snipara_inject, snipara_upload_documentPlan still applies per tool; memory write tools require Pro+
ADMINFull accessAll tools including snipara_swarm_create, snipara_claim, snipara_task_createSwarm coordination requires Team+; htask tools require Pro+

Creating API Keys

  1. Go to Project > API Keys in dashboard
  2. Click "Create API Key"
  3. Enter name and select access level (VIEWER/EDITOR/ADMIN)
  4. Copy key immediately (shown once only!)
Important: API keys are hashed before storage. The original key cannot be retrieved — copy it immediately after creation.

Using API Keys

curl -X POST https://api.snipara.com/mcp/my-project \
  -H "Content-Type: application/json" \
  -H "X-API-Key: snp-abc123..." \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "snipara_ask",
      "arguments": {"query": "How does auth work?"}
    }
  }'

Team API Keys

Access all projects in a team with a single key. Format: snp-team-...

# Multi-project query with team key
curl -X POST https://api.snipara.com/mcp/team/my-team \
  -H "X-API-Key: snp-team-abc123..." \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{
    "name":"snipara_multi_project_query","arguments":{"query":"authentication"}}}'

Device Flow

Device flow enables CLI and headless authentication without browser interaction during operation. Perfect for snipara-mcp and VS Code extension.

┌─────────────┐                              ┌─────────────┐
│    CLI      │                              │   Snipara   │
└──────┬──────┘                              └──────┬──────┘
       │                                            │
       │  1. Request device code                    │
       │  POST /api/oauth/device/code               │
       │────────────────────────────────────────────>
       │                                            │
       │  {device_code, user_code, uri}             │
       │<────────────────────────────────────────────
       │                                            │
       │  2. Display: "Go to snipara.com/device"    │
       │     Display: "Enter: ABCD-1234"            │
       │                                            │
       │  3. User opens browser, enters code        │
       │                                            │
       │  4. Poll: POST /api/oauth/device/token     │
       │────────────────────────────────────────────>
       │                                            │
       │  {access_token, api_key, project_slug}     │
       │<────────────────────────────────────────────

Step 1: Request Device Code

curl -X POST https://snipara.com/api/oauth/device/code \
  -H "Content-Type: application/json" \
  -d '{"client_id": "snipara_cli", "auto_provision": true}'

Response:

{
  "device_code": "abc123def456ghi789...",
  "user_code": "ABCD-1234",
  "verification_uri": "https://snipara.com/device",
  "verification_uri_complete": "https://snipara.com/device?code=ABCD-1234",
  "expires_in": 900,
  "interval": 5
}

Step 2: Poll for Token

curl -X POST https://snipara.com/api/oauth/device/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
    "device_code": "abc123def456ghi789...",
    "client_id": "snipara_cli"
  }'

Success response (with auto_provision: true):

{
  "access_token": "snipara_at_abc123...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "snipara_rt_def456...",
  "project_slug": "my-project",
  "api_key": "snp-abc123...",
  "mcp_endpoint": "https://api.snipara.com/mcp/my-project"
}

Auto-Provision

With auto_provision: true, new users automatically get a free account, personal workspace, default project, and API key — zero friction onboarding.

Rate Limiting

PlanRequests/MinuteMonthly Queries
FREE301,000
PRO12010,000
TEAM30050,000
ENTERPRISE1,000500,000 fair use

Rate Limit Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705320000

Security Best Practices

Never Commit Keys

Use environment variables. Add .env to .gitignore.

Rotate Regularly

Generate new keys periodically. Revoke old keys.

Use Minimal Scope

Prefer project keys over team keys. Use VIEWER when write access isn't needed.

Set Expiration

Create time-limited keys for temporary access.

Environment Variables

# .env (never commit!)
SNIPARA_API_KEY=snp-your_key_here
# .gitignore
.env
.env.local
.env.*.local

Requesting Project Access

If you can authenticate but still have no effective access to a project, use snipara_request_access to ask project admins for a higher access level.

snipara_request_access

snipara_request_access({
  requested_level: "EDITOR",
  reason: "Need to upload onboarding docs and store rollout decisions"
})

This creates an access request for project admins to review in the dashboard. Use it when your identity is valid but your current role is NONE or too limited for the task you need to perform.

Troubleshooting

ErrorCauseSolution
"Missing authentication"No credentials providedAdd X-API-Key header
"Invalid API key"Key revoked or expiredGenerate new key in dashboard
"Invalid OAuth token"Token expired (24h validity)Refresh with refresh_token
"Rate limit exceeded"Too many requestsWait and retry with backoff
"405 Method Not Allowed"POST request sent to an endpoint that only accepts a different methodCheck the route and method against the API reference before retrying

Next Steps