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.

TEXT
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 .env files (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:

  1. Create a new key with the same permissions
  2. Update your applications to use the new key
  3. Verify the new key works correctly
  4. 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.

Important: Once a key is revoked, any applications using it will immediately lose access. Plan key rotations carefully to avoid service disruptions.

Managing API Keys

Web Interface

  1. Go to Settings → API Keys in the app
  2. Click Generate New Key
  3. Select a name and role
  4. 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

JSON
{
  "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);
}
Copied to clipboard