Agency Keys & Cross-Org Targeting
An agency is an org that manages a portfolio of client orgs linked in graph8 as parent → child. An agency can mint a single agency-scoped API key and use it to operate any of its client orgs through the entire Developer API — contacts, sequences, dialer, workflows, appointments, deals, everything — without minting one key per client.
Mint an Agency Key
POST /api-keys
Create an agency-scoped API key on the agency (parent) org by passing is_agency: true in the request body.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable label for the key |
is_agency | boolean | No | Set true to mint an agency-scoped key. Omit or set false for a normal key |
Example
curl -X POST "https://be.graph8.com/api/v1/api-keys" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "CIENCE agency ops", "is_agency": true }'Response
{ "data": { "id": "key_abc123", "name": "CIENCE agency ops", "is_agency": true, "token": "sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }}Errors
| Status | Meaning |
|---|---|
400 | Org is not a recognized agency (no linked client orgs, not flagged is_agency) |
403 | Caller lacks API-key admin permission |
Cross-Org Targeting — X-Target-Org-Id
Once you have an agency key, send it with the X-Target-Org-Id header to act on a specific client org. The request then reads and writes that client org’s data.
Targeting Rules
| Request | Result |
|---|---|
Agency key, no X-Target-Org-Id | 200 — resolves to the agency’s own org |
Agency key + X-Target-Org-Id for an authorized client (case-insensitive) | 200 — operates that client org |
Agency key + X-Target-Org-Id set to the agency’s own org ID | 200 — operates the agency org |
Agency key + X-Target-Org-Id for an org outside the agency’s authorized set | 403 — not authorized for that target |
Normal key + X-Target-Org-Id | Header ignored — resolves to the key’s own org (no error) |
Notes
X-Target-Org-Idis honored on the Developer API (/api/v1/*) only. It is not used by in-app or customer-hub hybrid endpoints, which keep single-org semantics.X-Target-Org-Idis distinct fromX-Org-Id.X-Org-Idremains a same-org safety guard;X-Target-Org-Idis the agency selector. Do not conflate them. For an agency key,X-Org-Id(if sent) still checks against the agency’s own org, independent of anyX-Target-Org-Id.- The target is always clamped against the agency’s live authorized client set — a caller-supplied value can only select within that set, never widen it.
- Billing: credit-consuming actions performed in a client org are charged to that client org, not the agency.
- Cross-org writes are supported, with one exception: destructive marketplace operations (for example, approving an SDR invoice that fires a Stripe charge) still require a personal admin key and are refused for agency machine keys.
Example
# List contacts in a specific client orgcurl "https://be.graph8.com/api/v1/contacts" \ -H "Authorization: Bearer $AGENCY_KEY" \ -H "X-Target-Org-Id: org_client123"
# Create a contact in a client orgcurl -X POST "https://be.graph8.com/api/v1/contacts" \ -H "Authorization: Bearer $AGENCY_KEY" \ -H "X-Target-Org-Id: org_client123" \ -H "Content-Type: application/json" \ -d '{ "list_id": 5, "first_name": "Jane", "last_name": "Smith", "work_email": "[email protected]" }'Get Agency Credential Info
GET /agency/me
Describe the agency credential associated with the current API key. Returns metadata about the agency org and the number of client orgs the key can target.
Example
curl "https://be.graph8.com/api/v1/agency/me" \ -H "Authorization: Bearer $AGENCY_KEY"Response
{ "data": { "agency_org_id": "org_agency123", "agency_org_name": "CIENCE", "is_agency": true, "client_count": 52, "target_header": "X-Target-Org-Id" }}| Field | Type | Description |
|---|---|---|
agency_org_id | string | The org ID of the agency itself |
agency_org_name | string | Display name of the agency org |
is_agency | boolean | Always true for a valid agency key |
client_count | integer | Number of client orgs this key is authorized to target |
target_header | string | The header name to use for cross-org targeting (X-Target-Org-Id) |
Errors
| Status | Meaning |
|---|---|
403 | Key is not an agency-scoped key |
List Authorized Client Orgs
GET /agency/clients
List all client orgs this agency key is authorized to target. Each org_id in the response is a valid value for the X-Target-Org-Id header.
Example
curl "https://be.graph8.com/api/v1/agency/clients" \ -H "Authorization: Bearer $AGENCY_KEY"Response
{ "data": [ { "org_id": "org_client123" }, { "org_id": "org_client456" } ]}| Field | Type | Description |
|---|---|---|
org_id | string | Client org ID. Use this value as X-Target-Org-Id to operate that org |
Errors
| Status | Meaning |
|---|---|
403 | Key is not an agency-scoped key |