Me API
GET /me tells a caller who it is: which organization and workspace the credential acts in, which region serves it and the API base URL to call, what kind of credential it is, and the permissions it carries right now. It works with every credential - an API key, a dashboard session, or an OAuth access token - and needs no particular permission, so it is the natural "test connection" call.
All endpoints on this page are relative to the base URL: https://api-eu1.joryio.com/api - see API Overview.
Get the caller
GET /me
curl https://api-eu1.joryio.com/api/me \
-H "Authorization: Bearer jry_live_your_api_key"
Response 200:
{
"organization": { "id": "8f0c2c1e-3b0a-4d2e-9a51-0f6f4d1c2b11", "name": "Acme" },
"workspace": { "id": "1d2e3f40-5a6b-4c7d-8e9f-a0b1c2d3e4f5", "name": "Production" },
"region": "eu1",
"api_base_url": "https://api-eu1.joryio.com/api",
"principal": {
"type": "oauth",
"client_kind": "integration",
"client": "zapier",
"name": "Dana Levi"
},
"scopes": ["events:track", "users:read", "users:write"]
}
| Field | Type | Notes |
|---|---|---|
organization | object | id and name of the organization. |
workspace | object or null | The workspace the credential acts in. An API key and an OAuth token are bound to one workspace; a dashboard session uses the X-Workspace-Id header and gets null without it. |
region | string | The region that holds the data, e.g. eu1. |
api_base_url | string | The REST API base of that region. Call this, not a hard-coded host. |
principal | object | What the credential is - see below. |
scopes | string[] | The permissions this credential can use right now, sorted. |
Principal types
principal.type | Credential | Other fields |
|---|---|---|
api_key | An API key | api_key_id, name (the key's name). scopes are the key's scopes, including the ones they carry (for example canvas:activate carries canvas:enter). |
oauth | An OAuth access token | client_kind (integration - for example Zapier - or mcp, an AI agent), client (zapier for Zapier, otherwise the client's name), and the email and name of the person who connected it. scopes are what was granted AND what that person still holds. |
user | A dashboard session | email, name; scopes are the person's permissions in the workspace. |
OAuth for integrations
Integrations such as Zapier connect with "Sign in with Joryio" (OAuth 2.0 authorization code) instead of a pasted API key. The person picks the workspace and the permissions on a Joryio consent page; the integration then acts as that person, in that workspace, limited to what they allowed and to what they still hold. Integration clients are registered by Joryio - there is no self-service client registration.
The OAuth endpoints are on the region-neutral host connect.joryio.com, which forwards each request to the region that issued the code or token:
| Step | Endpoint |
|---|---|
| Authorize (browser) | GET https://connect.joryio.com/oauth/authorize?response_type=code&client_id=...&redirect_uri=...&scope=...&state=... |
| Token | POST https://connect.joryio.com/oauth/token |
| Revoke | POST https://connect.joryio.com/oauth/revoke |
- Client authentication:
client_secret_basic(HTTP Basic) orclient_secret_post(client_idandclient_secretin the form body). PKCE (S256) is optional and enforced when sent. - Redirect URI: must match one of the client's registered URIs exactly.
- Token response:
access_token,refresh_token,token_type,expires_in,scope, plusapi_base_url(call the API there) andregion. - Access tokens last one hour. An expired one gets
401; refresh and retry. - Refresh tokens rotate on every use and stay valid while the connection is used - they lapse after 180 days without any use. Two refreshes with the same token within 60 seconds (parallel steps) both get the same new pair; a rotated token presented later ends the connection.
- Scopes an integration can ask for:
users:read,pii:view(optional, see below),users:write,events:read,events:track,lists:read,subscriptions:read,segments:read,subscriptions:write,canvas:enter,hooks:manage. - Implied permissions: an OAuth token never gains
users:export,users:mergeorusers:aliasthrough another scope (segments:readandusers:writecarry them for roles and API keys, not for OAuth). Bulk contact export, merging and alias changes stay with roles and API keys. - Personal data (
pii:view, optional): without it an integration gets contact IDs only -GET /usersand the other contact reads returnemail,phoneandexternalIdasnulland mask attributes marked as personal data (and names), and webhook deliveries carrycontact.idonly. With it, they carry the contact's email, phone and External ID. It takes effect only while the person who connected also holdspii:viewin the workspace, checked on every request and delivery: losing it masks the next one. The consent page shows it as "See contacts' email address and phone number", unticked by default, and only to people who holdpii:view; someone without it is told the app will get contact IDs only, and can still connect. No other scope -users:readincluded - grants it. AI agents (MCP) cannot ask for it. - Disconnect: the person removes the connection under Settings > General > Connected apps; every token of the connection stops working at once.