REST API
Call Osorik from scripts and integrations over HTTPS.
The REST API serves JSON under /v1 on the API origin. It uses the same
credentials as the MCP server: a team API key
or an OAuth access token.
| Setting | Value |
|---|---|
| Base URL | https://api.osorik.dev/v1 |
| Reference | https://api.osorik.dev/v1/docs |
| OpenAPI 3.1 document | https://api.osorik.dev/v1/openapi.json |
Make a request
Send the credential as a bearer token:
curl https://api.osorik.dev/v1/team \
-H "Authorization: Bearer $OSORIK_API_KEY"The API reference lists every endpoint with its request and response schemas, and builds example requests for you. It is generated from the OpenAPI document, so it always matches what the API serves.
Writes send a JSON body. This changes one field of a transaction and leaves the others as they are:
curl -X PATCH https://api.osorik.dev/v1/transactions/$TRANSACTION_ID \
-H "Authorization: Bearer $OSORIK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "note": "Team offsite lunch" }'What the API covers
| Area | Read | Write |
|---|---|---|
| Team | Profile and your role | None |
| Contacts | List, search, get | Create, update |
| Categories | List | Create |
| Bank accounts | List | None |
| Transactions | List, filter, get | Category, note, contact, project, archive |
| Invoices | List, get, invoice settings | Create, update and delete drafts |
| Expenses | List, filter, get | Update details, archive |
| Projects | List, get | Create, update, change status |
| Time | Entries, tasks, running timer | Log, edit and delete entries; add tasks; start and stop the timer |
Issuing, voiding and sending invoices, deleting contacts or expenses,
uploading documents, connecting banks and managing members stay in the app.
Your role applies: an endpoint that needs an owner or admin returns 403 for
members.
Conventions
- IDs are strings. An ID that doesn't exist in your team returns
404. - Amounts are decimal strings in the currency's major unit, such as
"1250.00", next to an ISO 4217currencycode. - Dates are
YYYY-MM-DD; timestamps are ISO 8601 in UTC. - Absent values are
null, never missing. PATCHchanges only the fields you send. Sendnullto clear an optional field.- Creates return
201with the new record; deletes return{ "id": "…", "deleted": true }.
Pagination
List endpoints take limit (1 to 100, default 25) and cursor, and return a
page:
{
"data": [{ "id": "…" }],
"nextCursor": "eyJ…"
}Pass nextCursor as cursor to get the next page; it is null on the last
page. A page can hold fewer than limit items before the last one, so keep
going until nextCursor is null.
Errors
Every error returns a JSON body with a stable code and a readable message:
{
"code": "API_KEY_INVALID",
"message": "The API key is invalid or revoked."
}| Status | Code | Meaning |
|---|---|---|
400 | INVALID_REQUEST | The request failed validation |
400 | INVALID_CURSOR | The pagination cursor is invalid or expired |
400 | Other codes | A business rule rejected the input, such as INVALID_DATE_RANGE |
401 | API_KEY_REQUIRED | No bearer credential was sent |
401 | API_KEY_INVALID | The API key is invalid or revoked |
401 | OAUTH_TOKEN_INVALID | The access token is invalid or expired |
403 | INSUFFICIENT_SCOPE | The credential lacks the read or write scope the endpoint needs |
403 | *_FORBIDDEN | Your role can't do this, such as PROJECT_MANAGEMENT_FORBIDDEN |
404 | NOT_FOUND | No such endpoint |
404 | *_NOT_FOUND | The record doesn't exist in your team, such as INVOICE_NOT_FOUND |
409 | Conflict codes | The record's state blocks the change, such as INVOICE_IMMUTABLE for an issued invoice |
429 | RATE_LIMITED | Too many requests; wait for the seconds in Retry-After |
500 | INTERNAL_ERROR | Something went wrong on our side |
Discovery
GET https://api.osorik.dev/ returns an index that links the API, its OpenAPI document,
the reference, and the MCP endpoint.
The site publishes an API catalog at
https://osorik.dev/.well-known/api-catalog. It
links the REST API's OpenAPI document and guides, and the MCP server's
server card, guide, and OAuth
protected resource metadata.