Authentication
An API key is the credential your pipeline sends instead of signing in. It belongs to your organization and not to a person, so it keeps working when whoever created it leaves. It stops working on a date chosen when it was created.
Send the key on every request
Section titled “Send the key on every request”Put it in the Authorization header, after Bearer:
curl --silent --show-error --fail-with-body \ -H "Authorization: Bearer $FACTEUR_API_KEY" \ https://api.facteur.eu/inboxesA key starts with fk_. The API turns away anything else before it looks anything up.
Create, rotate and revoke
Section titled “Create, rotate and revoke”Creating, changing and revoking a key are done by a person who is signed in to the Facteur app, in Settings, then API keys, and only by an owner or an administrator. No key can make or end a key, its own included, and the API has no route for it.
You choose a duration of 30, 90, 180 or 365 days when you create a key, and every key expires. The key is shown once, when it is created. Facteur keeps a hash of it, so nobody can show it again. After a revocation, the next call made with that key is refused with API_KEY_REVOKED.
Choose what the key may do
Section titled “Choose what the key may do”A key holds one or more of four permissions, in two families:
| Permission | What it opens |
|---|---|
ws:read |
Read the inboxes, the messages and the requests for an SMS number of the workspaces the key reaches. |
ws:write |
Everything ws:read does, and create, change and delete inboxes and extractors, and ask for an SMS number or take the request back. |
org:read |
Read the structure of the organization: its workspaces and their members, its capacity and the destinations of its alerts. |
org:write |
Everything org:read does, and create and change workspaces and their members. |
Inside a family, writing includes reading. The two families never include each other: a key that holds org:write alone creates workspaces and reads no message.
Every operation of the reference names the permission it needs. A key that lacks it gets a 403 whose code is API_KEY_PERMISSION_MISSING, and whose permission member names the permission that was missing:
curl --silent --show-error --include \ -X POST \ -H "Authorization: Bearer $FACTEUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "A workspace"}' \ https://api.facteur.eu/workspacesWith a key that holds ws:read only, this call answers 403, with a WWW-Authenticate header that carries error="insufficient_scope" and the missing permission as scope.
Choose which workspaces the key reaches
Section titled “Choose which workspaces the key reaches”A workspace groups inboxes and decides who reaches them. When you create a key, you pick the workspaces it reaches, or every workspace, including those created later. A workspace the key does not reach answers 404, as if it did not exist.
What no key does
Section titled “What no key does”None of these has a route on the API, whatever permissions the key holds:
- invite a person to an organization;
- pay, change the plan or the spending cap, or read the invoices;
- create, change or revoke an API key;
- create, change or delete the destinations of the alerts. A key can only list them.
An API key never deletes a workspace either: DELETE /workspaces/{slug} always answers 403 with the code API_KEY_CANNOT_DELETE_WORKSPACE. A person deletes it from the app.
Read a refusal that says how to authenticate
Section titled “Read a refusal that says how to authenticate”A 401 carries a WWW-Authenticate header. It points at the document that describes how to present a key:
WWW-Authenticate: Bearer realm="Facteur API", resource_metadata="https://api.facteur.eu/.well-known/oauth-protected-resource"A key that was presented and refused adds error="invalid_token". Three codes tell apart the reasons for a refusal, because each one calls for a different fix:
| Code | What happened | What you do |
|---|---|---|
API_KEY_UNKNOWN |
The key never existed. | Check what your pipeline actually sends. |
API_KEY_REVOKED |
A person revoked it. | Create a new key. |
API_KEY_EXPIRED |
It is past its date. | Create a new key, and do it before the date next time. |
A request with no key at all answers UNAUTHENTICATED. The errors guide lists every code.