OAuth 2.0 for applications

From Planfix

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:

  • https URLs;
  • http URLs only for loopback hosts, such as localhost or 127.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 iss in 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.

Go To