OAuth
Our APIs are protected with OAuth 2.0. Your system authenticates itself with the credentials we issue to you, receives an access token, and sends that token with every API request.
This page covers how to obtain a token. The next page covers the token's lifetime and how to renew it.
The flow we use: Client Credentials
JobRad® APIs use the Client Credentials Flow (RFC 6749, Section 4.4). It is designed for server-to-server communication: your backend authenticates as itself, without any user being present and without any user having to log in or grant consent.
That has two practical consequences worth knowing up front:
- There is no browser redirect, no login page and no consent screen.
- There is no refresh token. When a token expires, you request a new one exactly the way you requested the first one. See Access Tokens.
Key terms
| Term | Meaning |
|---|---|
| Client | Your application or system, identified by a client_id and authenticated with a client_secret. |
| Authorization Server | The JobRad® server that authenticates your client and issues access tokens. |
| Resource Server | The JobRad® API you call with the access token. |
| Access Token | The short-lived credential you send with every API request. |
| Scope | Selects which API the token is valid for. |
Flows we do not support
Other OAuth flows exist, and you may know them from other providers. For the APIs documented here, they are not available:
- Authorization Code Flow (with or without PKCE)
- Device Code Flow
- Resource Owner Password Flow
- Refresh Token grant
If your use case seems to require one of these, contact us before you build around it.
Getting your credentials
You receive a client_id and a client_secret from us as part of onboarding. Credentials are issued per integrating system and per environment — your sandbox credentials are not valid in production, and vice versa.
See Applying for API Access for how to request them.
Requesting an access token
Token endpoint:
https://id.jobrad.org/realms/external/protocol/openid-connect/token
Request:
POST /realms/external/protocol/openid-connect/token
Host: id.jobrad.org
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=dealer-api
The same request as curl:
curl -X POST https://id.jobrad.org/realms/external/protocol/openid-connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=dealer-api"
⚠️ Never run this request from a browser, a mobile app or any other client you do not control — it would expose your
client_secret. The token request belongs on your server.
Scopes
The scope parameter selects the API your token is valid for. It is required: a token requested without the matching scope is rejected by the API.
| Scope | Grants access to |
|---|---|
dealer-api | JobRad® Offers API |
Request only the scope you actually need. If your integration uses more than one JobRad® API, request one token per scope.
Response
A successful request returns a JSON body containing your access_token. The fields are described in detail under Access Tokens.
Using the access token
Send the token as a Bearer token in the Authorization header of every API request:
curl https://connect.jobrad.org/v1/offers \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Do not send your client_id or client_secret to the API itself — they belong only in the token request.
OpenID Connect Discovery
Endpoint URLs and supported capabilities can be read from the discovery document:
https://id.jobrad.org/realms/external/.well-known/openid-configuration
Use it if your OAuth library configures itself from discovery metadata. Note that the document describes what the authorization server supports in general — the flows and scopes available to your credentials are the ones documented on this page.
Security best practices
- Always use HTTPS. Never send credentials or tokens over plain HTTP.
- Keep the
client_secreton your server. Never ship it in frontend code, mobile apps, source repositories or log output. - Store credentials in a secret manager, not in configuration files that travel with your code.
- Keep tokens out of logs and URLs. Send them in the
Authorizationheader only. - Use separate credentials per environment and per integrating system, so access can be revoked selectively.
- Report a suspected leak immediately via our contact channels so we can rotate your secret.
Error handling
Errors from the token endpoint follow the standard OAuth 2.0 format:
{
"error": "invalid_client",
"error_description": "Invalid client or Invalid client credentials"
}
Common errors when requesting a token:
| Error | Typical cause |
|---|---|
invalid_client | Unknown client_id, wrong client_secret, or credentials used against the wrong environment. |
invalid_request | A required parameter is missing or the request is not application/x-www-form-urlencoded. |
unsupported_grant_type | grant_type is not client_credentials. |
unauthorized_client | Your client is not permitted to use this grant type. |
invalid_scope | The requested scope does not exist or is not assigned to your client. |
Errors from the API are different: a 401 means the API did not accept your token (expired, malformed, or issued for another scope), a 403 means the token is valid but not authorized for that operation. How to react to a 401 is described under Access Tokens.