OAuth 2.0 for applications
OAuth 2.0 allows an application to access Planfix on behalf of a user without requesting or storing the user's password.
Planfix uses the Authorization Code flow with mandatory PKCE S256. OAuth can be used to connect to the REST API or the Planfix MCP server.
If you want to connect a ready-made AI client, start with Planfix MCP. If you manage access in your account, see OAuth and MCP applications in an account. Partners and developers of multi-account integrations should see OAuth applications for partners.
Application registration options
| Option | When to use it | Where it works |
|---|---|---|
| Account-owned application | The integration is intended for one account and the client needs a predefined client_id.
|
Only in the account that owns it. |
| Partner-owned application | The same application must connect to multiple customer accounts. | In accounts where it is allowed by the security policy or an administrator. |
| Automatic MCP client registration | The MCP client supports a Client ID Metadata Document (CIMD) or Dynamic Client Registration (DCR). | Registration does not grant account access by itself. The application must still be allowed in the selected account. |
CIMD and DCR are available only for MCP connections. For the REST API, use an account-owned or partner-owned application.
OAuth endpoints
New integrations should use the global endpoints. The account name is not included in these URLs: the user selects an account during authorization.
| Purpose | Address |
|---|---|
| Issuer | https://auth.planfix.com
|
| Authorization | https://auth.planfix.com/oauth/authorize
|
| Token | https://auth.planfix.com/oauth/token
|
| User information | https://auth.planfix.com/oauth/userinfo
|
| Token revocation | https://auth.planfix.com/oauth/revoke
|
| Dynamic MCP client registration | https://auth.planfix.com/oauth/register
|
The authorization server metadata is available at the standard endpoints:
https://auth.planfix.com/.well-known/oauth-authorization-server https://auth.planfix.com/.well-known/openid-configuration
Redirect URIs
A redirect URI must be registered in the application settings. The value sent in an authorization request must match a registered URI.
The following are allowed:
httpsURLs;httpURLs only for loopback hosts, such aslocalhostor127.0.0.1.
The port may be dynamic for a loopback URI, but its scheme, host, path, and query must match. URL fragments and user information in the URL are not allowed.
Access levels
An application receives only the access levels, or scopes, that were allowed in advance. See REST API access levels for the full list.
The requested set must be a subset of the scopes registered for the application. Application scopes do not extend the user's permissions in Planfix: the application can only access data that is available to the employee who connected it.
Managed applications also receive the service scopes userinfo, openid, and email.
User authorization
Generate a code_verifier and its SHA-256 representation, code_challenge, and then open the authorization endpoint in a browser.
REST API example:
GET https://auth.planfix.com/oauth/authorize
?client_id=CLIENT_ID
&redirect_uri=https%3A%2F%2Fexample.com%2Foauth%2Fcallback
&response_type=code
&scope=openid%20email%20task_readonly
&state=RANDOM_STATE
&code_challenge=CODE_CHALLENGE
&code_challenge_method=S256
For MCP, add the resource parameter with the exact MCP server URL:
resource=https%3A%2F%2Fmcp.planfix.com%2Fmcp
| Parameter | Description |
|---|---|
client_id
|
The identifier of a registered application. For CIMD, this is the URL of the client metadata document. |
redirect_uri
|
One of the allowed redirect URIs. |
response_type
|
Must be code.
|
scope
|
The required permissions separated by spaces. This parameter is mandatory for the REST API. An MCP client may omit it, in which case the scopes allowed for the application are used. |
state
|
A random value that protects the request from substitution. The application must validate it after the redirect. |
code_challenge
|
Base64url without padding of the SHA-256 hash of code_verifier.
|
code_challenge_method
|
Only S256 is supported.
|
resource
|
For MCP, the exact URL https://mcp.planfix.com/mcp. Do not send this parameter for the REST API.
|
The user selects an account, signs in, and reviews the requested permissions. An account-owned application opens its owner account directly. If the security policy requires administrator approval, Planfix displays the corresponding step. An administrator can approve the application and connect it in one action.
After successful authorization, Planfix redirects the browser to redirect_uri:
https://example.com/oauth/callback?code=AUTHORIZATION_CODE&state=RANDOM_STATE&iss=https%3A%2F%2Fauth.planfix.com
An authorization code is single-use and remains valid for 10 minutes.
Obtaining tokens
Send a POST request to /oauth/token using application/x-www-form-urlencoded:
grant_type=authorization_code &client_id=CLIENT_ID &code=AUTHORIZATION_CODE &redirect_uri=https%3A%2F%2Fexample.com%2Foauth%2Fcallback &code_verifier=CODE_VERIFIER
For MCP, repeat the resource parameter with the same value used in the authorization request.
A public client sends the request without a secret. A confidential client also authenticates using client_secret_basic or the client_id and client_secret parameters in the request body.
Example response:
{
"access_token": "ACCESS_TOKEN",
"token_type": "bearer",
"expires_in": 86400,
"refresh_token": "REFRESH_TOKEN",
"scope": "openid email task_readonly"
}
For the REST API, the response also contains account_name, account_domain, and account_url. Store these values and use the selected account's URL for REST API requests.
An access token is valid for 24 hours. It is bound to the user, account, application, scopes, and resource. A token issued for MCP cannot be used directly with the REST API, and a REST API token cannot be used with MCP.
Using a token with the REST API
Send the token in the Authorization header:
GET https://account.planfix.com/rest/task/123 Authorization: Bearer ACCESS_TOKEN
Use the account URL returned when the authorization code was exchanged for tokens. Only methods covered by the granted scopes are available. OAuth tokens are subject to the account plan and the standard REST API limits.
User information
The userinfo request requires the openid scope:
GET https://auth.planfix.com/oauth/userinfo Authorization: Bearer ACCESS_TOKEN
Example response when the email scope is present:
{
"sub": "123:user:456",
"email": "user@example.com",
"email_verified": true
}
Global OAuth authorization is available to account employees. Planfix does not issue an id_token; request user data through userinfo instead.
Refreshing tokens
POST https://auth.planfix.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=refresh_token &client_id=CLIENT_ID &refresh_token=REFRESH_TOKEN
For MCP, send the same resource again. A confidential client must authenticate using its secret.
Planfix returns a new access token and a new refresh token. The previous refresh token becomes invalid immediately, so the application must replace the stored value atomically.
Revoking a token
A client can revoke a refresh token through /oauth/revoke:
POST https://auth.planfix.com/oauth/revoke Content-Type: application/x-www-form-urlencoded token=REFRESH_TOKEN &client_id=CLIENT_ID
A user can also remove a connection from the Session management section of their user card. An administrator can revoke a third-party application's approval for the entire account. See OAuth and MCP applications in an account.
Compatibility with existing integrations
Tenant endpoints such as https://account.planfix.com/api/v2/oauth/authorize, /token, and /userinfo continue to work for existing integrations tied to a specific account.
Use the global endpoints for new integrations. They support standard metadata discovery, account selection, and MCP. Do not mix global and tenant endpoints within one OAuth session.
Security recommendations
- Always use PKCE S256 and validate
state. - Use a public client without a secret for mobile, desktop, and browser applications.
- Use a confidential client only when the secret can be stored securely on a server.
- Request the minimum required set of scopes.
- Do not write access tokens, refresh tokens, authorization codes,
code_verifier, or client secrets to logs. - Store refresh tokens and client secrets in encrypted storage.
- Validate
issin the response and accept only the expected Planfix issuer.
Possible errors
| Error | Cause |
|---|---|
invalid_client
|
The client is unknown or disabled, the client secret is incorrect, or the application is not available in the selected account. |
invalid_grant
|
The authorization code or refresh token is invalid, expired, already used, or does not match the client, redirect URI, PKCE data, or resource. |
invalid_scope
|
The request contains a scope that is not allowed for the application. |
invalid_target
|
The resource is unsupported or changed between requests.
|
access_denied
|
The user declined the connection or the account policy does not allow the application. |
HTTP 401, invalid_token
|
The access token is unknown, expired, or revoked. |
HTTP 403, insufficient_scope
|
The token does not contain the scope required for the operation. |