API tokens provide programmatic access to the TGM Expert API with granular permission control. Use tokens for integrations, scripts, CI/CD pipelines, and other automated systems.
Table of Contents¶
- Overview
- Multi-Tenancy Context
- Creating Tokens
- Using Tokens
- Permission Management
- Token Lifecycle
- Admin API
- Security Best Practices
Overview¶
Key Features¶
- Granular Permissions - Control access per resource and action
- Full Access Mode - Optionally grant full API access
- Expiration - Tokens can have expiration dates
- Revocation - Instantly revoke compromised tokens
- Audit Trail - All token usage is logged
- Multi-Tenant Scope - Tokens are scoped to a specific client
Multi-Tenancy Context¶
API tokens are scoped within TGM's multi-tenant architecture:
┌─────────────────────────────────────────────────────────────────┐
│ Platform Level │
│ (No platform-wide API tokens) │
└─────────────────────────────────────────────────────────────────┘
│
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Client A │ │ Client B │ │ Client C │
│ Database │ │ Database │ │ Database │
├───────────────┤ ├───────────────┤ ├───────────────┤
│ api_tokens │ │ api_tokens │ │ api_tokens │
│ (table) │ │ (table) │ │ (table) │
│ │ │ │ │ │
│ Token A-1 │ │ Token B-1 │ │ Token C-1 │
│ Token A-2 │ │ Token B-2 │ │ │
└───────────────┘ └───────────────┘ └───────────────┘
Key Points¶
- Tokens are client-scoped - A token from Client A cannot access Client B's data
- Tokens stored per-client - The
api_tokenstable is in each client's database - Client ID still required - When using a token, include
X-Client-IDheader
Using Tokens with Multi-Tenancy¶
# Using API token - still requires X-Client-ID
curl -X GET "http://localhost:1337/api/inspections" \
-H "Authorization: Bearer tgm_xxxxxxxxxxxx" \
-H "X-Client-ID: acme-corp"
# Or via subdomain
curl -X GET "https://acme-corp.tgm-expert.com/api/inspections" \
-H "Authorization: Bearer tgm_xxxxxxxxxxxx"
Token vs JWT¶
| Aspect | API Token | JWT |
|---|---|---|
| Purpose | Machine/Integration | User sessions |
| Expiration | Configurable | 24 hours |
| Permissions | Token-specific | User's permissions |
| Revocation | Instant | Requires blacklist |
| Format | tgm_xxxxxxxxxx |
eyJhbGciOiJI... |
| Scope | Client-specific | Client-specific |
Creating Tokens¶
Create Token Request¶
curl -X POST https://api.tgm-expert.com/api/admin/tokens \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Integration",
"description": "Used for syncing data with ERP system",
"expiresAt": "2027-01-01T00:00:00Z",
"isFullAccess": false,
"permissions": [
{
"resourceName": "inspections",
"canCreate": true,
"canRead": true,
"canUpdate": true,
"canDelete": false
},
{
"resourceName": "work_orders",
"canCreate": true,
"canRead": true,
"canUpdate": true,
"canDelete": false
},
{
"resourceName": "units",
"canRead": true
}
]
}'
Response¶
{
"data": {
"id": 1,
"name": "Production Integration",
"description": "Used for syncing data with ERP system",
"token": "tgm_abc123def456ghi789jkl012mno345pqr678stu901vwx234yz",
"tokenPreview": "tgm_abc...234yz",
"status": "ACTIVE",
"isFullAccess": false,
"expiresAt": "2027-01-01T00:00:00Z",
"permissions": [
{
"resourceName": "inspections",
"canCreate": true,
"canRead": true,
"canUpdate": true,
"canDelete": false,
"canPublish": false
}
],
"createdAt": "2026-02-01T00:00:00Z"
},
"meta": {
"message": "Token created. Save the token value - it won't be shown again."
}
}
Important: Save the
tokenvalue immediately. The full token is only returned once during creation.
Full Access Token¶
For tokens that need access to all resources:
{
"name": "Admin Integration",
"isFullAccess": true,
"expiresAt": "2027-01-01T00:00:00Z"
}
Using Tokens¶
Authentication¶
Include the token in the Authorization header:
curl -X GET https://api.tgm-expert.com/api/inspections \
-H "Authorization: Bearer tgm_abc123def456ghi789jkl012mno345pqr678stu901vwx234yz"
Token Format¶
Tokens follow this format:
tgm_{64_character_random_string}
Example:
tgm_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
Request Examples¶
List Resources¶
curl -X GET "https://api.tgm-expert.com/api/inspections?page=1&pageSize=25" \
-H "Authorization: Bearer tgm_xxx..."
Create Resource¶
curl -X POST https://api.tgm-expert.com/api/inspections \
-H "Authorization: Bearer tgm_xxx..." \
-H "Content-Type: application/json" \
-d '{
"title": "Monthly Inspection",
"unitId": 100,
"scheduledDate": "2026-02-15"
}'
Update Resource¶
curl -X PUT https://api.tgm-expert.com/api/inspections/123 \
-H "Authorization: Bearer tgm_xxx..." \
-H "Content-Type: application/json" \
-d '{
"status": "completed"
}'
Permission Management¶
Available Resources¶
| Resource | Description |
|---|---|
location |
Locations/plants |
unit |
Equipment units |
component |
Unit components |
component_group |
Component groups |
sub_assembly |
Sub-assemblies |
inspection |
Inspections |
intervention |
Interventions |
failure |
Failure records |
incident |
Incidents |
work_order |
Work orders |
maintenance_plan |
Maintenance plans |
spare_part |
Spare parts |
sensor |
Sensors |
sensor_reading |
Sensor readings |
alert |
Alerts |
drawing |
Drawings |
document |
Documents |
project |
Projects |
capex_project |
CAPEX projects |
asset_lifecycle |
Asset lifecycle |
notification |
Notifications |
todo |
Todos |
comment |
Comments |
user |
Users |
role |
Roles |
api_token |
API tokens |
Permission Actions¶
| Action | Description |
|---|---|
canCreate |
Create new records |
canRead |
View/list records |
canUpdate |
Modify existing records |
canDelete |
Delete records |
canPublish |
Publish/approve records |
Permission Examples¶
Read-Only Access¶
{
"resourceName": "inspections",
"canRead": true
}
Full CRUD Access¶
{
"resourceName": "inspections",
"canCreate": true,
"canRead": true,
"canUpdate": true,
"canDelete": true
}
Create and Read Only¶
{
"resourceName": "sensor_reading",
"canCreate": true,
"canRead": true
}
Updating Permissions¶
curl -X PUT https://api.tgm-expert.com/api/admin/tokens/1 \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"permissions": [
{
"resourceName": "inspections",
"canCreate": true,
"canRead": true,
"canUpdate": true,
"canDelete": true
}
]
}'
Token Lifecycle¶
Token States¶
| Status | Description |
|---|---|
ACTIVE |
Token is valid and can be used |
EXPIRED |
Token has passed expiration date |
REVOKED |
Token was manually revoked |
Expiration¶
Tokens can have optional expiration:
{
"name": "Temporary Token",
"expiresAt": "2026-03-01T00:00:00Z"
}
nullexpiration = token never expires- Expired tokens return
401 Unauthorized
Revocation¶
Immediately revoke a compromised token:
curl -X POST https://api.tgm-expert.com/api/admin/tokens/1/revoke \
-H "Authorization: Bearer $JWT_TOKEN"
Revoked tokens cannot be re-activated.
Regeneration¶
Generate a new token value while keeping settings:
curl -X POST https://api.tgm-expert.com/api/admin/tokens/1/regenerate \
-H "Authorization: Bearer $JWT_TOKEN"
Response includes the new token (only shown once).
Admin API¶
Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/admin/tokens |
List all tokens |
| GET | /api/admin/tokens/{id} |
Get token details |
| POST | /api/admin/tokens |
Create token |
| PUT | /api/admin/tokens/{id} |
Update token |
| DELETE | /api/admin/tokens/{id} |
Delete token |
| POST | /api/admin/tokens/{id}/revoke |
Revoke token |
| POST | /api/admin/tokens/{id}/regenerate |
Regenerate token |
| GET | /api/admin/tokens/resource-names |
List available resources |
List Tokens¶
curl -X GET https://api.tgm-expert.com/api/admin/tokens \
-H "Authorization: Bearer $JWT_TOKEN"
Response:
{
"data": [
{
"id": 1,
"name": "Production Integration",
"tokenPreview": "tgm_abc...234yz",
"status": "ACTIVE",
"isFullAccess": false,
"lastUsedAt": "2026-02-01T12:00:00Z",
"expiresAt": "2027-01-01T00:00:00Z",
"permissionsSummary": "inspections: CRUD, work_orders: CRU, units: R"
}
]
}
Get Token Details¶
curl -X GET https://api.tgm-expert.com/api/admin/tokens/1 \
-H "Authorization: Bearer $JWT_TOKEN"
Delete Token¶
curl -X DELETE https://api.tgm-expert.com/api/admin/tokens/1 \
-H "Authorization: Bearer $JWT_TOKEN"
Security Best Practices¶
1. Use Minimal Permissions¶
Grant only the permissions actually needed:
// Good - specific permissions
{
"permissions": [
{"resourceName": "inspections", "canRead": true}
]
}
// Bad - unnecessary full access
{
"isFullAccess": true
}
2. Set Expiration Dates¶
Always set reasonable expiration dates:
{
"expiresAt": "2026-06-01T00:00:00Z"
}
3. Rotate Tokens Regularly¶
Regenerate tokens periodically:
curl -X POST ".../tokens/1/regenerate"
4. Monitor Usage¶
Check lastUsedAt for suspicious activity:
curl -X GET ".../tokens/1"
5. Revoke Unused Tokens¶
Delete or revoke tokens that are no longer needed:
curl -X POST ".../tokens/1/revoke"
6. Secure Storage¶
- Never commit tokens to source control
- Use environment variables or secrets managers
- Don't log full token values
7. Use Descriptive Names¶
Name tokens clearly for auditing:
{
"name": "GitHub Actions - Production Deploy",
"description": "Used by CI/CD for production deployments"
}
8. Separate Environments¶
Use different tokens for dev/staging/production:
tgm_dev_xxx... - Development
tgm_stg_xxx... - Staging
tgm_prd_xxx... - Production
Error Responses¶
Token Errors¶
| Status | Code | Description |
|---|---|---|
| 401 | INVALID_TOKEN |
Token not found or malformed |
| 401 | TOKEN_EXPIRED |
Token has expired |
| 401 | TOKEN_REVOKED |
Token was revoked |
| 403 | INSUFFICIENT_PERMISSIONS |
Token lacks required permission |
Error Response Format¶
{
"error": {
"status": 403,
"code": "INSUFFICIENT_PERMISSIONS",
"message": "Token does not have 'inspections:create' permission"
}
}
Integration Examples¶
Python¶
import requests
TOKEN = "tgm_abc123..."
BASE_URL = "https://api.tgm-expert.com"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
}
# List inspections
response = requests.get(f"{BASE_URL}/api/inspections", headers=headers)
inspections = response.json()["data"]
# Create inspection
new_inspection = {
"title": "Automated Inspection",
"unitId": 100,
"scheduledDate": "2026-02-15"
}
response = requests.post(
f"{BASE_URL}/api/inspections",
headers=headers,
json=new_inspection
)
Node.js¶
const axios = require('axios');
const TOKEN = 'tgm_abc123...';
const BASE_URL = 'https://api.tgm-expert.com';
const api = axios.create({
baseURL: BASE_URL,
headers: {
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'application/json'
}
});
// List inspections
const { data } = await api.get('/api/inspections');
console.log(data.data);
// Create inspection
const response = await api.post('/api/inspections', {
title: 'Automated Inspection',
unitId: 100,
scheduledDate: '2026-02-15'
});
cURL Script¶
#!/bin/bash
TOKEN="tgm_abc123..."
BASE_URL="https://api.tgm-expert.com"
# List inspections
curl -X GET "$BASE_URL/api/inspections" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json"
# Create inspection
curl -X POST "$BASE_URL/api/inspections" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Automated Inspection",
"unitId": 100,
"scheduledDate": "2026-02-15"
}'