Skip to content

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.

AddressFor
REST APIhttps://raremargin.com/v1Scripts, integrations and data exports
MCP serverhttps://raremargin.com/mcpClaude and other AI agents
WebhooksYour HTTPS endpointReacting 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.

AreaEndpoints under /v1
LedgerGET /subsidiaries; GET, POST /accounts; GET, POST /journal-entries; GET /journal-entries/:id; POST /journal-entries/:id/reverse
Periods and controlsGET /book-periods; POST /book-periods/:period/close; GET /ledger/verify; GET /controls
RevenueGET, POST /customers; GET /customers/:id; GET, POST /products; GET, POST /contracts; GET /contracts/:id; POST /contracts/:id/activate
BillingGET, POST /invoices; GET /invoices/:id; POST /invoices/:id/issue; POST /invoices/:id/void; GET, POST /payments
SpendGET, POST /vendors; GET /vendors/:id; GET, POST /bills; GET /bills/:id; POST /bills/:id/payments
CashGET /bank-accounts; GET, POST /bank-accounts/:id/transactions
Reports and eventsGET /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.

Sources

Continuous close

Stop closing the books. Keep them closed.

Start a 14-day trial on your own data, or on a sample SaaS company with 14 months of history. No card needed.

Three desk objects on a green stage: a tray of blue month cubes, a console of toggle switches with a lit button, and a keyboard of keycaps under a monitor of code.