Authentication
Learn how to authenticate with the Pictograph API using API keys.
The Pictograph API uses API keys for authentication. API keys are scoped to your organization and can have different permission levels.
API Key Format
API keys follow this format: pk_live_ followed by 32 random characters.
pk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 Authentication Methods
Include your API key in every request using the X-API-Key header:
from pictograph import Client
import os
# From environment variable (recommended for production)
client = Client(api_key=os.environ["PICTOGRAPH_API_KEY"])
# Direct API key (for testing only)
client = Client(api_key="{{API_KEY}}") import requests
response = requests.get(
"https://api.pictograph.io/api/v1/developer/datasets/",
headers={"X-API-Key": "{{API_KEY}}"}
) curl https://api.pictograph.io/api/v1/developer/datasets/ \
-H "X-API-Key: {{API_KEY}}" const response = await fetch(
"https://api.pictograph.io/api/v1/developer/datasets/",
{
headers: { "X-API-Key": "{{API_KEY}}" }
}
);
const datasets = await response.json(); req, _ := http.NewRequest("GET",
"https://api.pictograph.io/api/v1/developer/datasets/", nil)
req.Header.Set("X-API-Key", "{{API_KEY}}")
resp, _ := http.DefaultClient.Do(req) API Key Roles
API keys can have one of four roles:
| Role | Permissions |
|---|---|
viewer | Read-only access to datasets, images, and annotations |
member | Read + write access (upload images, create annotations) |
admin | Full access including delete operations and exports |
owner | Full access including API key management |
Permissions Matrix
Detailed breakdown of what each role can do:
| Operation | Viewer | Member | Admin | Owner |
|---|---|---|---|---|
| List datasets | ✓ | ✓ | ✓ | ✓ |
| Get dataset details | ✓ | ✓ | ✓ | ✓ |
| Download images | ✓ | ✓ | ✓ | ✓ |
| Get annotations | ✓ | ✓ | ✓ | ✓ |
| Upload images | — | ✓ | ✓ | ✓ |
| Save annotations | — | ✓ | ✓ | ✓ |
| Create exports | — | — | ✓ | ✓ |
| Delete images | — | — | ✓ | ✓ |
| Delete exports | — | — | ✓ | ✓ |
| Manage API keys | — | — | — | ✓ |
API Key Lifecycle
Follow this workflow to manage your API keys securely:
1. Create
Generate a new key with the minimum required permissions. Give it a descriptive name like "CI Pipeline" or "Training Scripts" so you can identify its purpose later.
2. Store Securely
- Save the key immediately—it's only shown once
- Use a secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.)
- For local development, use environment variables or
.envfiles (added to.gitignore)
3. Use
Include the key in all API requests via the X-API-Key header.
Monitor usage in Settings → API Keys to track activity.
4. Rotate
Rotate keys periodically (every 90 days recommended) or immediately if you suspect compromise:
- Create a new key with the same permissions
- Update your applications to use the new key
- Verify the new key works correctly
- Revoke the old key
5. Revoke
Immediately revoke keys that are no longer needed, have been exposed, or belong to team members who have left the organization. Revocation takes effect immediately.
Managing API Keys
Web Interface
- Go to Settings → API Keys in the app
- Click Generate New Key
- Select a name and role
- Copy the key immediately (it won't be shown again)
Programmatically
from pictograph import Client
client = Client(api_key="{{API_KEY}}")
# List existing API keys (requires owner role)
keys = client.api_keys.list(organization_id="{{ORG_ID}}")
# Create a new API key
new_key = client.api_keys.create(
organization_id="{{ORG_ID}}",
name="CI Pipeline",
role="member"
)
print(f"New key: {new_key['key']}") # Only shown once!
# Revoke an API key
client.api_keys.delete(key_id="key-uuid") import requests
# List existing API keys
response = requests.get(
"https://api.pictograph.io/api/v1/api-keys/",
headers={"X-API-Key": "{{API_KEY}}"},
params={"organization_id": "{{ORG_ID}}"}
)
keys = response.json()["api_keys"]
# Create a new API key
response = requests.post(
"https://api.pictograph.io/api/v1/api-keys/",
headers={
"X-API-Key": "{{API_KEY}}",
"Content-Type": "application/json"
},
json={
"organization_id": "{{ORG_ID}}",
"name": "CI Pipeline",
"role": "member"
}
)
new_key = response.json()
print(f"New key: {new_key['key']}") # Only shown once!
# Revoke an API key
requests.delete(
"https://api.pictograph.io/api/v1/api-keys/key-uuid",
headers={"X-API-Key": "{{API_KEY}}"}
) # List existing API keys
curl "https://api.pictograph.io/api/v1/api-keys/?organization_id={{ORG_ID}}" \
-H "X-API-Key: {{API_KEY}}"
# Create a new API key
curl -X POST "https://api.pictograph.io/api/v1/api-keys/" \
-H "X-API-Key: {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"organization_id": "{{ORG_ID}}",
"name": "CI Pipeline",
"role": "member"
}'
# Revoke an API key
curl -X DELETE "https://api.pictograph.io/api/v1/api-keys/key-uuid" \
-H "X-API-Key: {{API_KEY}}" // List existing API keys
const listResponse = await fetch(
"https://api.pictograph.io/api/v1/api-keys/?organization_id={{ORG_ID}}",
{ headers: { "X-API-Key": "{{API_KEY}}" } }
);
const { api_keys } = await listResponse.json();
// Create a new API key
const createResponse = await fetch(
"https://api.pictograph.io/api/v1/api-keys/",
{
method: "POST",
headers: {
"X-API-Key": "{{API_KEY}}",
"Content-Type": "application/json"
},
body: JSON.stringify({
organization_id: "{{ORG_ID}}",
name: "CI Pipeline",
role: "member"
})
}
);
const newKey = await createResponse.json();
console.log("New key:", newKey.key); // Only shown once!
// Revoke an API key
await fetch(
"https://api.pictograph.io/api/v1/api-keys/key-uuid",
{
method: "DELETE",
headers: { "X-API-Key": "{{API_KEY}}" }
}
); Security Best Practices
- Never commit API keys to version control
- Use environment variables for production deployments
- Rotate keys regularly and revoke unused keys
- Use minimal permissions - give keys only the access they need
- Monitor usage - check last used dates in the dashboard
Environment Variables
# Set environment variable
export PICTOGRAPH_API_KEY="pk_live_your_key_here"
# Use in your application
python my_script.py # .env file (add to .gitignore!)
PICTOGRAPH_API_KEY=pk_live_your_key_here import os
from pictograph import Client
# Load from environment
client = Client(api_key=os.environ["PICTOGRAPH_API_KEY"])
# Or using python-dotenv
from dotenv import load_dotenv
load_dotenv()
client = Client(api_key=os.environ["PICTOGRAPH_API_KEY"]) // Load from environment
const apiKey = process.env.PICTOGRAPH_API_KEY;
// Or using dotenv
require('dotenv').config();
const apiKey = process.env.PICTOGRAPH_API_KEY; Error Responses
| Status | Meaning |
|---|---|
401 | Invalid or missing API key |
403 | Valid key but insufficient permissions |
429 | Rate limit exceeded (see Rate Limits) |
Error Response Format
{
"error": {
"code": "invalid_api_key",
"message": "The provided API key is invalid or has been revoked."
}
} Handling Authentication Errors
from pictograph import Client
from pictograph.exceptions import AuthenticationError
try:
client = Client(api_key="invalid_key")
datasets = client.datasets.list()
except AuthenticationError as e:
print(f"Authentication failed: {e.message}")
# Handle: check API key, regenerate if needed import requests
response = requests.get(
"https://api.pictograph.io/api/v1/developer/datasets/",
headers={"X-API-Key": "invalid_key"}
)
if response.status_code == 401:
error = response.json()["error"]
print(f"Authentication failed: {error['message']}") const response = await fetch(
"https://api.pictograph.io/api/v1/developer/datasets/",
{ headers: { "X-API-Key": "invalid_key" } }
);
if (response.status === 401) {
const { error } = await response.json();
console.log("Authentication failed:", error.message);
}