Concepts
Making requests
Addresses, methods, the response envelope, headers and size limits.
The Oatmilk API is a set of named actions, the same ones the Oatmilk app uses. Each action has its own address, takes a JSON object, and returns a JSON object. There are no nested resource paths to learn: if you know an action's name, you know its address.
POST https://app.getoatmilk.com/api/v1/accounting/invoices.createMethods
- POST works for every action. Send the input as a JSON body with
Content-Type: application/json. - GET also works for read actions, with the input in the query string. It's handy for quick checks and caching proxies, but values arrive as text, so use POST for anything with lists or nested objects.
An action that changes something refuses GET with METHOD_NOT_ALLOWED. Each action's page in the API reference shows which methods it accepts.
The response envelope
A successful response has one field, data, holding the action's result:
{ "data": { "id": "7f0f6c1e-1c1f-4b5e-9c8d-2f5e8e3c1a10", "status": "sent" } }A refused or failed request has one field, error, with a stable code you can branch on and a message you can show a person:
{ "error": { "code": "INVALID_INPUT", "message": "Amount needs a valid value. Check this field and try again.", "field": "amountMinor", "docUrl": "https://app.getoatmilk.com/docs/errors#invalid-input" } }field names the first problem when there is one, and docUrl links to what the code means. Some errors also carry dashboardUrl or portalUrl: the page where a person can finish the step. See Errors.
Headers
| Header | Meaning |
|---|---|
X-Request-Id | A unique ID for this request. Keep it in your logs and include it when you ask for help. |
X-Accounting-API-Version | The date of the API contract this response follows. |
Retry-After | On a 429 response: how many seconds to wait before retrying. |
WWW-Authenticate | On a 401 response: says a bearer credential is required. |
Limits
| Limit | Value |
|---|---|
| Requests per API key | 120 per minute |
| JSON body | 3 MB |
| Time to send the body | 15 seconds |
File in uploads.inline | 2 MB |
| File through an upload link | 50 MB |
Browser requests
The API answers cross-origin requests, so a tool running in a browser can call it. That doesn't make it safe to put an API key in a web page: anyone who opens the page can read the key. Call Oatmilk from your own server, or use OAuth so each person signs in with their own account.
The OpenAPI document
https://app.getoatmilk.com/api/openapi.json describes every action in OpenAPI 3.1, generated from the same definitions the API checks requests against. Import it into Postman, Insomnia or a code generator, or point an AI tool at it. Its webhooks section describes every event Oatmilk sends.