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 included with every Torgix account at no extra cost. 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.Quickstart
Three steps to your first response. No SDK required.
1 · Create a key
An admin opens Settings → API & Webhooks in the app, switches the API on, and creates a key. The full secret is shown once, so copy it straight into your environment:
export TORGIX_KEY=tgx_test_xxxxxxxxxxxxxxxxxxxxxxxx
2 · Make a call
curl https://app.torgix.ai/v1/assets \ -H "Authorization: Bearer $TORGIX_KEY"
3 · Read the envelope
{
"data": [ { "id": 142, "name": "Excavator 320", "status": "active" } ],
"next_cursor": "142",
"request_id": "req_8a1c2f…"
}
That is the whole shape. Every read returns data plus a cursor and a request id. From here, jump to pagination to walk a full list, creating & updating to write back, or webhooks to get pushed changes instead of polling for them.
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 has API access switched off 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, choosing 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 | API access switched off, 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 as 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"