API Keys
API Keys (sk_live_*) authenticate tool clients (PicGo / Moraya / your own scripts) to Picora’s API. They are not used for AI tools — those use OAuth via HTTP MCP (v0.14+) or npm install @picora/mcp for stdio (v0.13+).
Creating an API Key
- Open Settings → API Keys
- Click Create new key
- Give it a name (e.g., “PicGo on MacBook”, “Production blog server”)
- Pick scopes (default: all)
- Click Create
- Copy the displayed key now — it’s shown once and never again
The full key looks like sk_live_abcdef0123456789... (40 characters total: sk_live_ prefix + 32 nanoid chars).
Scopes
Each key carries scope flags that determine what it can do:
| Scope | Includes |
|---|---|
images:read | List images, get metadata |
images:write | Upload images, update metadata |
images:delete | Delete images |
videos:read / videos:write / videos:delete | Same as images, for videos |
audio:read / audio:write / audio:delete | For audio |
docs:read / docs:write / docs:delete | For Markdown documents (v0.15+) |
usage:read | Read your own quota / usage |
By default, keys get all *:read and *:write permissions but not *:delete — to reduce blast radius if a key leaks.
You can refine scopes per key:
PicGo Blog Key → images:write only (cannot list / delete)CI Pipeline Key → images:write + docs:writeRead-only Audit Key → *:read scopes onlyUsing an API Key
In every API request:
curl -H "Authorization: Bearer sk_live_..." https://api.picora.me/v1/imagesTool clients embed the key in their config:
- PicGo: see PicGo integration
- Moraya: see Moraya integration
- Custom scripts: just include
Authorization: Bearer sk_live_...header
Listing keys
Settings → API Keys shows all your active keys with:
- Name
- Last 4 characters (e.g.,
...4f3a) - Scopes granted
- Last used timestamp
- Created date
You cannot view the full key value after creation — only the suffix for identification.
Rotation
Best practice: rotate API Keys every 90 days, or immediately if you suspect compromise.
- Create a new key with the same name + same scopes
- Update your tool config to use the new key (test that it works)
- Once verified, click Revoke on the old key in the keys list
Revoked keys are immediately invalid — any in-flight requests using them get 401.
Revocation
Click Revoke on any active key. The token cache is purged within 5 seconds globally. The key cannot be recovered after revocation.
If you revoked the wrong key: create a new one with the same scopes. There’s no undo.
Security best practices
DO
- ✅ Use separate keys per tool / environment — easier to rotate / revoke
- ✅ Minimize scopes — only grant what the tool needs
- ✅ Store keys in environment variables or a secret manager (not in source code)
- ✅ Rotate every 90 days
- ✅ Revoke immediately on suspected leak
DON’T
- ❌ Commit keys to git (even private repos — they leak through forks, mirrors, CI logs)
- ❌ Embed keys in client-side code (browsers, mobile apps) — they’re visible in network tab
- ❌ Share keys via email / Slack / Discord — use a secret manager
- ❌ Use a single “master key” for everything — separate concerns
If you accidentally committed a key to git
- Revoke the key immediately in Settings → API Keys
- Remove from git history (use
git filter-branchor BFG Repo-Cleaner) - Force-push the cleaned history (warn collaborators first)
- Create a new key for your tool
GitHub’s secret scanning will detect leaked Picora keys and alert us — we’ll auto-revoke and email you within 1 hour.
Programmatic key management
You can manage keys via API:
# Create a key (requires JWT, not a key — keys can't create keys for security)POST /v1/api-keys{ "name": "Backup script", "scopes": ["images:write"]}
# ListGET /v1/api-keys
# RevokeDELETE /v1/api-keys/{keyId}See API Reference — API Keys for full details.
Common issues
“401 Unauthorized” with valid-looking key — check the Authorization header format: must be Bearer prefix + key. Common mistake: missing Bearer or extra whitespace.
“403 Forbidden — missing scope” — your key doesn’t have the required scope. Create a new key with the right scopes; the old key cannot be edited (only revoked).
“Key works locally but not from production server” — likely IP-based rate limit (production server gets shared IP via load balancer). Check admin / observability for rate limit logs.
Related
- Integration tools — PicGo / Moraya / Typora / Obsidian setups
- API Reference
- Security overview
- AI Workflows — for Claude / Cursor (uses OAuth, not API Keys)