Torgix API
Read and write your equipment data, export in bulk, and subscribe to webhooks. REST over HTTPS, JSON in and out, scoped to your account.
The API is a paid add-on. An admin turns it on and issues keys in the app under Settings → API & Webhooks. Every request is tenant-scoped to the account that owns the key, so you only ever see and touch your own data.
Base URL
https://app.torgix.ai/v1
v1, pinned in the path. Additive changes (new fields, new resources) won't break you; we'll version the path before any breaking change.Authentication
Send your key as a bearer token on every request:
curl https://app.torgix.ai/v1/assets \ -H "Authorization: Bearer tgx_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Keys are created in the app; the full secret is shown once at creation, so store it somewhere safe. You can set an optional IP allowlist per key, and revoke a key at any time. Missing or invalid credentials return 401; a key whose account doesn't have the add-on active returns 403.
Scopes & modes
Each key carries one or more scopes. A request that needs a scope the key lacks returns 403 insufficient_scope.
| Scope | Grants |
|---|---|
read | List, get, and poll events. |
write | Create, update, and batch. |
export | Bulk export endpoints. |
Keys are issued in live or test mode (the mode is part of the key prefix, e.g. tgx_live_… / tgx_test_…) so you can keep sandbox integrations separate.
OAuth 2.0
For apps that act on behalf of an account, use the authorization-code flow with PKCE instead of a static key. An admin registers a client in the app under Settings → API & Webhooks → OAuth applications — choose public (PKCE only, for mobile/SPA) or confidential (also issued a client secret).
| Endpoint | URL |
|---|---|
| Authorize | https://app.torgix.ai/oauth/authorize |
| Token | https://app.torgix.ai/oauth/token |
1 · Send the user to authorize
Generate a PKCE code_verifier and its code_challenge = base64url(SHA-256(verifier)), then redirect:
https://app.torgix.ai/oauth/authorize?response_type=code
&client_id=tgxc_…
&redirect_uri=https://your-app/callback
&scope=read%20write
&state=xyz
&code_challenge=<challenge>&code_challenge_method=S256
The user signs in and approves; Torgix redirects back to your redirect_uri with ?code=…&state=….
2 · Exchange the code for tokens
curl https://app.torgix.ai/oauth/token \ -d grant_type=authorization_code \ -d code=<code> -d code_verifier=<verifier> \ -d redirect_uri=https://your-app/callback \ -d client_id=tgxc_… -d client_secret=tgxs_… # secret only for confidential clients
{ "access_token":"tgo_…", "token_type":"Bearer", "expires_in":3600,
"refresh_token":"tgo_…", "scope":"read write" }
3 · Call the API & refresh
Use the access token exactly like a key: Authorization: Bearer tgo_…. Access tokens last 1 hour; refresh with grant_type=refresh_token (refresh tokens last 30 days and rotate on each use, so store the newest one).
Requests & responses
Request bodies are JSON; set Content-Type: application/json on writes. Successful reads return an envelope:
{
"data": [ { "id": 142, "name": "Excavator 320", "status": "active" } ],
"next_cursor": "142",
"request_id": "req_8a1c2f…"
}
A single record returns { "data": { … }, "request_id": "…" }. Every response includes X-Request-Id (also echoed in the body) — quote it if you contact support.
Pagination & filtering
- Pagination is cursor-based. Read
next_cursorfrom a page and pass it as?cursor=to get the next one;nullmeans you've reached the end. Use?page_size=(default 50, max 200). - Field selection:
?fields=id,name,statusreturns only those fields. - Incremental sync:
?changed_since=2026-06-01T00:00:00Zreturns only records created/updated since that time. - Filtering: add any field as a query param for an exact match, e.g.
?status=active.
curl "https://app.torgix.ai/v1/work_orders?status=open&page_size=100" \ -H "Authorization: Bearer $TORGIX_KEY"
Rate limits & fair use
Requests are limited to 10 per second per key. Each response carries X-RateLimit-Limit and X-RateLimit-Remaining; exceeding the limit returns 429 with Retry-After. Back off and retry.
Monthly fair-use guardrails keep the platform healthy: 100,000 records read and 2,000 records exported per month. Writes are uncapped. You can watch your usage against these limits in the app under Settings → API & Webhooks → Usage.
Errors
Errors share one shape:
{
"error": {
"code": "insufficient_scope",
"message": "This credential lacks the write scope.",
"field": null,
"request_id": "req_8a1c2f…"
}
}
| Status | Meaning |
|---|---|
400 | Malformed request (bad JSON, empty body, bad batch). |
401 | Missing or invalid credentials. |
403 | Add-on inactive, missing scope, or IP not allowlisted. |
404 | Not found in your account. |
422 | Write rejected — field names the offending column. |
429 | Rate limited — honor Retry-After. |
Resources
Eighteen resources are exposed. All support reading and export; the table shows which also accept writes in v1.
| Resource | Path | Writes |
|---|---|---|
| Assets | /v1/assets | create + update |
| Locations | /v1/locations | create + update |
| Work orders | /v1/work_orders | create + update |
| Issues | /v1/issues | create + update |
| Maintenance logs | /v1/maintenance | create |
| Inspections | /v1/inspections | create |
| Fuel logs | /v1/fuel_logs | create |
| Meter readings | /v1/meter_readings | create |
| PM schedules | /v1/pm_schedules | read-only |
| Activities | /v1/activities | read-only |
| Projects | /v1/projects | read-only |
| Rentals | /v1/rentals | read-only |
| Customers | /v1/customers | read-only |
| Parts requests | /v1/parts | read-only |
| Parts orders | /v1/parts_orders | read-only |
| Inventory | /v1/inventory | read-only |
| Warranties | /v1/warranties | read-only |
| Users | /v1/users | read-only |
Fields mirror the record as you see it in the app. Pull a record with GET to learn its shape, or import the OpenAPI spec into Postman, Insomnia, or a code generator.
Reading
| Method | Path | Returns |
|---|---|---|
| GET | /v1/{resource} | A page of records. |
| GET | /v1/{resource}/{id} | One record. |
curl https://app.torgix.ai/v1/assets/142 \ -H "Authorization: Bearer $TORGIX_KEY"
Creating & updating
| Method | Path | Does |
|---|---|---|
| POST | /v1/{resource} | Create a record. |
| PATCH | /v1/{resource}/{id} | Update supplied fields. |
Your account is set automatically — company_id and internal columns (ids, timestamps) can't be supplied and are ignored. For child resources like meter readings or fuel logs, pass the asset_id; it's verified to belong to your account.
curl https://app.torgix.ai/v1/assets \ -H "Authorization: Bearer $TORGIX_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 7c1f-asset-import-0042" \ -d '{"name":"Excavator 320","asset_code":"EX-320","category":"Heavy"}'
Idempotency-Key on a create and a retry with the same key replays the original result instead of creating a duplicate (the response carries Idempotent-Replayed: true). A missing required field returns 422 with field set.Batch
POST /v1/{resource}/batch runs up to 200 create/update operations in one call. Each item reports its own status, so a bad row doesn't sink the batch.
curl https://app.torgix.ai/v1/meter_readings/batch \ -H "Authorization: Bearer $TORGIX_KEY" -H "Content-Type: application/json" \ -d '{"operations":[ {"method":"create","data":{"asset_id":142,"hours":1203}}, {"method":"create","data":{"asset_id":143,"hours":880}} ]}'
{ "results": [ {"status":201,"data":{…}}, {"status":201,"data":{…}} ], "request_id":"req_…" }
Export
GET /v1/{resource}/export (needs the export scope) bulk-pulls records — a JSON array, or newline-delimited JSON with ?format=ndjson. The same fields and changed_since filters apply. Results are capped by fair use with a truncated flag when there's more.
curl "https://app.torgix.ai/v1/assets/export?format=ndjson" \ -H "Authorization: Bearer $TORGIX_KEY"
Webhooks
Add an endpoint in the app under Settings → API & Webhooks, choose the events (or * for all), and Torgix will POST each matching event to your https:// URL. Event types follow <resource>.created / <resource>.updated.
POST your-endpoint X-Torgix-Event: assets.updated X-Torgix-Event-Id: evt_4f1c… X-Torgix-Signature: t=1719190000,v1=<hex> { "id": "evt_4f1c…", "type": "assets.updated", "resource": "assets", "resource_id": 142, "data": { "id": 142, "status": "active" }, "created_at": "2026-06-24T01:00:00Z" }
Respond 2xx within 8 seconds. Failed deliveries retry at 1 min, 5 min, 30 min, 2 hr, 6 hr, then dead-letter; you can resend any delivery from the app. To avoid loops when your integration writes back to Torgix, include the X-Torgix-Skip-Webhook header on those API calls and no event is emitted.
Verifying signatures
The X-Torgix-Signature header is t=<unix>,v1=<hex>, where the hex is HMAC-SHA256 of "{t}.{rawRequestBody}" keyed with the endpoint's signing secret. Compare with a constant-time check and reject timestamps older than 5 minutes.
// Node.js — verify a Torgix webhook const crypto = require('crypto'); function verify(rawBody, header, secret) { const [tp, vp] = header.split(','); const t = tp.split('=')[1], sig = vp.split('=')[1]; if (Math.abs(Date.now()/1000 - Number(t)) > 300) return false; // stale const expected = crypto.createHmac('sha256', secret) .update(t + '.' + rawBody).digest('hex'); return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig)); }
Polling
Prefer to pull rather than receive? GET /v1/events returns recent events for your account. Cursor forward with the cursor of the last item, and optionally filter with ?event_type=.
curl "https://app.torgix.ai/v1/events?event_type=assets.updated" \ -H "Authorization: Bearer $TORGIX_KEY"
Torgix