Skip to content

TMI API Clients

Eric Fitzgerald edited this page Nov 12, 2025 · 1 revision

TMI API Clients

REST client libraries for the TMI threat modeling API in multiple languages.

Overview

The TMI API Clients repository contains auto-generated client libraries for interacting with the TMI (Threat Modeling Improved) REST API. These clients provide strongly-typed interfaces for working with threat models, diagrams, assets, threats, and other TMI resources in your preferred programming language.

Repository: /Users/efitz/Projects/tmi-clients

Available Languages

  • Python - tmi_client package (most mature, includes bug fixes)
  • JavaScript - tmi-js-client npm package
  • Go - Go module
  • Java - Maven package

All clients are generated from the TMI OpenAPI specification using swagger-codegen 3.0.75.

Features

  • Full REST API coverage for all TMI endpoints
  • Strongly-typed models matching OpenAPI schemas
  • Built-in request/response handling
  • OAuth 2.0 and SAML authentication support
  • AntV X6 graph library compatibility for diagrams
  • Comprehensive API documentation

Python Client

The Python client is the primary focus with modern packaging and bug fixes.

Installation

Using pip

pip install git+https://github.com/YOUR_ORG/tmi-clients.git#subdirectory=python-client-generated

Using uv (recommended)

cd python-client-generated
uv sync

Quick Start

from __future__ import print_function
import time
import tmi_client
from tmi_client.rest import ApiException
from pprint import pprint

# Configure API client
configuration = tmi_client.Configuration()
configuration.host = "https://api.tmi.dev"
configuration.access_token = "YOUR_JWT_TOKEN"

# Create API instance
api_client = tmi_client.ApiClient(configuration)
api_instance = tmi_client.ThreatModelsApi(api_client)

try:
    # List threat models
    threat_models = api_instance.list_threat_models()
    pprint(threat_models)
except ApiException as e:
    print(f"Exception when calling ThreatModelsApi: {e}")

Working with Diagrams

The Python client has been patched to properly handle diagram operations:

Creating a Diagram

from tmi_client.models.create_diagram_request import CreateDiagramRequest

# Create diagram request
request = CreateDiagramRequest(
    name="My Data Flow Diagram",
    type="DFD-1.0.0"
)

# Create the diagram
api = tmi_client.ThreatModelSubResourcesApi(api_client)
diagram = api.create_threat_model_diagram(request, threat_model_id)

Updating a Diagram

Important: Use DfdDiagramInput for updates, NOT DfdDiagram:

from tmi_client.models.dfd_diagram_input import DfdDiagramInput

# Correct - DfdDiagramInput for updates (no readOnly fields)
update = DfdDiagramInput(
    type="DFD-1.0.0",
    name="Updated Diagram Name",
    cells=[
        {
            "id": "node-1",
            "shape": "process",
            "x": 100,
            "y": 100,
            "width": 120,
            "height": 60,
            "attrs": {
                "body": {"fill": "#E1F5FE"},
                "text": {"text": "Web Server"}
            }
        }
    ]
)

updated_diagram = api.update_threat_model_diagram(update, tm_id, diagram_id)

Reading a Diagram

# Returns DfdDiagram (with readOnly fields: id, created_at, modified_at)
diagram = api.get_threat_model_diagram(threat_model_id, diagram_id)
print(f"Diagram: {diagram.name}")
print(f"Created: {diagram.created_at}")
print(f"Cells: {len(diagram.cells)}")

Input vs Output Schemas

The API uses separate schemas for input and output operations:

  • Input schemas (*Input classes): Used for POST/PUT operations, exclude readOnly fields
  • Output schemas (base classes): Returned from GET operations, include all fields including readOnly

This pattern applies to:

  • DfdDiagram (output) vs DfdDiagramInput (input)
  • Other resources following the same convention

Working with Assets

from tmi_client.models.asset import Asset

# Create an asset
asset = Asset(
    name="User Database",
    type="data-store",
    description="PostgreSQL database storing user data"
)

created_asset = api.create_threat_model_asset(asset, threat_model_id)

Working with Threats

from tmi_client.models.threat import Threat

# Create a threat
threat = Threat(
    name="SQL Injection",
    description="Attacker could inject SQL commands",
    severity="high",
    status="open",
    affected_assets=[asset_id]
)

created_threat = api.create_threat_model_threat(threat, threat_model_id)

Cell Structure for Diagrams

Diagrams use the AntV X6 graph library format for cells (nodes and edges):

# Node example
node = {
    "id": "node-uuid",
    "shape": "process",
    "x": 100,
    "y": 100,
    "width": 120,
    "height": 60,
    "attrs": {
        "body": {"fill": "#E1F5FE"},
        "text": {"text": "Web Component"}
    }
}

# Edge example
edge = {
    "id": "edge-uuid",
    "shape": "edge",
    "source": {"cell": "source-node-id"},
    "target": {"cell": "target-node-id"},
    "attrs": {"line": {"stroke": "#333"}}
}

Testing

Run tests using pytest:

cd python-client-generated

# Run all tests
uv run --with pytest python3 -m pytest test/ -v

# Run specific test file
uv run --with pytest python3 -m pytest test/test_dfd_diagram.py -v

# Run with coverage
uv run --with pytest --with pytest-cov python3 -m pytest test/ --cov=tmi_client --cov-report=term

Multi-version Testing with Tox

Test against Python 3.8-3.14:

cd python-client-generated

# Test all versions
tox

# Test specific version
tox -e py311

# Run with pytest arguments
tox -- -k test_dfd_diagram

API Classes

