Skip to main content

Tagaris REST API v1

The API lets external tools read and write assets, people, locations, issues, vendors and purchase orders: reporting tools, a service desk, or your own automation. It is versioned under /api/v1 and authenticated with a token you create in the app.

API access is included on every plan, the free plan too, and needs no licence key; see Licensing.

The mobile app's endpoints are separate​

The Tagaris mobile app talks to its own endpoints under /api/app, signed in with the user's own session (password or single sign-on) rather than an API key. That surface ships with the app, may change between app releases, and is not covered by the v1 stability promise. Build your integrations against /api/v1 only.

Authentication​

There are two kinds of key, both shown once (only a hash is stored, so a lost key cannot be recovered and must be replaced), and both with an expiry you choose when you create them (30, 90, 180 or 365 days, or never). An expired key returns 401.

  • Personal keys (My account, API keys). Any user can create their own. A personal key acts as that user and is limited to what they may do: their role plus their access groups. A view-only person with no access group only ever gets a read key; with one, their key can make exactly the changes the group allows, and any other write returns 403 naming the permission. A personal key also follows its owner's site limit: assets and locations at other sites are not returned. Changes are recorded as that person. If their access is later reduced or they leave the organisation, the key loses that access automatically.
  • Organisation keys (Settings, API keys, an administrator only). For headless integrations. Not tied to a person; they act for the whole organisation with the scopes the admin grants.

The API can be turned off install-wide by the install owner (Application, API) or with the API_ENABLED=false environment variable. When it is off, every request returns 403 regardless of the key.

Send the token as a bearer token:

Authorization: Bearer tag_xxxxxxxxxxxxxxxxxxxxxxxx

A token has one org and a set of scopes:

  • read: GET requests.
  • write: POST, PATCH and DELETE. A read-only token gets 403 on writes.

All data is scoped to the token's org. A token cannot see or change another org's records.

Rate limit​

Requests are limited to 120 per minute per token. Over the limit returns:

429 Too Many Requests
Retry-After: 60

Responses and errors​

Successful reads and writes return { "data": ... }. List endpoints return { "data": [...], "total", "limit", "offset" }. Errors return { "error": "message" }, and validation errors add { "fieldErrors": { field: message } }.

StatusMeaning
200OK
201Created
400Bad request (for example invalid JSON)
401Missing or invalid token
403Token lacks the required scope
404Not found in your org
422Validation failed
429Rate limit exceeded

Assets​

  • GET /api/v1/assets?limit=&offset=&q=&status= list (limit up to 200, default 50). q searches name, tag, serial, manufacturer, model, hostname and IP address; status filters by one status value. With no filters the list includes every asset, disposed ones included, so existing integrations see unchanged totals.
  • POST /api/v1/assets create. Body fields match the asset form: name (required), status, assetTag (optional, auto-generated when blank), categoryId, locationId, assignedToId, withAssignee (boolean: the asset is with its assignee rather than at a location, requires assignedToId and clears locationId), serialNumber, manufacturer, model, supplier, purchaseDate (YYYY-MM-DD), warrantyEnd, purchasePrice, ipAddress, hostname, macAddress, notes.
  • GET /api/v1/assets/{id} fetch one.
  • PATCH /api/v1/assets/{id} update. Send only the fields you want to change.
  • DELETE /api/v1/assets/{id} delete.

Example:

curl -X POST https://your-host/api/v1/assets \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Reception iPad","status":"IN_USE","manufacturer":"Apple"}'

People​

  • GET /api/v1/people
  • POST /api/v1/people body: name (required), email (optional).
  • GET /api/v1/people/{id}
  • PATCH /api/v1/people/{id}
  • DELETE /api/v1/people/{id}

Locations​

  • GET /api/v1/locations
  • POST /api/v1/locations body: name (required), parentId (optional, must be another location in your org).
  • GET /api/v1/locations/{id}
  • PATCH /api/v1/locations/{id} a location cannot be its own parent.
  • DELETE /api/v1/locations/{id}

Issues​

  • GET /api/v1/issues open issues, newest first, 500 at most. status=all, OPEN, IN_PROGRESS or RESOLVED changes which; assetId= narrows to one asset.
  • POST /api/v1/issues body: title (required), description, assetId, categoryId, priority (LOW, NORMAL, HIGH), assigneeId (a user in your org), and setRepair: true to also set the asset to Repair.
  • GET /api/v1/issues/{id} one issue with its notes.

An issue raised with a personal key is reported by that user. One raised with an organisation key has no person behind it and says so. Changing and resolving issues is done in the app. See Issues.

Vendors​

  • GET /api/v1/vendors every vendor, the ones in use first.
  • POST /api/v1/vendors body: name (required), plus any of website, accountNumber, contactName, email, phone, address, supportUrl, supportPhone, notes. A name you already have returns 422.
  • GET /api/v1/vendors/{id}
  • PATCH /api/v1/vendors/{id} send only what changes. active: false marks a vendor as no longer used. Renaming also renames it on everything bought from them.
  • DELETE /api/v1/vendors/{id} what was bought from the vendor keeps the name as text.

You rarely need to create vendors first. supplier on an asset is matched to a vendor by name, ignoring case and spacing, and a new name creates the vendor. The asset's supplier field is unchanged for existing integrations. See Vendors and contracts.

Purchase orders​

  • GET /api/v1/purchase-orders open orders (draft, ordered, part received), newest first, 500 at most, each with its lines. status=all, or DRAFT, ORDERED, PARTIAL, RECEIVED or CANCELLED, changes which; vendorId= narrows to one vendor; q= searches numbers, references, vendors and line descriptions.
  • POST /api/v1/purchase-orders creates a draft. Body: vendor (a name, matched or created like an asset's supplier), number (optional, else the next one), orderedAt, expectedAt, vendorReference, requestedById (a person), notes, and lines: a list of { kind, description, quantity, unitPrice, categoryId, templateId }. kind is ASSET, ACCESSORY, COMPONENT, CONSUMABLE, LICENCE or SERVICE.
  • GET /api/v1/purchase-orders/{id} asset lines include the assets received on them.
  • PATCH /api/v1/purchase-orders/{id} send only what changes. lines, when sent, is the whole list: a line with an id is updated, one without is added, one left out is removed. A line that has had items received cannot be removed or change kind.
  • DELETE /api/v1/purchase-orders/{id} drafts only (409 otherwise).

Marking an order as ordered, cancelling it and receiving deliveries are done in the app. total and each line's receivedQuantity are read-only. See Purchase orders.

Health check​

GET /api/health needs no token and returns { "status": "ok", "db": "up" } when the app and database are reachable, or 503 with { "status": "degraded" } when the database is down. Use it for uptime monitoring.

Notes​

  • Relations are referenced by id (categoryId, locationId, assignedToId, parentId). Ids must belong to your org or the request returns 422.
  • Deleting a category, location or person that assets reference sets that link to empty on those assets; the assets are kept.

Stability​

v1 is stable: fields may be added, but existing fields and endpoints will not change shape or be removed under /api/v1. Any breaking change ships under a new version prefix, so a token-authed client can rely on v1.