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

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

  1. Tokens are client-scoped - A token from Client A cannot access Client B's data
  2. Tokens stored per-client - The api_tokens table is in each client's database
  3. Client ID still required - When using a token, include X-Client-ID header

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 token value 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"
}
  • null expiration = 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"
  }'