Key API classes for common operations:

  • ThreatModelSubResourcesApi - Primary API for threat models, diagrams, assets, threats
  • ThreatModelsApi - Threat model CRUD operations
  • AuthenticationApi - OAuth2/SAML authentication
  • AssetsApi - Asset-specific operations
  • ThreatsApi - Threat-specific operations including bulk operations
  • DocumentsApi - Document management
  • NotesApi - Notes and documentation
  • RepositoriesApi - Source code repository references

JavaScript Client

The JavaScript/Node.js client provides the same API coverage with JavaScript conventions.

Installation

npm install tmi-js-client --save

Or install from git:

npm install YOUR_ORG/tmi-clients#subdirectory=javascript-client-generated --save

Quick Start

var TmiJsClient = require("tmi-js-client");
var defaultClient = TmiJsClient.ApiClient.instance;

// Configure authentication
defaultClient.authentications['BearerAuth'].accessToken = "YOUR_JWT_TOKEN";

// Create API instance
var api = new TmiJsClient.ThreatModelsApi();

// List threat models
api.listThreatModels(function(error, data, response) {
  if (error) {
    console.error(error);
  } else {
    console.log('Threat models:', data);
  }
});

Working with Diagrams

var api = new TmiJsClient.ThreatModelSubResourcesApi();

// Create diagram
var request = new TmiJsClient.CreateDiagramRequest();
request.name = "My Diagram";
request.type = "DFD-1.0.0";

api.createThreatModelDiagram(request, threatModelId, function(error, data, response) {
  if (error) {
    console.error(error);
  } else {
    console.log('Created diagram:', data);
  }
});

Webpack Configuration

If using Webpack, disable AMD loader:

module: {
  rules: [
    {
      parser: {
        amd: false
      }
    }
  ]
}

Go Client

The Go client provides idiomatic Go interfaces for the TMI API.

Installation

go get github.com/YOUR_ORG/tmi-clients/go-client-generated

Usage

import (
    tmi "github.com/YOUR_ORG/tmi-clients/go-client-generated"
)

// Configure client
cfg := tmi.NewConfiguration()
cfg.Host = "api.tmi.dev"
cfg.Scheme = "https"

// Add authentication
cfg.AddDefaultHeader("Authorization", "Bearer YOUR_JWT_TOKEN")

// Create API client
client := tmi.NewAPIClient(cfg)

// List threat models
models, _, err := client.ThreatModelsApi.ListThreatModels(context.Background())
if err != nil {
    log.Fatal(err)
}

Java Client

The Java client uses Maven for dependency management.

Installation

Add to your pom.xml:

<dependency>
  <groupId>YOUR_ORG</groupId>
  <artifactId>tmi-java-client</artifactId>
  <version>1.0.0</version>
</dependency>

Usage

import io.swagger.client.ApiClient;
import io.swagger.client.api.ThreatModelsApi;
import io.swagger.client.model.ThreatModel;

// Configure client
ApiClient client = new ApiClient();
client.setBasePath("https://api.tmi.dev");
client.setAccessToken("YOUR_JWT_TOKEN");

// Create API instance
ThreatModelsApi api = new ThreatModelsApi(client);

// List threat models
List<ThreatModel> models = api.listThreatModels();

API Endpoints

All clients provide access to the complete TMI API:

Core Resources

  • Threat Models - CRUD operations
  • Diagrams - DFD diagram management
  • Assets - Asset tracking
  • Threats - Threat management with bulk operations
  • Documents - Document attachments
  • Notes - Markdown notes
  • Repositories - Source code references

Authentication

  • OAuth 2.0 authorization flows
  • SAML authentication
  • Token refresh and introspection
  • User profile management

Collaboration

  • Real-time collaboration sessions
  • WebSocket support (via separate connection)

Metadata

  • Custom metadata on all resources
  • Bulk metadata operations

Common Patterns

Hierarchical Authorization

TMI uses hierarchical authorization - access control is defined at the ThreatModel level via the authorization field (readers, writers, owners). All child resources inherit permissions from their parent ThreatModel.

Bulk Operations

The following resources support bulk operations:

  • Threats - POST (create), PUT (upsert), PATCH (partial update), DELETE
  • Assets - POST, PUT, DELETE
  • Documents - POST, PUT, DELETE
  • Repositories - POST, PUT, DELETE

Notes and Diagrams do NOT support bulk operations.

All resources support bulk metadata operations.

Pagination

List endpoints support pagination with query parameters:

  • limit - Number of items per page
  • offset - Number of items to skip

Partial Updates (PATCH)

All resources support PATCH for partial updates using JSON Patch (RFC 6902):

import jsonpatch

# Create JSON Patch
patch = jsonpatch.JsonPatch([
    {"op": "replace", "path": "/name", "value": "New Name"},
    {"op": "add", "path": "/description", "value": "New description"}
])

# Apply patch
api.patch_threat_model(patch.patch, threat_model_id)

Documentation

Each client includes comprehensive auto-generated documentation:

  • Python: python-client-generated/docs/
  • JavaScript: javascript-client-generated/docs/
  • Go: Generated GoDoc comments
  • Java: Generated JavaDoc

Regenerating Clients

The Python client can be regenerated from the latest OpenAPI spec:

cd python-client-generated
./scripts/regenerate_client.sh

This script:

  • Generates the client with correct package name
  • Configures Python 3.8+ requirements
  • Updates dependencies with security fixes
  • Applies constructor patches automatically
  • Runs all tests
  • Generates comprehensive reports

See python-client-generated/docs/developer/REGENERATION_README.md for details.

Related Resources

Support

For client library issues:

  • Check the auto-generated documentation in each client's docs/ directory
  • Review test files for usage examples
  • Consult the OpenAPI specification at /Users/efitz/Projects/tmi-clients

For API issues:

Clone this wiki locally