Concepts

Authentication

API keys, sign-in tokens, permissions, roles and choosing a company.

Every request carries a credential in the Authorization header:

HTTP
Authorization: Bearer oat_live_…

Oatmilk accepts two kinds of credentials. Both work with the REST API and with MCP.

CredentialBest forHow you get it
API keyYour own server, scripts and back-office jobsDevelopers › API keys
OAuth tokenApps other people connect, and AI assistantsThe person signs in to Oatmilk and approves access

API keys

An API key belongs to the person who made it and to one company. It starts with oat_live_ in production or oat_test_ in staging, and the two never work in each other's environment.

  • It's shown once. Copy it when you create it. Oatmilk only stores a hash, so nobody can show it to you again. If you lose it, rotate the key to get a new secret.
  • It expires. Keys last 90 days unless you choose otherwise, and at most a year.
  • It follows its owner. Every request checks the owner's current role and membership. A key stops working when it's revoked, when it expires, or when its owner leaves the company.
  • It's for servers. Never put a key in browser code, a mobile app or a public repository.

Permissions

A key or token only does what its permissions allow. Each action's page in the API reference lists the permissions it needs, and a request without them is refused with INSUFFICIENT_SCOPE.

PermissionAllows
accounting:readRead accounting. Read records and receipt evidence allowed by your role.
accounting:writeWrite accounting. Submit receipts and, with finance access, edit records and reconcile. Select read access too.
accounting:adminAccounting administration. Manage access, bank settings and closed periods. Administrator role remains required.
mail:readRead company mail. Read cleared company email and its original files. Separate from accounting access.
mail:writeManage company mail. Review email and financial drafts. Select mail read too; booking also requires accounting read and write.
mail:securityRead restricted account-access mail. Explicitly allow access codes, security messages and unscreened mail. Requires administrator role and mail read.
api_keys:manageManage API keys. Create or replace your keys within this key’s permissions and expiration; administrators may revoke organization keys.
mailboxes:searchSearch your inbox for receipts. Start Find in my inbox for purchases that need a receipt, or check your inbox now, in your own connected inbox only. Read and write access don’t include it.
contractor:readRead your contractor records. Read your own hours, timesheets, pay, agreements and profile with one company.
contractor:writeChange your contractor records. Log and submit your own hours and update your profile. Select read access too.

Roles

Permissions say what a credential may try. The owner's role in the company decides what they may actually do, and the stricter of the two always wins.

RoleCan work with
adminEverything, including people, settings, connectors, webhooks and closing periods.
financeThe books: transactions, receipts, matching, invoices, contractors and reports.
contributorTheir own receipts and card purchases, and the company's categories.
accountantAn outside accountant: reads and exports what their access allows, through OAuth only.
contractorThe contractor API: only their own hours, pay, agreements and profile.

Choosing a company

An API key always works in the company it was made in. A person with an OAuth token may belong to several companies: send X-Accounting-Organization with the company's ID to choose one. If you send it with an API key, it must name the key's own company.

HTTP
X-Accounting-Organization: org_2abc…

Each person can also have a personal workspace for their own money, chosen the same way. identity.get returns workspaceKind (company or personal). A personal workspace has every action except the contractor portal, recruiting and team invitations, which fail there with PERSONAL_WORKSPACE.

OAuth for apps and AI assistants

Apps that other people connect should use OAuth instead of asking for an API key. The person signs in to Oatmilk, sees what your app asks for, and approves it. Your app never sees their password, and they can disconnect it at any time.

Oatmilk publishes its OAuth details at https://app.getoatmilk.com/.well-known/oauth-authorization-server, and MCP clients discover them automatically from https://app.getoatmilk.com/.well-known/oauth-protected-resource/api/mcp. See MCP server.

Steps only a person can take

Some things always need a person in Oatmilk itself: signing an agreement, approving a suggestion, sending money, or entering bank and tax numbers. The API refuses them with an INTERACTIVE_… error that includes the link to the right page, so your app can hand it to the person. See Errors.