All docs
Start here
API basics
Agent setups
Resources
- Contacts
- Companies
- Lists
- Deals
- Tasks
- Notes
- Fields
- Quotes
- Stage Checklist Pipelines
- Sequences
- Sequence Lifecycle
- Inbox
- Meetings
- Appointments Management
- Voice & Dialer
- Skills (LLM + API)
- Workflows
- GTM Campaigns
- GTM Context
- GTM Knowledge Base
- Launch Helpers
- Landing Pages
- Intent & Signals
- Search
- Enrichment
- Assert / Upsert
- Agency Keys & Cross-Org Targeting
- CRM Syncs
- Audience Syncs
- Destinations
- Snippet
- Functions
Data pipeline
Webhooks
What's new
Restricted Keys (Scopes)
Limit an API key to specific resource:action scopes
Restrict an API key to a subset of the API with scopes. A key with no scopes is unrestricted (full access) — so every existing key keeps working; scopes are opt-in.
| Scope | Grants |
|---|---|
* | Everything |
contacts:* | Every action on contacts |
contacts:read | Exactly contacts read |
Mint a restricted key
Pass scopes to POST /v1/api-keys. The scopes are stored on the key (authoritative) and returned in the response.
curl
curl -X POST https://be.graph8.com/v1/api-keys \
-H "Authorization: Bearer $G8_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "read-only usage", "scopes": ["usage:read", "contacts:read"]}'
# => { "api_key_id": "...", "api_key_token": "g8_live_...", "scopes": ["usage:read","contacts:read"], ... } Python
import httpx
r = httpx.post(
"https://be.graph8.com/v1/api-keys",
headers={"Authorization": f"Bearer {api_key}"},
json={"name": "read-only usage", "scopes": ["usage:read", "contacts:read"]},
) TypeScript
await fetch("https://be.graph8.com/v1/api-keys", {
method: "POST",
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
body: JSON.stringify({ name: "read-only usage", scopes: ["usage:read", "contacts:read"] }),
}); Enforcement
A request to an endpoint whose required scope the key lacks returns 403 with { "type": "forbidden", "code": "403", ... }. An unscoped key passes every check.