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
- Open Settings → Integrations, find API keys and choose Generate key.
- Give it a Key name after what will use it, such as Zapier or Online shop.
- 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.
- 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
- Open Settings → Integrations, find Webhooks and choose Add webhook.
- Paste the address the other app gave you into Endpoint URL.
- 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)
- In Zapier, make a Zap. For the trigger choose Webhooks by Zapier, event Catch Hook, and copy the address it shows.
- In Tamra, Add webhook, paste that address and tick Bill Posted.
- Post a bill in Tamra. Back in Zapier, Test trigger: the bill's message appears.
- 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)
- Make a key with the Write scope.
- In Zapier, trigger on a new row in your sheet. For the action choose Webhooks by Zapier → Custom Request.
- Method POST, address
https://www.tamraerp.com/api/v1/partners. - Headers: Authorization with the value
Bearer YOUR_KEY, and Content-Type with the valueapplication/json. - Data:
{ "name": "…", "type": "customer", "email": "…" }, with the sheet's columns put in.
Recipe 3 — Online shop orders as draft invoices (Zapier or Make)
- In Tamra, make one customer called Online shop and note its id (read it from /api/v1/partners).
- Trigger on a new order in your shop.
- 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. - 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 } ] }
- 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.