Authorization: Bearer <key> or in an x-api-key header.
Quick Start
If you already have an API key, here’s the fastest way to make a request:YOUR_API_KEY with your actual key (a brand key starts with sk_team_, an organization key with sk_org_; older brand keys start with plain sk_ and keep working). Add Content-Type: application/json whenever you send a body. A single-page audit streams newline-delimited JSON (status lines, then the result on the last line), so -N shows progress as it arrives.
Creating an API Key
1
Go to the API settings page
In the SnowSEO dashboard, navigate to Settings → Integrations → API. Only organization admins and owners can create or delete keys, and the organization needs the Scale plan.
2
Create a new key
Under Brand API keys (one brand) or Organization API keys (every brand), click Create new key. Give it a descriptive name so you remember what it’s for - e.g.,
Production Server, CI/CD Pipeline, or Analytics Dashboard. See Key Scopes to choose between them.3
Copy and store the key immediately
The full key is shown only once after creation. Copy it right away and store it in a secure location.
Making Your First Request
Here’s a complete example showing how to call the API from different environments:- Node.js
- Python
- Next.js API Route
Key Scopes & Permissions
There are two kinds of key. Pick a brand key when an integration only needs one brand, and an organization key when one integration works across all of them.
Brand keys. The key carries your organization and brand, so you don’t pass
teamId. If you do pass a teamId (or teamIds), it must be the key’s own brand; any other brand returns 403 with code API_KEY_TEAM_MISMATCH. Organization-level endpoints return 403 with code API_KEY_ROUTE_NOT_ALLOWED.
Organization keys. Name the brand on each request with teamId (query string for reads, body for writes). Call GET /v3/mcp/teams first to list the brands and their IDs. A team-scoped request without teamId returns 400, and a brand from another organization returns 403 with code API_KEY_TEAM_MISMATCH.
Endpoints tied to a person rather than a brand, such as Ask Snowy chats, can’t be called with either kind of key and return 403 with code API_KEY_ROUTE_NOT_ALLOWED.
Common Integration Patterns
Serverless Functions (Vercel, Netlify, etc.)
Webhook Handler (Receiving Data)
If you’re building an integration that receives webhooks from SnowSEO (e.g., article published events), validate theAuthorization header:
Automated Reporting Script
Error Handling
The API returns structured error responses. Here’s how to handle them properly:Error Reference
Theerror field holds a human-readable message (e.g. "teamId is required", "Team not found", "Rate limit exceeded."). Some errors also include a machine-readable code, such as UNAUTHORIZED, FST_ERR_VALIDATION, MCP_TOOL_DISABLED, or SCALE_PLAN_REQUIRED; IndexNow endpoints return message only. Branch on the HTTP status code (and code when present), and surface error / message to the user.
Security Best Practices
Use environment variables
Use environment variables
Always store your key in an environment variable, never hardcoded:
Never commit secrets to version control
Never commit secrets to version control
Add your For GitHub, use Secrets (Settings → Secrets and variables → Actions) to store API keys for CI/CD pipelines.
.env file to .gitignore:Use separate keys per environment
Use separate keys per environment
Create different API keys for development, staging, and production:
MyApp-DevMyApp-StagingMyApp-Production
Rotate keys periodically
Rotate keys periodically
Rotate your API keys every 90 days or immediately if you suspect compromise:
- Create a new key in the dashboard
- Update your environment variable
- Deploy and verify it works
- Delete the old key
Validate incoming webhooks
Validate incoming webhooks
If you’re receiving webhooks from SnowSEO, always validate the
Authorization header against your stored secret:Rate Limits & Retries
Each API key is capped at 120 requests per 60 seconds. Routes also have their own limits (for example 100 per minute for/v3/seo-audit and 150 for rank tracking), and there is a global cap of 240 requests per minute for the organization. If you exceed any of these, you’ll get a 429 response with a retryAfterSeconds hint (the key-level limit also sends a Retry-After header and code RATE_LIMITED):
Implementing Retry Logic
Quick Test
Verify your key works with a simple request:401 Unauthorized, double-check:
- The key is correctly set in your environment variable
- You’re using
Bearer(with the space) before the key - The key hasn’t been deleted from the dashboard

