{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-en/b2b-v3/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Quickstart","description":"Official Altegio API documentation for integrating online booking, CRM, scheduling, POS, and business management features into your applications.","siteUrl":"https://developer.alteg.io","lang":"en","keywords":["Altegio API","REST API","online booking API","appointment scheduling API","business management API","CRM integration","POS API"],"image":"/assets/og-image.5c9c342f49e4dd72b96f7a0faf29bb71fab6ff06bbf97cf4b230d6fcc0abcdb3.e746d8a7.jpg","meta":[{"name":"author","content":"Altegio"},{"name":"twitter:card","content":"summary_large_image"},{"name":"twitter:site","content":"@altegio"}]},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"quickstart","__idx":0},"children":["Quickstart"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Get from nothing to your first successful V3 call. Everything else — the full reference, error registry, PII rules — is in the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/en/b2b-v3/openapi"},"children":["Business Management v3"]}," page; you should not need it to finish this one."]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["October 2026"]},"; additional operations become ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["available"]}," in subsequent iterations."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Working with ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["v1 or v2"]}," instead? Those use a partner token and a combined ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Bearer <partner>, User <user>"]}," header — see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/en/get-api-key"},"children":["How to Get API Keys (v1 and v2)"]},". V3 does not accept that header."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"1-pick-your-integration-type","__idx":1},"children":["1. Pick your integration type"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This one choice decides everything that follows."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"You are building"},"children":["You are building"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Credential"},"children":["Credential"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Flow"},"children":["Flow"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Your own script for your own business"]}," — internal automation, a private MCP server, a report job"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Restricted key"]},", created in your Altegio account"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["None. The key ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["is"]}," the credential"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["A product other businesses install"]}," — a marketplace app with a backend that runs unattended"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Marketplace application + ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["confidential"]}," OAuth client (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}," + ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]},")"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Client Credentials"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["An agent or desktop/CLI tool acting as a specific employee"]}," — Claude, Cursor, Codex, your own native app"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["OAuth ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["public"]}," client — self-registered via DCR/CIMD, or pre-registered"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Authorization Code + PKCE"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Two things that surprise people:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"2-get-your-credential","__idx":2},"children":["2. Get your credential"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Marketplace app"]}," — register the application, then create a confidential OAuth client for it. You get ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]},"; the secret is shown once and can be rotated with overlap."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Agent / native client"]}," — either pre-register and receive a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]},", or self-register:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST https://api.alteg.io/oauth/register \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"client_name\": \"Example MCP Host\",\n    \"redirect_uris\": [\"http://127.0.0.1/callback\"],\n    \"grant_types\": [\"authorization_code\", \"refresh_token\"],\n    \"token_endpoint_auth_method\": \"none\"\n  }'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Loopback redirects are accepted for native and CLI clients and the port is dynamic — you do not register every port you might bind. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["localhost"]}," is not accepted; use the literal ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["127.0.0.1"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["[::1]"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"3-get-a-token","__idx":3},"children":["3. Get a token"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Restricted key — skip this step."]}," The key is sent directly as the Bearer credential."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Marketplace backend."]}," You need the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["location_id"]}," you are acting in: you receive it when the business installs your app, as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["salon_id"]}," on your registration redirect. One token is bound to ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["one"]}," Location — an app installed in twenty Locations requests twenty tokens."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST https://api.alteg.io/oauth/token \\\n  -u \"$CLIENT_ID:$CLIENT_SECRET\" \\\n  -d grant_type=client_credentials \\\n  -d location_id=777 \\\n  -d 'scope=clients:read appointments:read'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["No refresh token comes back — request a new access token when the 15-minute one expires."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Agent acting as an employee."]}," Send the user to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /oauth/authorize"]}," with PKCE, let them log in and pick which Locations you may touch, then exchange the code:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST https://api.alteg.io/oauth/token \\\n  -d grant_type=authorization_code \\\n  -d client_id=\"$CLIENT_ID\" \\\n  -d code=\"$CODE\" \\\n  -d code_verifier=\"$VERIFIER\" \\\n  -d redirect_uri=http://127.0.0.1:53682/callback\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This flow returns a rotating refresh token. Each use rotates it; replaying an old one kills the whole family, so always store the newest."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"4-see-what-you-can-reach","__idx":4},"children":["4. See what you can reach"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl https://api.alteg.io/oauth/accessible-resources \\\n  -H \"Authorization: Bearer $ACCESS_TOKEN\"\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Returns the Locations and chains this token can act in, with the scopes granted on each. Use it to learn which ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["location_id"]}," to put in a path — it describes the token you already hold, so it is a ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["check"]},", not a way to discover your first Location."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"5-make-the-call","__idx":5},"children":["5. Make the call"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Resource paths sit under ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/api/v3"]}]},". OAuth and discovery stay on the host root (no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/api/v3"]},")."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl \"https://api.alteg.io/api/v3/locations/777/clients?limit=25\" \\\n  -H \"Authorization: Bearer $ACCESS_TOKEN\"\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every resource lives under a Location. Lists are cursor-paginated: pass the returned ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["next_cursor"]}," back as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["cursor"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Errors are ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["application/problem+json"]}," with a stable ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["code"]}," — branch on that, never on the message:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"type\": \"https://developers.alteg.io/problems/missing-scope\",\n  \"title\": \"Missing scope\",\n  \"status\": 403,\n  \"code\": \"missing_scope\",\n  \"detail\": \"The token does not carry clients:read.\",\n  \"instance\": \"urn:altegio:request:req_a1b2\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]}," on a Location means \"not yours or not there\" — the two are deliberately indistinguishable, so do not treat it as \"deleted\"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"two-complete-examples","__idx":6},"children":["Two complete examples"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Agent host (Codex, Cursor, Claude)."]}," Self-register → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]},", no secret · Authorization Code + PKCE with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["127.0.0.1"]}," redirect · the employee picks Locations on the consent screen · call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["accessible-resources"]}," to see what they picked · then act. Rotate the refresh token on every use."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Personal server-to-server script."]}," Create a restricted key in your account, scoped to the Locations you need · send it as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization: Bearer <key>"]}," · that is the whole setup. No OAuth, no token endpoint, no refresh."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"what-not-to-expect","__idx":7},"children":["What not to expect"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /oauth/accessible-resources"]}," to inspect the effective grants."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["No refresh for marketplace backends."]}," Re-authenticate with your client credentials instead."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}," is not an application id."]}," The word \"client\" also means the business's customer in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/clients"]}," — the OAuth one is always written as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}," and looks like ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["altg_oauth_…"]}," or a CIMD URL."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Scopes differ per credential class."]}," Client Credentials cannot be granted chain-wide scopes, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["locations:create"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["team_members:manage_access"]},"; restricted keys also cannot use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["team_members:manage_access"]}," in the first iteration. Requesting an unavailable scope fails with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invalid_scope"]},"/",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["missing_scope"]},". Authorization Code may hold ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["team_members:manage_access"]}," when the business grants it."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Resource base is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/api/v3"]},"."]}," Example: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://api.alteg.io/api/v3/locations/{location_id}/…"]},". Token, register, revoke, and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["accessible-resources"]}," stay at ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://api.alteg.io/oauth/…"]},"."]}]}]},"headings":[{"value":"Quickstart","id":"quickstart","depth":1},{"value":"1. Pick your integration type","id":"1-pick-your-integration-type","depth":2},{"value":"2. Get your credential","id":"2-get-your-credential","depth":2},{"value":"3. Get a token","id":"3-get-a-token","depth":2},{"value":"4. See what you can reach","id":"4-see-what-you-can-reach","depth":2},{"value":"5. Make the call","id":"5-make-the-call","depth":2},{"value":"Two complete examples","id":"two-complete-examples","depth":2},{"value":"What not to expect","id":"what-not-to-expect","depth":2}],"frontmatter":{"title":"V3 Quickstart","rightSidebar":false,"seo":{"title":"Quickstart"}},"lastModified":"2026-09-03T07:22:56.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/en/b2b-v3/quickstart","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}