Guide › Connecting other apps

Connecting other apps

Tamra connects to other software in two ways. Both are set up in Settings → Integrations.

  • Webhooks — Tamra tells another app when something happens: a bill posted, a purchase order submitted.
  • The API — another app reads from Tamra, or hands it a customer, a product or a draft invoice.

Automation apps such as Zapier, Make and n8n can use both through their generic Webhooks and HTTP request steps. Tamra does not have a tile of its own in their app lists yet, so set-up is a few minutes of copy and paste. Setting up keys and webhooks needs Integrations edit in the company (the built-in Super Admin has it).

What you can do

You want to… Use
Get a Slack message, an email or a row in a sheet when a bill is posted, a purchase order is submitted, payroll is computed or leave is decided A webhook
Read invoices, bills, customers and vendors, products, stock, the trial balance or your tax rates into a sheet or a dashboard The API, reading
Add a customer, a product or a draft invoice from another app: an online order, a form, a row in a sheet The API, creating

Make an API key

  1. Open Settings → Integrations, find API keys and choose Generate key.
  2. Give it a Key name after what will use it, such as Zapier or Online shop.
  3. Under Permissions tick what it may do. Read lets it view data. Write lets it create customers, vendors, products and draft invoices (it cannot change or delete what exists). Admin covers both. Give each key only what it needs.
  4. Copy the key when it appears. It is shown once and cannot be shown again. It looks like sb_live_ followed by 64 letters and numbers.

Treat a key like a password. A key belongs to the company it was made in and reads that whole company whatever role the person who made it has. When an app stops using it, revoke it in the same list.

Try it

In Terminal, with your own key in place of YOUR_KEY:

curl -H "Authorization: Bearer YOUR_KEY" "https://www.tamraerp.com/api/v1/invoices?limit=3"

You get back { "data": [ … ], "meta": { "count": …, "limit": 3 } }. An error comes back as { "error": "…" } and says what to fix.

Reading

Every list comes newest first, 50 at a time. Add limit=200 for more. For the next page, send before= with the created_at of the last row you got.

Address What it gives Filters
/api/v1/invoices number, customer (partner_id), status, dates, currency, VAT, total, amount paid and amount due status, partner_id
/api/v1/bills the same for bills, with the vendor as partner_id status, partner_id
/api/v1/partners customers and vendors: name, email, phone, TRN, currency type = customer or vendor
/api/v1/products name, SKU, barcode, type, sale price type = stockable, service or consumable
/api/v1/stock quantity on hand by product and location product_id
/api/v1/trial-balance the trial balance as_of = a date, such as 2026-10-31
/api/v1/tax-rates your tax rates, with the id a line can name

Add / and an id to read one invoice, bill, customer or vendor, product or tax rate.

Creating

