View as Markdown

Authentication

Every API call carries a credential. An integration uses an API key. An AI assistant that connects to the MCP server uses OAuth, and the MCP server calls the API with that token for it.

API keys

An API key belongs to one organization. It reaches the companies of that organization, and nothing else.

GET /api/organizations/ HTTP/1.1
Authorization: Bearer osk_live_...
  • Create a key in the Oscar app, in the settings of your organization, under API keys. You need the permission api_keys.manage (an owner has it). Give the key a name, its scopes, and an optional expiry date.
  • The full key is shown once, when you create it. Oscar stores only a hash of it. Keep it in a secret store, never in your code or in a log.
  • A key starts with osk_, for example osk_live_..., so a secret scanner can find it.
  • A key acts for the person who created it. It has the permissions of that person's role in the organization, narrowed by the scopes of the key and by what Oscar allows the clients of each company. When that person leaves the organization or is deactivated, the key is revoked.
  • An owner sees every key of the organization in the settings, and can revoke one at any time. An unknown, revoked or expired key gets 401 authentication_failed.

Scopes

ScopeAllows
readEvery read: the organization, the books, the documents
writeEvery change that the role allows: record and issue invoices, create parties, upload documents

A key needs read to read and write to change something. No key can manage the organization, its members or its API keys: only a person signed in to the app can do that.

A call that the role allows but the scopes of the key do not gets 403 insufficient_scope. A call that the role does not allow gets 403 permission_denied.

Which permissions does my key have?

GET /api/companies/{company_id}/ returns permissions: the effective permissions of the caller in that company. Each operation of the API reference names the permission it needs.

OAuth

Oscar is an OAuth 2.1 authorization server for the MCP server. An MCP client such as Claude or ChatGPT signs the user in, the user approves the connection on a consent page and chooses one organization, and the client gets an access token for that organization.

  • The authorization code flow with PKCE S256, and nothing else.
  • The metadata is at /.well-known/oauth-authorization-server. The authorization endpoint is /oauth/authorize and the token endpoint is /oauth/token.
  • Each request names the MCP server as its resource (RFC 8707).
  • The scopes are the same as for an API key: read and write. A request that names no scope gets read only; ask for read write to write.
  • An access token lives for one hour. Refresh tokens rotate.
  • The user sees every connection under "Connected apps" in the account settings, and can revoke one there.

An integration that is not an MCP client uses an API key. The details of the flow are in Connect an AI assistant.

Requests without a session

A request with an API key or an OAuth token sends no cookie, so it needs no CSRF token. Send JSON with Content-Type: application/json, and a file upload as multipart/form-data.

Every response carries an X-Request-Id header. Give it to us when you report a problem. You can also send your own X-Request-Id, and the API keeps it when it is well formed.