Sign-in and scopes
Version 2 uses OAuth 2.0 client credentials. Your server exchanges a client id and secret for a token that lasts an hour, and sends the token with every call.
Clients and secrets
Frantz creates a client for you and sends you its client_id and
client_secret. The secret is a password for your integration:
- Keep it on your server. Never put it in a web page, an app, a log or a repository.
- Frantz stores only a hash of it and cannot show it again. If you lose it, ask Frantz for a new client.
- You can have several clients. To replace a secret without downtime, ask for a new client, move your servers to it, and ask Frantz to withdraw the old one.
- When Frantz withdraws a client, its tokens stop working at once. Ask Frantz to do that straight away if a secret may have leaked.
Test and production have separate clients.
Getting a token
POST /api/v2/auth/token takes a form
(application/x-www-form-urlencoded), not JSON. Always call it, and the rest of the API, on
https: a request to http is redirected, and the redirect turns a POST into a
GET, which answers 405.
| Field | Value |
|---|---|
grant_type | client_credentials |
client_id | Your client id. |
client_secret | Your client secret. |
scope | Optional. The scopes you want, separated by spaces. Leave it out to get all your client has. |
You can send the id and secret as HTTP Basic authentication instead, as most OAuth libraries do. Send them one way, not both.
POST /api/v2/auth/token HTTP/1.1
Host: api.frantz.no
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=fzc_...&client_secret=fzcs_...HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: application/json; charset=utf-8
{
"access_token": "fzat_...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "job-adverts:write statistics:read"
}
expires_in is the number of seconds the token works. There is no refresh token: when the hour is up,
ask for a new token the same way.
Using the token
Send the token in the Authorization header of every other call:
GET /api/v2/job-adverts/744376 HTTP/1.1
Host: api.frantz.no
Authorization: Bearer fzat_...- Reuse it for its hour. Every request to the token endpoint makes a new token, so do not ask for one per call. Keep it in memory and ask for a new one a minute or so before it expires.
- On
401, get a new token and try once more. If the new token is refused too, the client has been withdrawn: stop and contact Frantz. - Keep it on your server. A token gives the same access as the secret for an hour. Do not log it.
Scopes
Each client has the scopes Frantz has given it, and each endpoint needs one. A token can have fewer scopes than its
client: a job that only reads statistics can ask for scope=statistics:read.
| Scope | Lets you |
|---|---|
job-adverts:write | Send, change and read job adverts, and read audiences. |
statistics:read | Read statistics for your job adverts. |
campaigns:read | Read the advertisers you can order for, the media products, places and audiences, ask for quotes, and read your campaigns and their budgets. Frantz gives this scope on request. |
campaigns:write | For partners in the pilot: create, change, order, cancel, pause, resume and stop campaigns, and add their material. Ordering costs the advertiser money, so Frantz gives this scope on request. |
The reference shows the scope each endpoint needs, and Campaigns lists the scopes for the campaign calls.
When sign-in fails
The token endpoint answers errors the OAuth way, with error and error_description, not
with Problem Details.
| Status | error | Why |
|---|---|---|
| 400 | invalid_request | Not a form, grant_type is missing, or the id and secret were sent both as HTTP Basic and in the form. |
| 400 | unsupported_grant_type | grant_type is not client_credentials. |
| 400 | invalid_scope | You asked for a scope your client does not have. Frantz does not quietly give less. |
| 401 | invalid_client | Unknown client, wrong secret, or the client or your partner account is switched off. |
{
"error": "invalid_client",
"error_description": "Unknown client, wrong secret, or the client or partner is switched off."
}When a call is refused
The other endpoints answer 401 or 403 with Problem Details and a
WWW-Authenticate header that says why:
| Status | WWW-Authenticate | What to do |
|---|---|---|
| 401 | Bearer | The call had no token. Send Authorization: Bearer. |
| 401 | Bearer error="invalid_token" | The token is unknown, has expired, or its client is switched off. Get a new token and try once more. |
| 403 | Bearer error="insufficient_scope", scope="statistics:read" | The token lacks the scope in scope. Ask for a token with it, or ask Frantz to give your client the scope. |