Automation Tools & AI Assistants

Connect Beeswax to Zapier, Make, n8n, a script in any language, or an AI assistant through MCP.

Which route?

You want to… Use
Ask questions of your books in plain English, draft quotes or journals with an assistant The Beeswax MCP server in Claude Desktop, Claude Code, Cursor or any MCP app. No code.
React to events in another tool (a new deal, a form submission) by creating something in Beeswax Zapier, Make or n8n with an HTTP request step (below).
Pull Beeswax data on a schedule into a spreadsheet, warehouse or dashboard A short script (below) or n8n on a schedule, using updated_since.
Build a product feature or a two-way integration Your own code against the API. Start with Best practices.

All of them use the same token from Account Settings → API Tokens and the same endpoints.


Zapier

Zapier has no native Beeswax app yet, so use Webhooks by Zapier.

  1. Create the token in Beeswax with only the scopes the Zap needs, for example invoices:write, companies:read, transaction_accounts:read for "new deal → draft invoice".
  2. In the Zap, add an action Webhooks by Zapier → Custom Request.
  3. Method POST (or GET to read). URL https://app.beeswaxapp.com/new_api/v1/invoices (or the endpoint you need).
  4. Headers: Authorization: Bearer YOUR_API_TOKEN, Content-Type: application/json, and Idempotency-Key mapped to a unique field from the trigger (the deal id, the form submission id). That last one is what stops a re-run of the Zap creating a second invoice.
  5. Data: the JSON body from the relevant recipe, with trigger fields mapped in. Wrap it in the singular resource key ({"invoice": {...}}).
  6. Test. The response is the created resource; map id and number into later steps (a Slack message, a CRM note).

Reading data in Zapier. A GET returns a page of up to 100 rows. Zapier's line-item handling copes with invoices[]; for anything larger, schedule a script instead.


Make (Integromat)

  1. Add an HTTP → Make a request module.
  2. URL as above, method POST, Body type Raw, Content type JSON.
  3. Headers: Authorization: Bearer YOUR_API_TOKEN and Idempotency-Key bound to a unique upstream id.
  4. Enable Parse response so the returned JSON is available to later modules.

n8n

  1. Add an HTTP Request node.
  2. Method and URL as above.
  3. Authentication: Generic Credential Type → Header Auth, name Authorization, value Bearer YOUR_API_TOKEN. Store it as a credential so it is not in the workflow JSON.
  4. Headers: add Idempotency-Key as an expression, for example {{ 'invoice:' + $json.order_id }}.
  5. Body: JSON, from the recipe.
  6. For scheduled syncs, put a Schedule Trigger in front, store meta.server_time in a workflow static-data field, and pass it back as updated_since next run (minus one minute; see Sync). Use Pagination on the HTTP node with page incrementing until meta.total_pages is reached.

Scripts

Everything below is plain HTTPS plus JSON; no SDK is required. There is no official client library yet, so pick your language's standard HTTP client and wrap these three things once: the base URL and token, an error handler that branches on status, and a retry loop for 409/429/5xx that keeps the same Idempotency-Key.

curl

curl "https://app.beeswaxapp.com/new_api/v1/invoices?outstanding=true&per_page=100" \
  -H "Authorization: Bearer $BEESWAX_TOKEN" \
  -H "User-Agent: acme-report/1.0"

Python

import os, requests

BASE = "https://app.beeswaxapp.com/new_api/v1"
S = requests.Session()
S.headers.update({"Authorization": f"Bearer {os.environ['BEESWAX_TOKEN']}",
                  "User-Agent": "acme-report/1.0"})

r = S.get(f"{BASE}/invoices", params={"outstanding": "true", "per_page": 100})
r.raise_for_status()
for inv in r.json()["invoices"]:
    print(inv["number"], inv["payable"], inv["due_on"])

Ruby

require "net/http"; require "json"; require "bigdecimal"

uri = URI("https://app.beeswaxapp.com/new_api/v1/invoices?outstanding=true&per_page=100")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch("BEESWAX_TOKEN")}"
req["User-Agent"]    = "acme-report/1.0"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
raise "#{res.code}: #{res.body}" unless res.is_a?(Net::HTTPSuccess)

JSON.parse(res.body)["invoices"].each do |inv|
  puts [inv["number"], BigDecimal(inv["payable"]).to_s("F"), inv["due_on"]].join("  ")
end

JavaScript (Node 18+)

const BASE = "https://app.beeswaxapp.com/new_api/v1";
const headers = { Authorization: `Bearer ${process.env.BEESWAX_TOKEN}`, "User-Agent": "acme-report/1.0" };

const res = await fetch(`${BASE}/invoices?outstanding=true&per_page=100`, { headers });
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const { invoices, meta } = await res.json();
console.log(meta.total_count, "outstanding");
for (const inv of invoices) console.log(inv.number, inv.payable, inv.due_on);

Google Sheets (Apps Script)

function pullOutstanding() {
  const token = PropertiesService.getScriptProperties().getProperty("BEESWAX_TOKEN");
  const res = UrlFetchApp.fetch("https://app.beeswaxapp.com/new_api/v1/invoices?outstanding=true&per_page=100",
    { headers: { Authorization: "Bearer " + token }, muteHttpExceptions: true });
  if (res.getResponseCode() !== 200) throw new Error(res.getContentText());
  const rows = JSON.parse(res.getContentText()).invoices.map(i => [i.number, i.title, i.due_on, Number(i.payable)]);
  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.clearContents();
  sheet.getRange(1, 1, rows.length + 1, 4).setValues([["Number", "Title", "Due", "Owing"], ...rows]);
}

Store the token in script properties, not in the sheet.


AI assistants (MCP)

The Beeswax MCP server (beeswax-mcp on npm, and a one-click extension for Claude Desktop) wraps this API for Claude and other MCP-capable apps. Every question the assistant asks becomes a normal, authenticated API call with the token you give it, so the same scopes and the same ledger rule apply. Setup for each app, connecting more than one account, and a full list of what the assistant can do are in Connect to Claude & AI assistants.

If you are building your own agent rather than using an MCP app: the ledger rule, Idempotency-Key on every write, and a scoped read-mostly token are the three things that keep an agent from doing damage. The MCP server's source is a worked example of all three.


Making an automation trustworthy

  • Scope the token to the job. A "new invoice → Slack" Zap needs invoices:read, nothing else.
  • Always send Idempotency-Key on writes from tools that can re-run a step. Zapier replays, n8n retries and Make re-executions are exactly the duplicate-creating events the header exists for.
  • Watch the token's *last used* in Account Settings; a live automation should keep it moving. A stale one has broken silently.
  • Keep an eye on the 300-requests-a-minute limit. A Zap that fires per row of a spreadsheet import can hit it; batch, or add a delay step.
  • Never put a token in a shared spreadsheet, a public workflow template or a browser extension. Use each tool's credential store.
Browse Topics