API Keys & Webhooks
Iraca can connect to your other systems two ways. API keys let an outside script or service pull data from Iraca. Webhooks let Iraca push a notification to your systems the moment something happens. Both live under Settings, and both are limited to owners and admins.
Want to ask an AI assistant about your data?
API keys are for scripts and integrations. To connect Claude or another AI assistant, use Talk to Iraca instead: its connection keys are read-only, follow each person's role, and work only with AI assistants.
API keys
An API key authenticates a script or external tool as your workspace, without a person signing in. They're built for pulling reporting data into another system — a BI tool, a scheduled export, an internal dashboard.
Creating a key
Open Settings → API Keys → Create API Key and give it:
- Name — something that identifies what's using it (e.g. "Looker dashboard," "Nightly export script").
- Abilities —
readand/orwrite. A mutating request (anything other thanGET) is rejected unless the key haswrite. - Expiry (optional) — a date after which the key stops working on its own.
Click Create, and the key's plain-text value is shown once. Copy it immediately — Iraca stores it hashed and can't show it to you again. If you lose it, delete the key and create a new one.
Using a key
Send it as a Bearer token, along with your workspace ID:
Authorization: Bearer <your-key>
X-Tenant-ID: <your-workspace-id>What a key can reach
API keys are deliberately restricted to a narrow, fixed set of endpoints — currently the dashboard summary and the Canopy reporting endpoints (inventory valuation, sales velocity, production efficiency, COGS, journal, trial balance, period locks). This list grows only as real integrations need it, so an exposed key can't be used to browse or change data outside of reporting.
Good to know
- Deleting a key revokes it immediately. There's no way to temporarily disable one — delete and, if needed, create a replacement.
- Keys are workspace-wide, not scoped to the person who created them. Any key can read everything the allowlist covers, regardless of who made it or their role.
- A signed-in session (the normal way you use Iraca) is unaffected by any of this — these restrictions only apply to API keys.
Webhooks
A webhook is the reverse direction: Iraca sends a signed HTTP POST to a URL you control whenever something happens in your workspace, so your systems don't have to poll for changes.
Setting one up
Open Settings → Webhooks → Add Endpoint and provide:
- Endpoint URL — where Iraca sends the notification.
- Events — pick the specific events you want, or leave all unchecked to receive everything (including events added in the future).
- Active — toggle a webhook off to pause deliveries without losing its configuration.
The endpoint must be a public address on the standard port: https:// on 443 (or http:// on 80), with no username or password in the URL. Addresses on a private or internal network, such as localhost, 10.x.x.x or 192.168.x.x, are refused when you save, and again before each delivery. Iraca doesn't follow redirects, so point the webhook at the final URL.
Verifying a delivery
Every delivery carries two headers:
X-Webhook-Event— the event name, e.g.order.fulfilled.X-Signature—sha256=<hmac>, an HMAC-SHA256 of the raw request body using your endpoint's signing secret.
The signing secret is shown once, right after you create the endpoint. If you didn't save it, delete the webhook and create a new one — there's currently no way to view an existing secret again.
To verify a delivery is genuinely from Iraca, recompute the HMAC yourself and compare:
$expected = 'sha256=' . hash_hmac('sha256', $rawRequestBody, $yourStoredSecret);
if (! hash_equals($expected, $request->header('X-Signature'))) {
abort(401);
}Every payload has the same envelope:
{
"event": "order.fulfilled",
"timestamp": "2026-09-19T14:32:00+00:00",
"payload": { "...": "event-specific fields" }
}Use the Send test button on an endpoint to fire a one-off test event and confirm your receiver is reachable and returns a success response.
Delivery retries
If your endpoint doesn't return a success response, Iraca retries up to 3 times with increasing delay (30s, 60s, then 120s) before giving up on that delivery.
Events and their payloads
| Event | payload fields |
|---|---|
order.created | order_id, type, source, status |
order.status_changed | order_id, status, previous_status |
order.fulfilled | order_id, source |
inventory.adjusted | product_id, product_name, sku, warehouse_id, type, quantity_on_hand |
inventory.low_stock | product_id, warehouse_id, quantity_on_hand, reorder_point |
production_run.completed | production_run_id, recipe_id, recipe_name, actual_quantity |
tenant.created | tenant_id, tenant_slug, plan_slug |
tenant.plan_changed | tenant_id, before, after |
tenant.status_changed | tenant_id, before, after |
tenant.shipping_updated | tenant_id, before, after |
tenant.subscription_created | plan, interval |
tenant.subscription_updated | status, stripe_status |
tenant.subscription_deleted | stripe_subscription_id |
tenant.payment_failed | invoice_id, amount_due, currency, attempt |
tenant.trial_expiring | tenant_id, tenant_slug, trial_ends_at, days_remaining |
tenant.trial_expired | tenant_id, tenant_slug, trial_ends_at, plan_slug |
inventory.low_stock fires once when a product crosses into low stock — not again on every later sale while it stays low. It uses the same definition as the low-stock list on your dashboard (a reorder point set above zero, the product active, and low-stock notifications enabled), so the two never disagree.
Good to know
- Leave events unchecked to subscribe to everything, including events Iraca adds after you set the webhook up.
- A webhook's signing secret is unique to that endpoint. If you run several endpoints, verify each delivery against the secret for the endpoint that received it.
- Deliveries happen in the background — creating an endpoint or an order won't wait on your server responding.