FrantzPublic API
Guide

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.

FieldValue
grant_typeclient_credentials
client_idYour client id.
client_secretYour client secret.
scopeOptional. 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.

HTTP
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_...
JSON
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:

HTTP
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.

ScopeLets you
job-adverts:writeSend, change and read job adverts, and read audiences.
statistics:readRead statistics for your job adverts.
campaigns:readRead 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:writeFor 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.

StatuserrorWhy
400invalid_requestNot a form, grant_type is missing, or the id and secret were sent both as HTTP Basic and in the form.
400unsupported_grant_typegrant_type is not client_credentials.
400invalid_scopeYou asked for a scope your client does not have. Frantz does not quietly give less.
401invalid_clientUnknown client, wrong secret, or the client or your partner account is switched off.
JSON
{
  "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:

StatusWWW-AuthenticateWhat to do
401BearerThe call had no token. Send Authorization: Bearer.
401Bearer error="invalid_token"The token is unknown, has expired, or its client is switched off. Get a new token and try once more.
403Bearer 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.