Integrating
Let people sign in with ClikDeploy, and let your app act on their behalf with scoped permission.
ClikDeploy is an OpenID Connect provider — a site other apps can send people to in order to sign them in. That gives you two things. Your app can offer a “Sign in with ClikDeploy” button, and your app can call the ClikDeploy API as that person, with only the permissions they agreed to.
Both use the same setup: register your app once, then run a standard OpenID Connect sign-in. Whether you get API access on top is decided by which permissions you ask for.
ClikDeploy publishes a discovery document — one JSON file, at a fixed URL, listing every endpoint, every permission and every sign-in method the server supports. Point any standard OpenID Connect library at the URL below and it reads that file and configures itself.
issuer
https://clikdeploy.com
That value is the issuer: the base URL of the ClikDeploy you sign in at. Most libraries ask for exactly this one field. If you run ClikDeploy yourself, the issuer is your own origin instead.
If your library wants the document URL rather than the issuer, use either of these — they serve the same file, and libraries differ only in which one they look for.
https://clikdeploy.com/.well-known/openid-configuration https://clikdeploy.com/.well-known/oauth-authorization-server
Go to /oauth/apps while signed in to ClikDeploy and create an application. Four things are asked for.
https, except on localhost, and may not contain a *.A server-side app (called confidential in the OAuth specs) runs on a machine you control, so it can hold a password-like client secret that no user ever sees. Pick this for a web backend.
An SPA, CLI or native app (called public) runs on the user's own device, where any secret you ship can be read out of it. So it gets no secret at all. It proves itself with PKCE instead — a one-time random value your app generates at the start of sign-in and produces again at the end, so a stolen authorization code is useless to anyone else. Every OpenID Connect library does this for you.
A server-side app is shown its client secret once, at creation. It is stored hashed and cannot be shown again — if you lose it, rotate it from the app's page, which issues a new secret and stops the old one working immediately.
cli
clikdeploy oauth clients create "My integration" \ --redirect-uri https://myapp.example/api/auth/callback/clikdeploy \ --scopes openid,profile,email \ --type confidential
clikdeploy oauth scopes prints every permission this server can issue, read from its own discovery document.
This is the common case, and it is mostly library configuration. Give your library the issuer, your client ID, your client secret if you have one, and the permissions you want. Here it is in Auth.js (NextAuth v5), which is the usual choice for a Next.js app.
auth.ts
import NextAuth from 'next-auth';
export const { handlers, auth } = NextAuth({
providers: [
{
id: 'clikdeploy',
name: 'ClikDeploy',
type: 'oidc',
issuer: 'https://clikdeploy.com',
clientId: process.env.CLIKDEPLOY_CLIENT_ID!,
clientSecret: process.env.CLIKDEPLOY_CLIENT_SECRET!,
authorization: { params: { scope: 'openid profile email' } },
checks: ['pkce', 'state'],
},
],
});The redirect URI to register for that config is https://your-app.example/api/auth/callback/clikdeploy.
Any conformant library works the same way. In Python, Authlib needs the document URL and the same three values.
python
oauth.register(
name="clikdeploy",
server_metadata_url="https://clikdeploy.com/.well-known/openid-configuration",
client_id=os.environ["CLIKDEPLOY_CLIENT_ID"],
client_secret=os.environ["CLIKDEPLOY_CLIENT_SECRET"],
client_kwargs={"scope": "openid profile email", "code_challenge_method": "S256"},
)After sign-in you get an ID token — a signed statement of who the person is. Its contents follow the permissions you asked for: openid gives you a stable user id, profile adds name and avatar, email adds the email address. A field you did not ask for is absent, never blank.
Redirect URIs are matched character for character
Ask for functional permissions alongside the identity ones, in the same sign-in. The person sees the whole list on one approval screen and approves or declines all of it.
scope: 'openid profile email apps:read deploy:write offline_access'
Your library exchanges the result for an access token. Send it as a bearer token on any REST API request, and the API acts as that user, limited to what they approved.
curl https://clikdeploy.com/api/apps \ -H "Authorization: Bearer <access token>"
Access tokens last 10 minutes. To keep working after that, ask for offline_access, which also returns a refresh token your library trades for a fresh access token when the old one expires. Without offline_access there is nothing to refresh with, and the person has to sign in again.
If a call needs a permission you were not granted, the API answers 403 and names the missing permission in the WWW-Authenticate header, so you know exactly what to add. The endpoints themselves are documented in the REST API reference.
For a backend job that acts as itself — a deploy bot, an exporter, a nightly script — use the client_credentials grant. Your app swaps its own client ID and secret for an access token. There is no person, no approval screen and no ID token.
This needs a server-side app whose registration includes that grant. The web form does not offer it; create the client from the CLI with --grants client_credentials, or from the management API.
curl https://clikdeploy.com/oauth/token \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -d grant_type=client_credentials \ -d 'scope=apps:read deploy:write'
Leave scope out and the token carries everything the client is registered for. Ask for anything beyond that and the request fails with invalid_scope — a client cannot grant itself more than it was registered with. These tokens also last 10 minutes, and there is no refresh token; when one expires, request another.
A scope is one named permission. ClikDeploy scopes are almost all shaped area:read or area:write, where the area is a part of the platform: apps, deployments, servers, domains and so on. Asking for area:write automatically includes area:read — write is the bigger permission, not a different one.
Four scopes are not shaped that way: the identity scopes below, which come from the OpenID Connect standard rather than from ClikDeploy.
| Scope | What it lets your app do |
|---|---|
openid | Confirm who the user is. Required for sign-in. |
profile | Read their name and avatar. |
email | Read their email address. |
offline_access | Keep working after the access token expires (returns a refresh token). |
apps:read | List their apps and read app settings. |
apps:write | Create, change, start, stop and delete apps. Includes apps:read. |
deploy:write | Trigger, cancel, retry and roll back deployments. Includes deploy:read. |
observe:read | Read logs, metrics, health and uptime. |
There are 50 scopes in total. The full list is in the discovery document, under scopes_supported, and clikdeploy oauth scopes prints it with descriptions. The list is generated from what the platform can actually do, so it is never out of date.
Twelve of the 50 are administrator permissions, named admin-…. They require an administrator account, and they are never given to an app that registered itself through the automatic registration endpoint.
Your library finds all of these in the discovery document; the table is here for the rare case that yours cannot. Prefix each path with the issuer.
| Path | What it is |
|---|---|
/.well-known/openid-configuration | The discovery document. Also served at /.well-known/oauth-authorization-server. |
/oauth/authorize | Where you send the person to sign in and approve. Browser redirect. |
/oauth/token | Exchange an authorization code, a refresh token or client credentials for tokens. Form-encoded POST. |
/oauth/userinfo | Read the signed-in user’s claims with an access token. Needs the openid scope. |
/oauth/jwks | The public keys tokens are signed with, so your own services can verify a token without calling us. |
/oauth/revoke | Throw away an access or refresh token you hold. POST. |
/oauth/introspect | Ask whether a token is still valid and what it covers. Server-side apps only. |
/oauth/device/code | Start sign-in for a device with no browser; the person types a short code at /oauth/device. |
/oauth/register | Automatic self-registration, used mostly by MCP clients. No human step, and never granted an admin scope. |
Every one of these also answers at /api/oauth/…, which is where the handlers actually live. Use the /oauth/… form — that is what discovery advertises.
Errors follow the OAuth standard: an error code and usually an error_description, in JSON.
When someone signs in to your app, ClikDeploy shows them an approval screen naming your app, the site they will be sent back to, and every permission you asked for. The permissions are grouped: identity first, then read-only ones, then ones that can change things, which are marked as such. Administrator permissions get their own warning. If they have approved your app before, only the new permissions are highlighted.
They can decline, and they can change their mind later: /oauth/authorized lists every app with access to their account. Removing one withdraws consent and invalidates every token that app holds for them, immediately.