Ask AwraIQ about features, pricing, onboarding, login, integrations, security, demos, mobile apps, automation, reports, or support.
Your workspace’s data, over HTTPS, with a key that already knows whose it is.
Read items and stock, customers and invoices, vendors and purchase orders. Create and update items, customers and vendors. Every call carries one API key, the key carries your organization, and each key holds only the scopes you gave it — so a reporting script can read and never write.
POST /api/v1/customers Authorization: Bearer awra_9fK2… Idempotency-Key: 7c1e0b4a-… Content-Type: application/json { "company_name": "Acme Ltd", "email": "[email protected]", "currency_code": "KES" }
{
"data": {
"id": 12,
"company_name": "Acme Ltd",
"email": "[email protected]"
}
}
# audit log actor:
# API key “CRM sync” The same request from a key that only holds developer:read
403 { "error": { "code": "insufficient_scope", "message": "… Required: sales:write." } }
developer:read and * never satisfy oneOne key per integration, and the key says who it belongs to.
Someone who holds the permission to manage API keys mints one, names it after the system that will use it, ticks its scopes and, if you want it to lapse, gives it an expiry. The token is shown once. Send it as a bearer token, or in an X-Api-Key header when your proxy keeps Authorization for itself.
- Scopes
- sales:readsales:write
- Expires
- in 365 days (optional, up to 730)
- Stored as
- a SHA-256 hash and the first ten characters, so the list can show which key is which
- Shown
- once, on the screen that minted it
GET /api/v1/me # the organization, the key’s name, prefix, # scopes, created and expiry dates
- Your organization is carried by the key
No route accepts an organization or workspace identifier from the caller. Every query is filtered on the key’s workspace, and a record that exists in another organization answers 404, so the API never confirms that an ID exists elsewhere.
- Rotate or revoke
Rotating revokes the old token at once and issues a new one with the same scopes and expiry. Revoking stops a key immediately. A revoked, inactive or expired key answers 401.
- Your IP allowlist binds keys too
If the workspace limits sign-in to certain addresses under Settings → Security, API calls from anywhere else are refused with 403
ip_not_allowed, before they count against any limit. - How many keys
Your plan sets how many active keys the workspace can hold. Separate keys per integration let you revoke one system without touching the others.
Reading is one decision. Writing is a second one, made by name.
Writes arrived on 15 October 2026. A key minted before that — developer:read or * — went on reading everything and did not gain the power to change a record. To write, a key needs the module’s write scope or the developer:write umbrella.
| Scope on the key | Read inventory | Read sales | Read procurement | Write items | Write customers | Write vendors |
|---|---|---|---|---|---|---|
inventory:read | — | — | — | — | — | |
sales:read | — | — | — | — | — | |
procurement:read | — | — | — | — | — | |
developer:read or * | — | — | — | |||
inventory:write | — | — | — | — | ||
sales:write | — | — | — | — | ||
procurement:write | — | — | — | — | ||
developer:write |
A module’s write scope also reads that module. A key with no scopes at all is refused rather than treated as all-access. /me answers any valid key, however narrow, so you can check a key before wiring it in.
Nineteen endpoints, grouped by the scope that opens them.
The API reference lists every filter and a sample response for each, and the same catalog is published as an OpenAPI document at /openapi.json for client generators.
Identity
any valid key/meInventory
inventory:read · inventory:write/items/items/{id}/categories/warehouses/items/items/{id}Sales
sales:read · sales:write/customers/customers/{id}/invoices/invoices/{id}/customers/customers/{id}Procurement
procurement:read · procurement:write/vendors/vendors/{id}/purchase-orders/purchase-orders/{id}/vendors/vendors/{id}Master data goes in over the API. Stock, money and approvals stay where their controls run.
An API key has no person behind it to keep out of their own approval, so the writes are the records an integration most often needs to keep in step — the item list, the customer list, the supplier list — and nothing that moves a balance.
A retry is not a duplicate
Send an Idempotency-Key header on a POST and a repeat of the same request returns the first result instead of creating a second item, customer or vendor.
Every write is on the audit log
Each create and update is recorded with the API key’s name as the actor, so the audit log shows which integration changed a record, not just that one did.
The answer is the record
A create returns 201 with the record in the same shape the read endpoints use, and an update returns it as it now stands. Send only the fields you are changing.
Your item rules still apply
Item creates and updates go through the same item master checks as the screens. A SKU must be unique in your organization, and a vendor’s email must be too.
Stock is refused
A new item starts at zero. A stock field is refused with 422; stock moves through adjustments, receipts and sales in the product. An item’s type is set when it is created and cannot be patched later.
Payout details are refused
Bank and mobile-money fields on a vendor answer 422. Where a supplier is paid changes in the product, where a second person can be required and the supplier is told. Reads leave those fields out as well.
Built for a nightly sync, not only for one lookup.
- Filter on the server. Items by search, category, type or low stock; invoices by status, customer, issue dates or unpaid; purchase orders by status, payment status, vendor or order dates; vendors by active or preferred.
- Ask for what changed.
updated_sincereturns records changed at or after a timestamp. An unparseable value is refused with 422 rather than ignored — an ignored filter would hand you a full export while you believed you had a delta. - Walk a whole resource with a cursor.
paginate=cursormakes page 1,000 cost what page 1 costs, and no row is skipped or repeated while records change underneath you. Followlinks.nextuntil it is null. - Or page by number. 25 a page by default and up to 100, with a total, for a screen that needs “page 3 of 12”.
- React instead of polling. A customer or vendor created over the API raises the same
customer.createdandvendor.createdwebhooks as one created on screen, so your other systems hear about it once.
GET /api/v1/items?updated_since=2026-10-27T00:00:00Z &paginate=cursor&per_page=100 Authorization: Bearer $AWRA_API_KEY
{
"data": [ … ],
"meta": { "pagination": "cursor", "per_page": 100, "has_more": true },
"links": { "next": "…?cursor=eyJpZCI6MTAwfQ", "prev": null }
}
# stop when links.next is null; never build a cursor yourself Two limits, and an error that tells you which one.
Counted against the key, not the IP address, so two customers behind one office network do not share a budget. Over it, a 429 with Retry-After.
Shared by all of the workspace’s keys and set by your plan; the plan comparison lists each figure. It resets at midnight UTC.
The daily count is taken only once a key is known to be valid, in scope and from an allowed address, so a stray token never uses up your allowance.
unauthorizedNo key, or a key that is unknown, revoked or expired. Check the credential; retrying will not help.insufficient_scopeA valid key without the scope this endpoint needs. The message names the scope required.ip_not_allowedThe workspace has an IP allowlist and the call came from outside it.not_foundNo such record in your organization, including records that exist in someone else’s.invalid_parameterA malformed query parameter. A write that fails validation, including a refused field such as stock, also answers 422 and names the field.daily_quota_exceededThe workspace has used today’s calls. Backing off within the day will not help.What AWRA OpsHub does today
- Thirteen read endpoints for your identity, items, categories, warehouses, customers, invoices with their lines, vendors and purchase orders with their lines.
- Six write endpoints that create and update items, customers and vendors.
- Keys minted in Settings, shown once, stored as a hash, with an optional expiry of up to two years, and rotated or revoked from the same screen.
- The organization carried by the key, with no identifier accepted from the caller and a 404 for any record outside it.
- Read scopes per module and write scopes by name, so a read key or an all-access key minted before writes never writes.
- Idempotent creates with an Idempotency-Key header, and every write on the audit log against the key.
- Server-side filters, updated_since, numbered pages and cursor paging on every list.
- 120 requests a minute per key, a daily allowance per workspace set by the plan, and the workspace’s IP allowlist applied to keys.
- A public reference and an OpenAPI document generated from the same catalog as the routes.
More we can add to your workspace
- Invoice, order and payment writes, created as drafts that still go through your approval rules before they count.
- Stock adjustments over the API, raised as pending adjustments for a person to approve, the way count variances are.
- Read endpoints for more modules, such as accounts and journals, fixed assets, employees and helpdesk tickets.
- Delete and archive endpoints, routed to the trash so a removal can be restored.
- Webhook subscriptions managed with an API key, alongside the settings screen that manages them today.
- Official client libraries for PHP, JavaScript and Python, generated from the OpenAPI document.
- Batch endpoints that take many records in one call with a per-record result.
- Sign in with AWRA for third-party apps, so a vendor’s app asks your people for access rather than being handed a key.
Where we point you to a specialist
- We will not accept a workspace identifier from the caller. The key decides whose data it is; a request cannot ask for someone else’s.
- We will not let a read key start writing. A key minted to read stays a read key, whatever scopes are added to the API later.
- We will not take a supplier’s bank or mobile-money details over the API. Where money is sent changes in the product, under dual control, with the supplier told.
Draft invoice writes and read endpoints for accounting are the two items in that middle column integrators ask for first. Tell us what your integration needs to send or read and we will come back with a written spec, a timeline and a price.
Where the Developer API meets the rest of your integrations.
Frequently asked questions
How do I get an API key?
Do I pass a workspace or company ID with each request?
Can the API create and update records?
Will my existing read key start writing?
What stops a retry creating a duplicate?
What are the rate limits?
Can I change a supplier’s bank details over the API?
Is there an OpenAPI description?
Help Center
Need a quick answer while you read?
Run inventory, procurement, assets, sales, and field work with approved AWRA guidance for setup, migration, integrations, security, pricing, and support.