Send a POST with a JSON body and the header Content-Type: application/json. The key needs the Write scope.

  • Customer or vendor — /api/v1/partners: name (required), type (customer or vendor; customer if left out), email, phone, trn, currency_id (your company's currency if left out).
  • Product — /api/v1/products: name (required), type (service if left out), sku, barcode, sale_price, uom_id (counted in Units if left out).
  • Draft invoice — /api/v1/invoices: partner_id (required; a customer of this company) and lines (1 to 100). Each line has a product_id or a description, a quantity above zero, a unit_price, and optionally a tax_id. You can also send date, due_date, currency_id, exchange_rate and notes.

An invoice made this way is a draft with no number. VAT is on each line, at the rate the line names, else the product's own sales rate, else your default sales rate. Someone in Tamra posts it, and it takes the next invoice number then.

Send an Idempotency-Key header with a value that is unique to the thing you are creating, such as the shop's order number. If the same request is sent again, Tamra answers with the first result and marks it replayed, instead of creating a second one. Keys are remembered for 7 days.

Webhooks

  1. Open Settings → Integrations, find Webhooks and choose Add webhook.
  2. Paste the address the other app gave you into Endpoint URL.
  3. Tick the Events to subscribe to.
Event When
purchase_order.submitted a purchase order is submitted
bill.posted a bill is posted
payroll.computed a payroll run is computed
leave.decided leave is approved or rejected
codex.mention (shown as Codex Mention) someone is mentioned on a Scribe page
All events everything Tamra raises as a notification, except chat

What arrives is a POST with this body:

{ "event": "bill.posted", "company_id": "…", "created_at": "…",
  "data": { "type": "bill.posted", "title": "…", "body": "…", "link": "…" } }

The message says what happened and links to it. It does not carry the whole record. When you need the amounts, read the record through the API.

Each call carries three headers: X-SmartBook-Event, X-SmartBook-Delivery (the same on every retry, so you can ignore a repeat) and X-SmartBook-Signature. The signature is sha256= followed by the HMAC-SHA256 of the body, made with the webhook's own signing secret. The Secret button on the webhook's line shows the secret, with a Copy button, for people with Integrations edit. Zapier and Make don't need it.

How delivery works

  • Tamra sends within about a minute of the event.
  • An answer in the 2xx range within 8 seconds counts as delivered.
  • Anything else is tried again, up to five times in all, with longer gaps each time (about 1, 2, 4 and 8 minutes). Then it stops.
  • The same event with the same link inside 15 seconds is sent once.
  • Recent deliveries, at the foot of the page, lists every attempt and how it ended, for 30 days. Redeliver sends a failed one again.

Recipe 1 — A Slack message when a bill is posted (Zapier)

  1. In Zapier, make a Zap. For the trigger choose Webhooks by Zapier, event Catch Hook, and copy the address it shows.
  2. In Tamra, Add webhook, paste that address and tick Bill Posted.
  3. Post a bill in Tamra. Back in Zapier, Test trigger: the bill's message appears.
  4. For the action choose Slack → Send Channel Message, and use the title, body and link from the message.

Recipe 2 — A new customer from a spreadsheet row (Zapier)

  1. Make a key with the Write scope.
  2. In Zapier, trigger on a new row in your sheet. For the action choose Webhooks by Zapier → Custom Request.
  3. Method POST, address https://www.tamraerp.com/api/v1/partners.
  4. Headers: Authorization with the value Bearer YOUR_KEY, and Content-Type with the value application/json.
  5. Data: { "name": "…", "type": "customer", "email": "…" }, with the sheet's columns put in.

Recipe 3 — Online shop orders as draft invoices (Zapier or Make)

  1. In Tamra, make one customer called Online shop and note its id (read it from /api/v1/partners).
  2. Trigger on a new order in your shop.
  3. Action: a Custom Request (in Make, HTTP → Make a request) with method POST to https://www.tamraerp.com/api/v1/invoices, the same two headers as Recipe 2, and one more: Idempotency-Key with the shop's order number.
  4. Body:
{ "partner_id": "THE_ONLINE_SHOP_ID", "date": "2026-10-18",
  "notes": "Shop order 1042",
  "lines": [ { "description": "Khalas dates 1 kg", "quantity": 2, "unit_price": 38.00 } ] }
  1. In Tamra, the drafts wait under Invoices. Check them, post them, and record the money as you do for any invoice.

An order with several items is easier in Make, which handles a list of items directly. In Zapier it needs its line item tools.

What it doesn't do yet

  • There is no Tamra tile in Zapier's or Make's app lists.
  • The API cannot edit or delete, post an invoice, record a payment or create a bill. Posting stays with the people in Tamra.
  • The API cannot look a customer up by email or name. You can list customers and filter by type, so an app that creates a customer for every order would create duplicates. Use one customer, as in Recipe 3, or create each customer once.
  • A webhook message is a title, some text and a link. It is not the whole record.
  • A key covers one company and everything in it.

Common questions

Which company does a key belong to? The one it was made in. Each company makes its own keys.

Can I make a key that only reads? Yes. Tick Read and nothing else.

I lost a key. Make a new one, change it in the other app, and revoke the old one.

An event arrived twice. Check X-SmartBook-Delivery. A retry carries the same value as the first try.

If something goes wrong

  • 401 — the key is missing, mistyped, revoked or expired. Send it exactly as Authorization: Bearer sb_live_….
  • 403 — the key lacks the scope: Read to read, Write to create.
  • 400 — the message says what to fix, such as a partner_id that is not in this company or a tax_id that is not one of your sales rates.
  • Nothing arrives at the other app — open Recent deliveries. It shows the last answer the other app gave. Check the address, that the webhook is Active and not Paused, and that the event is ticked, then press Redeliver.