OAuth Integration
First obtain the client credentials and register a Redirect URI, then set the permissions. Keep Client Secret only on the server.
Authorization request
Open https://senler.io/oauth/authorize in the browser with these parameters:
response_type=code, the only supported response type;client_id, the application's Client ID;redirect_uri, an exact registered address;subject=project|user, the access scenario;projectis used when omitted;project_id, an optional preselected project only forsubject=project;scope, an optional set ofcan_*permissions in selected mode orproject_access/user_accessin dynamic mode;state, a random one-time value stored by the integration until the user returns.
Example project authorization with project selection in Senler AI:
https://senler.io/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fexample.com%2Foauth%2Fcallback&subject=project&scope=project_access&state=RANDOM_STATE
For the user scenario, replace subject=project with subject=user, use the matching scope, and do not add project_id.
After approval, Senler AI returns code and the original state to the Redirect URI. After denial, it returns error=access_denied, error_description, and state. The integration server must compare the returned state with the stored value. The code is valid for 10 minutes and can be used only once.
Exchanging the code for tokens
Send POST https://api.senler.io/api/apps/oauth/token as application/x-www-form-urlencoded or JSON. Client ID and Client Secret can be passed through HTTP Basic or body fields, but not as two conflicting values.
curl -X POST https://api.senler.io/api/apps/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://example.com/oauth/callback'
The response contains access_token, refresh_token, token_type=Bearer, expires_in, scope, and subject. It also returns project_id for subject=project or user_id for subject=user. Use the access token as Authorization: Bearer ... and rely on expires_in instead of assuming a lifetime.
Refreshing tokens
To refresh, send grant_type=refresh_token and the current refresh_token to the same endpoint, authenticating the OAuth client again.
curl -X POST https://api.senler.io/api/apps/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'
After a successful request, the previous refresh token is revoked and the response contains a new token pair. Store both new values before the next refresh.
Revoking a user authorization
To disconnect one external client or revoke your own user authorization, open Connected applications in Account settings. Disconnecting a client ends access only for that connection; revoking the user authorization disconnects all of its clients. Client Secret regeneration replaces the OAuth client key, but it does not revoke user access that has already been granted.
Token endpoint errors
The token endpoint returns { "error": "...", "error_description": "..." }:
invalid_requestmeans a required parameter is absent or parameters conflict;invalid_clientmeans Client ID or Client Secret is invalid; the HTTP status is 401;invalid_grantmeans the code or refresh token expired, was already used, was revoked, or was issued to another client;unauthorized_clientmeans the application type does not support OAuth;unsupported_grant_typemeansgrant_typeis not supported.
Start a new authorization after invalid_grant, verify the current Client Secret after invalid_client, and correct other errors using error_description. Do not retry the same request indefinitely.