Skip to main content

Authentication

Access to the Scribee API is secured via the OAuth 2.0 protocol.

Grant type​

The grant type is Client Credentials (client_id + client_secret). There is no intermediate user: the client authenticates directly with the API to obtain an access token.

Getting an access token​

Send a POST request to the /oauth/token endpoint with your credentials and the scopes you need:

curl -X POST https://app.scribee.tech/oauth/token \
-d grant_type=client_credentials \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET \
-d scope="read write"

The response contains the access token to use in the Authorization header of every request:

{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 28800,
"scope": "read write",
"created_at": 1767225600
}

created_at is a Unix timestamp in seconds. Treat the response as extensible: do not reject a field you do not know.

Scopes​

An access token grants access to every workspace granted to your application - GET /api/v1/workspaces lists them - and carries one or more of the following scopes:

ScopeDescription
readRequired on GET endpoints. The default scope: what a token request that omits scope receives, provided your application carries read.
writeRequired on POST, PATCH and PUT endpoints. Also accepted on DELETE.
destroyA least-privilege alternative to write on DELETE endpoints only, which accept either one.

The scopes attached to your application are set when it is created. A workspace manager or owner creates the application themselves from the Scribee interface, under Workspace > API tab, OAuth applications section. The form offers three cumulative combinations: read for a client that only reads, read write for a client that creates and updates, and read write destroy for a client that also deletes - read is always included. The name and the scopes stay editable afterwards from the same tab, where the application can also be deleted. Narrowing the scopes immediately revokes the access tokens that carried the removed rights; widening them, or renaming the application, revokes nothing. A token that escapes that revocation is refused - and revoked - on its next call anyway: as soon as its scopes are no longer a subset of the application's, it receives a 401 invalid_token. After a scope change, request a new token.

The client ID stays visible at any time on the application page, in the same API tab. The client secret, on the other hand, is displayed only once, at creation and again at each regeneration: it is stored hashed and cannot be read back afterwards. The same tab lets you regenerate it. Regeneration invalidates the old secret immediately and revokes the application's still-active access tokens: deploy the new secret before your next call, otherwise your requests fail with the credentials and tokens they were carrying until then.

An application may also be provisioned by a Scribee administrator - which is notably the case for an application shared across several workspaces. It then appears in the workspace list with a "Provisioned by Scribee" marker, read-only: its name, its scopes and its secret are managed on the Scribee side only. The administration form offers two combinations, read and read write. destroy is a fully configured scope - the server accepts it on an application and DELETE endpoints honour it - but if you want a client that deletes without being able to write, ask for it explicitly.

The value you send in scope does not have to repeat everything granted to you: any subset is accepted. invalid_scope is returned only when you request a scope outside your perimeter.

Omitting scope is NOT always equivalent to requesting read. The server intersects your application's scopes with the default read scope, and that intersection is what it issues: an application carrying read receives read. An application that does not carry it intersects to nothing, and the token request is refused with invalid_scope - no token is issued, not even a scope-less one. A destroy-only application must therefore send scope=destroy explicitly. Always send the scope you want rather than relying on the default.

:::caution What the server actually checks, endpoint by endpoint

Writes are scope-checked: POST, PATCH and PUT require write, and DELETE requires destroy or write. A read-only token receives a 403 there, with the message Vous n'êtes pas autorisé à effectuer cette action.

Reads are too: a GET requires read. A token whose scopes omit read receives a 403 on a read endpoint, with the same message - a token carrying only write does not read, and neither does a token carrying only destroy.

So request read on every token request as soon as your integration reads anything, and read write as soon as it writes. It is what the OpenAPI reference declares, and it is what the server enforces.

:::

GET /api/v1/health is the one exception to authentication: it requires no token at all, precisely so it stays reachable when your credentials are what is in question.

IP allowlisting​

Tenant-scoped API access is also filtered by the target tenant's IPv4 allowlist when one is configured. Requests from denied IPs receive a JSON 403 on direct tenant resolution, and denied tenants are omitted from workspace and resource lookups.

:::caution The allowlist is strictly IPv4 As soon as a workspace has at least one allowlist entry, a request whose source address is not IPv4 is denied whatever the list contains - no entry can ever authorize an IPv6 address. If your servers egress dual-stack, force IPv4 towards app.scribee.tech before asking for an allowlist, otherwise your calls will intermittently return 403 depending on the address used. :::