Skip to navigation

Connect on behalf of a user

Use OAuth 2.0 to connect your application to a Middesk user’s account. For server-to-server access without user sign-in, use client credentials.

Create an OAuth client

1

Register your application

Open the Dashboard’s Credentials page and select Add New Client in the OAuth section. Enter your application’s Redirect URI and, optionally, a Name.

2

Save your credentials

Copy the Client ID and Secret. Keep the secret on your server. The client must allow the authorization_code grant, which is enabled by default.

Redirect users to Middesk

Send the user’s browser to https://app.middesk.com/oauth/authorize with these query parameters:

ParameterDescription
client_idRequired. Your client ID.
redirect_uriRequired. Must exactly match the registered redirect URI.
response_typeRequired. Set to code.
scopeThe requested access scope. Defaults to read_only.
stateA unique, random value for this authorization attempt. Validate it on the callback to prevent CSRF.
Authorization URL
https://app.middesk.com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Fapp.example.com%2Foauth%2Fcallback&response_type=code&scope=read_only&state=YOUR_RANDOM_STATE

Middesk prompts the user to sign in if needed, then redirects back to your application. There is no separate consent screen.

Applications that cannot keep a secret must use a public client and PKCE. Create a public client through POST /v1/oauth_clients using an API key, with confidential: false and your redirect_uri.

Generate a verifier for each authorization attempt using your OAuth library. Add code_challenge (the base64url-encoded SHA-256 hash of the verifier, without padding) and code_challenge_method=S256 to the authorization request. Send the original verifier as code_verifier in the token request. Continue to validate state.

Public clients send client_id without a secret when exchanging codes, refreshing tokens, or revoking access. Confidential clients can also use PKCE and must still authenticate with their credentials.

Handle the redirect

Your callback receives code and the state you sent:

Authorization callback
https://app.example.com/oauth/callback?code=AUTHORIZATION_CODE&state=YOUR_RANDOM_STATE

Reject the callback if state does not match. Authorization codes are single-use and expire after 10 minutes. An invalid scope returns error=invalid_scope and an error_description instead of a code.

Exchange the code for an access token

Send a form-encoded request to https://api.middesk.com/oauth/token:

ParameterDescription
grant_typeRequired. Set to authorization_code.
codeRequired. The code from the callback.
redirect_uriRequired. The same URI used in the authorization request.
client_id, client_secretSend as the HTTP Basic Auth username and password, or in the form body. Public clients omit the secret.
code_verifierRequired if the authorization request included a PKCE challenge; otherwise omit it.
Exchange an authorization code
curl https://api.middesk.com/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode "code=$AUTHORIZATION_CODE" \
--data-urlencode 'redirect_uri=https://app.example.com/oauth/callback'

Token responses

Both OAuth grants return access_token, token_type, scope, and account_id. Expiring tokens also include expires_in in seconds.

Authorization-code token response (default confidential-client settings)
{
"access_token": "EXAMPLE_ACCESS_TOKEN",
"token_type": "bearer",
"scope": "read_only",
"account_id": "2f0d6a2e-3d18-4e8a-b9f1-72c4e6a8d031"
}

For authorization-code clients, refresh tokens are included when refresh_tokens_enabled is true. Without a configured access_token_ttl, confidential-client tokens do not expire automatically and public-client tokens expire after one hour.

Managing token expiry and refresh

To enable expiring tokens and refresh tokens, update the client using an API key:

Enable token expiry and refresh
curl -X PATCH "https://api.middesk.com/v1/oauth_clients/$CLIENT_ID" \
-u "$MIDDESK_API_KEY:" \
-H 'Content-Type: application/json' \
-d '{"access_token_ttl":900,"refresh_tokens_enabled":true}'

access_token_ttl accepts 1–86400 seconds and applies to newly issued tokens. Use a refresh token to get a new access token before the current one expires:

Refresh an access token
curl https://api.middesk.com/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode "refresh_token=$REFRESH_TOKEN"

Replace both stored tokens with the values in the response. Refreshing invalidates the previous access tokens for that authorization, and refresh tokens rotate by default. Avoid concurrent refresh requests or reusing old refresh tokens. If refresh fails with invalid_grant, or refresh tokens are disabled and the access token expires, have the user authorize again.

Make API requests

For either OAuth grant, send the access token in the Authorization header:

Get businesses
curl https://api.middesk.com/v1/businesses \
-H "Authorization: Bearer $ACCESS_TOKEN"

The read_only scope permits GET requests; read_write permits read and write access. OAuth tokens cannot manage API keys or OAuth clients, or create sub-accounts.

Authorization-code requests act as the user who authorized the client, and the account’s IP allowlist applies. Client-credentials requests act on the client’s account and have additional restrictions.

Revoke access

For either OAuth grant, authenticate as the issuing client and send the token to /oauth/revoke:

Revoke an access token
curl https://api.middesk.com/oauth/revoke \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "token=$ACCESS_TOKEN"

With valid client authentication, Middesk returns 200 even if the token is unknown or belongs to another client. Only the issuing client can revoke its tokens. Revoking a user access token invalidates the associated authorization’s access and refresh tokens. Deleting a client invalidates all its tokens.

Get a demo
Contact your account manager or contact sales to inquire about access.

Next steps