Skip to main content

Working with this group

Every operation under /me reads or writes only the authenticated caller’s own resources: profile preferences, speed-dial favorites, saved campaign drafts, report history, recommendation drafts, and ring rules. The credential on the request determines the tenant: an API key (dv_live_sk_* or dv_test_sk_*) resolves to the organization that owns the key, while a dashboard session resolves to the organization the signed-in user is currently working in.

First call: the identity probe

GET /api/v1/me is the first call every SDK quick start makes: it proves the credential works and returns the identity, organization id, and plan that every later request acts under. Authorization is role-based, so the response carries the caller’s role on the user object and per organization; there is no per-call scope list to request.
cURL
200

List saved campaign drafts from any SDK

GET /api/v1/me/campaign-drafts returns the caller’s saved AI campaign drafts in data.drafts. The history is capped at 50 drafts, so the full list arrives in one response and there is no cursor to follow; meta carries the correlation fields only. The same call in four styles:
200

Correlating a request

Every response on this page repeats meta.request_id, a server-generated id for exactly one request. Quote it when reporting a failed call or reading your request logs: support and diagnostics resolve it to the same request across services. meta.timestamp is the server time the response was produced.

title: “Worked identity and org-context samples” description: “The startup introspection chain — call GET /me, read identity + tenant + memberships, decide on the caller’s role — plus a worked sweep of the per-user me/* resources (ring rules, favorites, campaign drafts, generated reports) and the authentication failures this probe surfaces first.”

Worked identity and org-context samples

Bootstrap the session, then decide: call GET /api/v1/me at startup before touching any resource operation, read data.user, data.tenant, and data.organizations out of the same envelope, and branch on the caller’s role before you call a write path. Every signed-in client resolves identity through this probe — the dashboard’s org picker and the mobile client both bootstrap from it. Cache the response per session, keep meta.request_id for support correlation, and re-fetch only on org switch or role change.

Worked sequence: dashboard-adjacent operator reads

The me/* GETs below are the per-user state the dashboard piles onto the post-login bootstrap: distinctive-ring rules, speed-dial favorites, saved AI campaign drafts, and generated-report history. Chain them in this order so a mobile or API client can render the operator’s own resources in one sweep; a drafted campaign row travels as one entry of data.drafts[] with the brief, the generated copy, and the target channels.
A drafted campaign row — one entry of data.drafts[] from the third call above (the generated blueprint is null when the row was saved brief-only):
Each sweep is scoped to the signed-in operator only — a leaked row id from another user never resolves. Empty state is an empty array (or data.draft: null on the Recommendations tester), so render your empty-view CTA rather than a table skeleton.

Worked reads — ring rules and favorites

Each per-user read below is the second leg of the worked sequence: the GET the bootstrap chain fires, paired with the envelope it answers. Chain them after GET /me resolves the caller.

Ring rules — the caller’s distinctive-ring rules

GET /api/v1/me/ring-rules
Distinctive-ring rules map an inbound-caller match to the ring pattern the softphone plays; data.patterns is the picker catalog the dashboard renders for the rule editor. Request
Response

Favorites — one-tap dial targets

GET /api/v1/me/favorites
Speed-dial favorites ordered by sort_order then creation time — the dialpad’s one-tap call surface. label is null when the caller never named the target. Request
Response

Campaign drafts — the AI Studio draft history

GET /api/v1/me/campaign-drafts
One entry per saved AI Studio draft; draft is null when the row was saved brief-only, so gate the preview panel on its presence. Request
Response

Read the authenticated caller

GET /api/v1/me
Returns the caller’s identity, the active tenant, and every organization the caller belongs to in one envelope. Request
Response
The three data keys always arrive together: user carries the identity fields above plus the caller’s per-user preferences (softphone layout, voicemail-to-email opt-in, inbox signature), tenant is the organization context every subsequent request runs in, and organizations lists every membership with the caller’s role in each.

Preflight: decide on the caller’s role

Branch on data.user.role / membership role before calling a write path
The identity probe answers three startup questions in one call: who is calling (data.user), which organization the key is bound to (data.tenant.slug), and whether the caller’s role in that org justifies the call you are about to make (data.organizations[].role). A workspace-scoped key resolves to exactly one tenant; multi-org dashboard (Clerk-session) callers receive every membership in data.organizations. An admin-of-one-org membership appears alongside the rest — treat the per-org role as the decision input and the org-scoped endpoint’s own verdict as authoritative.
The decision table for the role you read: A 200 on /me tells you the credential is good — it never tells you a write will succeed. Read the role, decide, and treat the operation’s own 403 as the authoritative verdict when the table disagrees with your role map.

Org-context and capability probes in the me surface

The me surface resolves the caller’s active organization context and capability footprint. Use these probes to hide unsupported actions, decide whether an organization area should surface in the dashboard, and map each caller to the operations they can drive. The GET /me envelope is the org-context probe: it resolves the active tenant and memberships in one round trip. Request
Response
The data.tenant block carries the active organization footprint (id, name, slug, plan) every subsequent request runs against; data.organizations lists every membership with the caller’s role. Prefer this single envelope over a second call — there is no separate GET /me/org or GET /me/memberships path; the memberships guard lives on this envelope.

Membership / role guard

Resolve the caller’s membership in the active organization before any write path and gate on its role — the same guard the dashboard applies when opening an organization area.
The guard answers “does this caller belong to the active org, and with what role” without a dedicated memberships call. Membership role is the only role input the me surface honors — org-scoped endpoints refuse operations the role does not carry.

Feature-gate probe — predictive activation schedule

GET /api/v1/me/predictive-activation-schedule
GET /api/v1/me/predictive-activation-schedule is the capability probe for the predictive-models panel: it returns the caller’s per-model auto-activation schedule intent, or data.schedule: null when no schedule is saved. SDK helpers use null to hide the panel and non-null to render it, so the probe doubles as the feature gate. Request
Response with a saved schedule
Response with no schedule saved
Build the features map your SDK helpers consume from the probe: featuresEnabled.predictiveSchedule = data.schedule !== null, and each model key that survives the server registry (churn_propensity, conversion_intent, lifetime_value, engagement_fatigue) marks its panel as enabled. A PUT on the same path toggles the intent — treat the read as the probe and the write as the setter, never cache the write’s response as the gate.

Chain — authenticated caller → memberships → capabilities

The standard bootstrap chain the me surface supports: (1) call GET /me to resolve identity, (2) guard on data.organizations membership for the active organization, and (3) probe GET /me/predictive-activation-schedule so unsupported actions stay hidden.
Each probe is idempotent, so cache the envelope per session and re-fetch only on org switch or role change. Treat the chain as the only sequence that establishes org context before touching a resource operation.

Errors worth branching on

This probe is where an invalid credential surfaces first — an integration that skips the bootstrap re-discovers the same 401 on every later call. The mechanics of the envelope (error.code / message / status / details, the meta.docs_url trail) are owned by the error handling guide; only the /me-specific branch is hers.

401 — the credential itself fails

A 401 on this probe means the X-API-Key header value itself fails — it never means the identity payload moved. The failure precedes tenant resolution, so there is no data envelope to fall back to. Read meta.docs_url for the code’s remedy anchor; rotate the key or mint a new one, because retrying the same header re-fails identically.

Retry matrix

The platform-wide retry-vs-terminal decision table lives in the error handling guide.

Worked response reference — every operation on this page

The sections above teach the bootstrap chain; this reference supplies the populated response body for every remaining operation on the page. Every /me read returns only the authenticated caller’s own resources: drafts, reports, favorites, and ring rules are stored per user, and a row id leaked from another user never resolves here. The API key on X-API-Key determines the tenant, so every body below is already scoped to one organization.

The identity probe — org id, plan, user id, roles

GET /api/v1/me is the first call in the SDK quick start: one round trip that proves the key works and returns the org id (data.tenant.id), the plan (data.tenant.plan), the user id (data.user.id), the workspace role (data.user.role), and the caller’s per-organization roles (data.organizations[].role). There is no scopes array on a key: the key binds to one tenant, and authorization rides on those roles, which is exactly what the preflight above branches on.
GET /api/v1/me
Request
Response

Campaign drafts — list and replace

GET /api/v1/me/campaign-drafts
The AI Studio draft history, stored per caller. data.drafts is the list the draft picker renders; draft is null for brief-only rows, so gate any preview panel on its presence. Request — the same call in cURL, the typed Node SDK’s escape hatch, Python, and Go:
Response
The list is bounded and replaced whole on write; PUT re-validates every row and answers the same rows back:
PUT /api/v1/me/campaign-drafts

Generated reports — the Insights run history

GET /api/v1/me/generated-reports
Metadata for the caller’s generated reports, most recent first. Row-level report content is never persisted server-side, so each entry carries the column layout the report grid renders, not the rows themselves. Request
Response
PUT replaces the caller’s history with the sanitized list and echoes it back:
PUT /api/v1/me/generated-reports

Recommendations draft — the tester’s saved inputs

GET /api/v1/me/recommendations-draft
The Recommendations tester’s editable input set: product catalog, observed signals, and scoring weights. data.draft is null until the caller saves a first configuration, so seed your defaults on null. Request
Response
PUT saves the full tester state and answers it back with updated: true:
PUT /api/v1/me/recommendations-draft

Ring rules — replace the caller’s rules

PUT /api/v1/me/ring-rules
PUT replaces the caller’s full rules array (validated and deduplicated server-side) and echoes the stored rules back with the same shapes the GET above documents:

Favorites — create, relabel, delete

POST /api/v1/me/favorites
A successful pin answers 201 with the created row; the dialpad Favorites tab renders it immediately:
PATCH /api/v1/me/favorites/{id}
Relabel or reorder one pin; the answer carries the updated row:
DELETE /api/v1/me/favorites/{id}
A delete that belongs to the caller answers deleted: true with the removed id:

Correlating with support — meta.request_id

Every response on this page, 200s and errors alike, carries meta.request_id. Quote that value in a support ticket or a bug report and it resolves to the exact request trace on our side; it is the correlation key between your logs and ours. In sandbox runs (X-Test-Mode: true or a dv_test_sk_* key) the envelope additionally carries meta.test_mode: true, so a pasted body is self-identifying as sandbox traffic.