RareMargin has a versioned REST API at /v1, an MCP server at /mcp for AI agents, and webhooks signed with HMAC-SHA256. All three run on the same services and approval rules as the app, so a script gets exactly the rules a person does.
| Address | For | |
|---|---|---|
| REST API | https://raremargin.com/v1 | Scripts, integrations and data exports |
| MCP server | https://raremargin.com/mcp | Claude and other AI agents |
| Webhooks | Your HTTPS endpoint | Reacting to changes in the books |
01How do I authenticate with the RareMargin API?
Create an API key in Settings and send it as a Bearer token. Each key carries a role, and its writes go through the same approval rules as a person’s.
curl https://raremargin.com/v1/accounts \
-H "Authorization: Bearer $RAREMARGIN_API_KEY"02What can the RareMargin REST API do?
It reads and writes the ledger and every subledger: accounts, journal entries, periods, customers, products, contracts, invoices, payments, vendors, bills and bank lines.
| Area | Endpoints under /v1 |
|---|---|
| Ledger | GET /subsidiaries; GET, POST /accounts; GET, POST /journal-entries; GET /journal-entries/:id; POST /journal-entries/:id/reverse |
| Periods and controls | GET /book-periods; POST /book-periods/:period/close; GET /ledger/verify; GET /controls |
| Revenue | GET, POST /customers; GET /customers/:id; GET, POST /products; GET, POST /contracts; GET /contracts/:id; POST /contracts/:id/activate |
| Billing | GET, POST /invoices; GET /invoices/:id; POST /invoices/:id/issue; POST /invoices/:id/void; GET, POST /payments |
| Spend | GET, POST /vendors; GET /vendors/:id; GET, POST /bills; GET /bills/:id; POST /bills/:id/payments |
| Cash | GET /bank-accounts; GET, POST /bank-accounts/:id/transactions |
| Reports and events | GET /reports/:name; GET /events; GET, POST /webhooks; DELETE /webhooks/:id |
Reports include the trial balance, income statement, balance sheet, cash flow, general ledger, AR and AP aging, SaaS metrics, deferred revenue, revenue by customer, spend, cash position, burn and runway, and the cash forecast.
03How does the API handle amounts, retries and errors?
Amounts are decimal strings, writes accept an Idempotency-Key, lists page with cursors, errors follow RFC 9457, and a write held for approval returns 202 Accepted.
JSON keys are snake_case. Each API key has its own rate limit, reported in X-RateLimit headers.
04How do I connect Claude or another AI agent to RareMargin?
Add https://raremargin.com/mcp to the client as a Streamable HTTP MCP server, with your API key as a Bearer token; the agent gets the assistant’s 17 tools.
The settings file differs between clients; for most it looks like this:
{
"mcpServers": {
"raremargin": {
"type": "http",
"url": "https://raremargin.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Its two write tools, propose_journal_entry and propose_accrual, create approval requests, never postings, so an agent can prepare the work and a person decides what reaches the books.
Exact setup for Claude Code, Claude Desktop, Cursor and Codex is in the guide to using RareMargin in Claude, ChatGPT and Cursor.
05Which webhook events does RareMargin send?
34 event types, covering accounts, journal entries, periods, approvals, customers, contracts, invoices, payments, vendors, bills and bank lines.
- account.created, account.updated, subsidiary.created
- journal_entry.created, journal_entry.posted, journal_entry.rejected, journal_entry.reversed
- book_period.closed, book_period.reopened
- approval.requested, approval.approved, approval.rejected
- customer.created, customer.updated, product.created
- contract.created, contract.activated, contract.terminated, contract.completed
- invoice.created, invoice.issued, invoice.paid, invoice.voided, payment.created
- vendor.created, bill.created, bill.approved, bill.rejected, bill.paid, bill.voided
- bank_account.created, bank_transactions.imported, bank_transaction.matched, bank_transaction.unmatched
06How are RareMargin webhooks signed and retried?
Each delivery carries X-RareMargin-Signature: v1= and a base64 HMAC-SHA256 of the event id, timestamp and body, keyed with your endpoint’s secret.
Deliveries also carry X-RareMargin-Id, X-RareMargin-Event and X-RareMargin-Timestamp (Unix seconds). Reject a delivery whose timestamp is more than 5 minutes off, and compare signatures in constant time:
import { createHmac, timingSafeEqual } from 'node:crypto';
// headers: the request's headers, lower-cased; body: the raw request body as a string.
function verify(secret, headers, body) {
const id = headers['x-raremargin-id'];
const ts = Number(headers['x-raremargin-timestamp']);
if (!(Math.abs(Date.now() / 1000 - ts) <= 300)) return false;
const expected = 'v1=' + createHmac('sha256', secret).update(`${id}.${ts}.${body}`).digest('base64');
const got = headers['x-raremargin-signature'] ?? '';
return got.length === expected.length && timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}A failed delivery is retried up to 8 times, 30 seconds after the first attempt and then twice as long each time, up to 6 hours. Events go out from a transactional outbox, and every delivery is logged in Settings.
