Get from nothing to your first successful V3 call. Everything else — the full reference, error registry, PII rules — is in the Business Management v3 page; you should not need it to finish this one.
V3 is a contract preview. The endpoints are not deployed yet, so the calls below do not return data today. The shapes are stable enough to build against. The initial production release, including the core business flows, is planned for October 2026; additional operations become
availablein subsequent iterations.Working with v1 or v2 instead? Those use a partner token and a combined
Bearer <partner>, User <user>header — see How to Get API Keys (v1 and v2). V3 does not accept that header.
This one choice decides everything that follows.
| You are building | Credential | Flow |
|---|---|---|
| Your own script for your own business — internal automation, a private MCP server, a report job | Restricted key, created in your Altegio account | None. The key is the credential |
| A product other businesses install — a marketplace app with a backend that runs unattended | Marketplace application + confidential OAuth client (client_id + client_secret) | Client Credentials |
| An agent or desktop/CLI tool acting as a specific employee — Claude, Cursor, Codex, your own native app | OAuth public client — self-registered via DCR/CIMD, or pre-registered | Authorization Code + PKCE |
Two things that surprise people:
- Registering an OAuth client grants you nothing. It creates an identity, not access. Data still requires either a business installing your app, or a person consenting.
- Public clients cannot use Client Credentials. If you self-registered through DCR, you act on behalf of a user — there is no unattended path without a marketplace application.
Restricted key — create it in your account. It is shown once; store it like a password. Choose its scopes and its Locations at creation time.
Marketplace app — register the application, then create a confidential OAuth client for it. You get client_id and client_secret; the secret is shown once and can be rotated with overlap.
Agent / native client — either pre-register and receive a client_id, or self-register:
curl -X POST https://api.alteg.io/oauth/register \
-H 'Content-Type: application/json' \
-d '{
"client_name": "Example MCP Host",
"redirect_uris": ["http://127.0.0.1/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none"
}'Loopback redirects are accepted for native and CLI clients and the port is dynamic — you do not register every port you might bind. localhost is not accepted; use the literal 127.0.0.1 or [::1].
Restricted key — skip this step. The key is sent directly as the Bearer credential.
Marketplace backend. You need the location_id you are acting in: you receive it when the business installs your app, as salon_id on your registration redirect. One token is bound to one Location — an app installed in twenty Locations requests twenty tokens.
curl -X POST https://api.alteg.io/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials \
-d location_id=777 \
-d 'scope=clients:read appointments:read'No refresh token comes back — request a new access token when the 15-minute one expires.
Agent acting as an employee. Send the user to GET /oauth/authorize with PKCE, let them log in and pick which Locations you may touch, then exchange the code:
curl -X POST https://api.alteg.io/oauth/token \
-d grant_type=authorization_code \
-d client_id="$CLIENT_ID" \
-d code="$CODE" \
-d code_verifier="$VERIFIER" \
-d redirect_uri=http://127.0.0.1:53682/callbackThis flow returns a rotating refresh token. Each use rotates it; replaying an old one kills the whole family, so always store the newest.
curl https://api.alteg.io/oauth/accessible-resources \
-H "Authorization: Bearer $ACCESS_TOKEN"Returns the Locations and chains this token can act in, with the scopes granted on each. Use it to learn which location_id to put in a path — it describes the token you already hold, so it is a check, not a way to discover your first Location.
Resource paths sit under /api/v3. OAuth and discovery stay on the host root (no /api/v3).
curl "https://api.alteg.io/api/v3/locations/777/clients?limit=25" \
-H "Authorization: Bearer $ACCESS_TOKEN"Every resource lives under a Location. Lists are cursor-paginated: pass the returned next_cursor back as cursor.
Errors are application/problem+json with a stable code — branch on that, never on the message:
{
"type": "https://developers.alteg.io/problems/missing-scope",
"title": "Missing scope",
"status": 403,
"code": "missing_scope",
"detail": "The token does not carry clients:read.",
"instance": "urn:altegio:request:req_a1b2"
}404 on a Location means "not yours or not there" — the two are deliberately indistinguishable, so do not treat it as "deleted".
Agent host (Codex, Cursor, Claude). Self-register → client_id, no secret · Authorization Code + PKCE with a 127.0.0.1 redirect · the employee picks Locations on the consent screen · call accessible-resources to see what they picked · then act. Rotate the refresh token on every use.
Personal server-to-server script. Create a restricted key in your account, scoped to the Locations you need · send it as Authorization: Bearer <key> · that is the whole setup. No OAuth, no token endpoint, no refresh.
- No account-wide token. Every marketplace Client Credentials token is bound to one Location. User-delegated tokens and restricted keys may cover multiple Locations and chains — call
GET /oauth/accessible-resourcesto inspect the effective grants. - No refresh for marketplace backends. Re-authenticate with your client credentials instead.
client_idis not an application id. The word "client" also means the business's customer in/clients— the OAuth one is always written asclient_idand looks likealtg_oauth_…or a CIMD URL.- Scopes differ per credential class. Client Credentials cannot be granted chain-wide scopes,
locations:createorteam_members:manage_access; restricted keys also cannot useteam_members:manage_accessin the first iteration. Requesting an unavailable scope fails withinvalid_scope/missing_scope. Authorization Code may holdteam_members:manage_accesswhen the business grants it. - Resource base is
/api/v3. Example:https://api.alteg.io/api/v3/locations/{location_id}/…. Token, register, revoke, andaccessible-resourcesstay athttps://api.alteg.io/oauth/….