Authentication
The COMMITLY API uses the OAuth 2.0 client credentials flow. Your application authenticates as itself with a client ID and client secret; there is no user login and no redirect.
| Base URL | https://app.commitly.com/api |
| Token URL | https://app.commitly.com/api/auth/token/ |
| Grant type | client_credentials |
| Client authentication | Credentials in the request body |
| Token lifetime | 5 minutes |
| Header | Authorization: Bearer <access_token> |
Get credentials
Section titled “Get credentials”In COMMITLY, open Add-ons and connect the COMMITLY Public API tile. The tile shows the client ID and the client secret. Disconnect revokes the credentials; connecting again issues new ones.
Credentials belong to one company. For group-level access across all companies (Enterprise), contact support@commitly.com, see Editions and access.
Request a token
Section titled “Request a token”POST /api/auth/token/ HTTP/1.1Host: app.commitly.comContent-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRETThe token endpoint also accepts JSON or multipart bodies. Credentials are read from the body only; HTTP Basic authentication is not supported.
A successful response (200) looks like this:
{ "access_token": "eyJhbGciOi…", "token_type": "bearer", "expires_in": 300, "refresh_token": "…", "refresh_expires_in": 1209600, "scope": "all"}Send the access_token with every request:
GET /api/categories/ HTTP/1.1Host: app.commitly.comAuthorization: Bearer YOUR_ACCESS_TOKENToken lifetime and renewal
Section titled “Token lifetime and renewal”Access tokens expire after 5 minutes (expires_in: 300). For server-to-server integrations the simplest way is to request a new token with the client credentials when the old one has expired; you do not need the refresh_token.
A robust client caches the token, reuses it for all calls within its lifetime and fetches a new one shortly before it expires, or when a call is rejected as unauthenticated.
let cached = { token: null, expiresAt: 0 };
async function getToken() { // Renew 30 seconds early to avoid using a token that expires mid-request. if (cached.token && Date.now() < cached.expiresAt - 30_000) return cached.token; const res = await fetch("https://app.commitly.com/api/auth/token/", { method: "POST", body: new URLSearchParams({ grant_type: "client_credentials", client_id: process.env.COMMITLY_CLIENT_ID, client_secret: process.env.COMMITLY_CLIENT_SECRET, }), }); if (!res.ok) throw new Error(`Token request failed: ${res.status}`); const { access_token } = await res.json(); cached = { token: access_token, expiresAt: Date.now() + 5 * 60_000 }; return access_token;}Errors
Section titled “Errors”| Status | When | Body |
|---|---|---|
400 |
Wrong client ID or secret at the token endpoint | {"non_field_errors": ["…"]} |
401 |
Invalid or expired access token | {"detail": "Invalid token."}, header WWW-Authenticate: Bearer |
403 |
No access token sent | {"detail": "User must be authenticated to access this resource."} |

