cURL
curl -X POST 'https://api.supermodeltools.com/v1/graphs/domain' \
-H 'Idempotency-Key: <idempotency-key>' \
-H 'X-Api-Key: <api-key>' \
-F 'file=@/path/to/your/repo-snapshot.zip;type=application/zip'import { readFile } from 'node:fs/promises';
const baseUrl = process.env.API_BASE_URL || 'https://api.supermodeltools.com';
const apiKey = '<api-key>';
const idempotencyKey = '<idempotency-key>';
const archivePath = '/path/to/your/repo-snapshot.zip';
const buffer = await readFile(archivePath);
const form = new FormData();
form.append('file', new Blob([buffer], { type: 'application/zip' }), 'repo-snapshot.zip');
const res = await fetch(`${baseUrl}/v1/graphs/domain`, {
method: 'POST',
headers: {
'Idempotency-Key': idempotencyKey,
'X-Api-Key': apiKey
},
body: form
});
if (!res.ok) throw new Error(await res.text());
console.log(await res.json());import { Configuration, DefaultApi } from '@supermodel/public-api-typescript';
import { readFile } from 'node:fs/promises';
const baseUrl = process.env.API_BASE_URL || 'https://api.supermodeltools.com';
const apiKey = '<api-key>';
const idempotencyKey = '<idempotency-key>';
const archivePath = '/path/to/your/repo-snapshot.zip';
const buffer = await readFile(archivePath);
const archiveBlob = new Blob([buffer], { type: 'application/zip' });
const configuration = new Configuration({ basePath: baseUrl });
const apiKeyOverride = async ({ init }) => ({
headers: { ...(init.headers ?? {}), 'X-Api-Key': apiKey }
});
const api = new DefaultApi(configuration);
const result = await api.generateDomainGraph(
{ idempotencyKey, file: archiveBlob },
apiKeyOverride
);
console.log(result);import org.openapitools.client.ApiClient;
import org.openapitools.client.api.DefaultApi;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
String baseUrl = System.getenv().getOrDefault("API_BASE_URL", "https://api.supermodeltools.com");
String apiKey = "<api-key>";
String idempotencyKey = "<idempotency-key>";
File archive = new File("/path/to/your/repo-snapshot.zip");
ApiClient client = new ApiClient();
client.updateBaseUri(baseUrl);
client.setRequestInterceptor(rb -> {
rb.header("X-Api-Key", apiKey);
});
DefaultApi api = new DefaultApi(client);
api.generateDomainGraph(idempotencyKey, archive);
}
}import os
from supermodel_public_api import ApiClient, Configuration
from supermodel_public_api.api.default_api import DefaultApi
base_url = os.environ.get("API_BASE_URL", "https://api.supermodeltools.com")
api_key = "<api-key>"
idempotency_key = "<idempotency-key>"
configuration = Configuration(host=base_url)
configuration.api_key["ApiKeyAuth"] = api_key
api_client = ApiClient(configuration)
api = DefaultApi(api_client)
with open("/path/to/your/repo-snapshot.zip", "rb") as f:
payload = f.read()
result = api.generate_domain_graph(idempotency_key, file=payload)
print(result)use bytes::Bytes;
use reqwest::multipart::{Form, Part};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let base_url = std::env::var("API_BASE_URL")
.unwrap_or_else(|_| "https://api.supermodeltools.com".to_string());
let api_key = "<api-key>";
let idempotency_key = "<idempotency-key>";
let archive_bytes = Bytes::from(tokio::fs::read("/path/to/your/repo-snapshot.zip").await?);
let url = format!("{}/v1/graphs/domain", base_url.trim_end_matches('/'));
let file_part = Part::bytes(archive_bytes.to_vec())
.file_name("repo.zip")
.mime_str("application/zip")?;
let form = Form::new().part("file", file_part);
let response = reqwest::Client::new()
.post(url)
.header("Idempotency-Key", idempotency_key)
.header("X-Api-Key", api_key)
.multipart(form)
.send()
.await?;
let status = response.status();
let body = response.bytes().await?;
if status.is_success() {
println!("{}", String::from_utf8_lossy(&body));
} else {
anyhow::bail!(
"Request failed ({}): {}",
status.as_u16(),
String::from_utf8_lossy(&body)
);
}
Ok(())
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.supermodeltools.com/v1/graphs/domain",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data; boundary=---011000010111000001101001",
"Idempotency-Key: <idempotency-key>",
"X-Api-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.supermodeltools.com/v1/graphs/domain"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}require 'uri'
require 'net/http'
url = URI("https://api.supermodeltools.com/v1/graphs/domain")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'multipart/form-data; boundary=---011000010111000001101001'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"status": "completed",
"jobId": "abc-123-def",
"result": {
"runId": "smart-sampling-a1b2c3d4",
"graph": {
"nodes": [
{
"id": "domain:BillingAccount",
"labels": [
"Domain"
],
"properties": {
"name": "BillingAccount",
"description": "Handles billing and account management"
}
},
{
"id": "subdomain:BillingAccount:PaymentProcessing",
"labels": [
"Subdomain"
],
"properties": {
"name": "PaymentProcessing",
"description": "Processes payment transactions"
}
}
],
"relationships": [
{
"id": "domain:BillingAccount->contains->subdomain:BillingAccount:PaymentProcessing",
"type": "contains",
"startNode": "domain:BillingAccount",
"endNode": "subdomain:BillingAccount:PaymentProcessing",
"properties": {}
}
]
},
"metadata": {
"analysisStartTime": "2025-02-05T15:42:10Z",
"analysisEndTime": "2025-02-05T15:42:25Z",
"fileCount": 2,
"languages": [
"typescript"
]
},
"domains": [
{
"name": "BillingAccount",
"descriptionSummary": "Handles billing and account management",
"keyFiles": [
"src/domain/billing.ts",
"src/services/billing.service.ts"
],
"responsibilities": [
"Account creation",
"Payment processing"
],
"subdomains": [
{
"name": "PaymentProcessing",
"descriptionSummary": "Processes payment transactions",
"files": [
"src/services/billing.service.ts"
],
"functions": [
"func-123"
],
"classes": []
}
]
},
{
"name": "UsageSummary",
"descriptionSummary": "Tracks and summarizes usage metrics",
"keyFiles": [
"src/domain/usage.ts"
],
"responsibilities": [
"Usage tracking",
"Metrics aggregation"
],
"subdomains": []
}
],
"relationships": [
{
"from": "BillingAccount",
"to": "UsageSummary",
"type": "aggregates",
"strength": 0.8,
"reason": "BillingAccount aggregates usage data for billing purposes"
}
],
"fileAssignments": [
{
"filePath": "src/domain/billing.ts",
"domainName": "BillingAccount"
},
{
"filePath": "src/domain/usage.ts",
"domainName": "UsageSummary"
}
],
"functionAssignments": [
{
"functionId": "func-123",
"subdomainName": "PaymentProcessing",
"parentDomain": "BillingAccount"
}
],
"unassignedFunctions": [
{
"functionId": "func-456",
"reason": "Utility function with unclear domain association"
}
],
"classAssignments": [
{
"classId": "class-789",
"domainName": "BillingAccount"
}
],
"functionDescriptions": [
{
"functionId": "func-123",
"descriptionSummary": "Processes incoming payment transactions",
"domainName": "BillingAccount"
},
{
"functionId": "func-456",
"descriptionSummary": "Aggregates usage metrics for billing period"
}
],
"stats": {
"nodeCount": 2,
"relationshipCount": 1,
"nodeTypes": {
"Domain": 2,
"Subdomain": 1
},
"relationshipTypes": {
"contains": 1
},
"domainCount": 2,
"subdomainCount": 1,
"assignedFileCount": 1,
"assignedFunctionCount": 1,
"assignedClassCount": 0,
"fileAssignments": 2,
"functionAssignments": 1,
"unassignedFunctions": 1,
"classAssignments": 1
}
}
}{
"status": "processing",
"jobId": "abc-123-def",
"retryAfter": 5
}{
"status": 400,
"code": "invalid_request",
"message": "Missing required query parameter 'repo'.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEF1234",
"details": [
{
"field": "repo",
"issue": "This field is required.",
"location": "query"
}
]
}{
"status": 401,
"code": "unauthorized",
"message": "Provide a valid OAuth token to access this resource.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFXYZ1"
}{
"status": 403,
"code": "forbidden",
"message": "The token lacks the required keys:write scope.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFFORB"
}{
"status": 404,
"code": "not_found",
"message": "API key ak_live_missing was not found.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFF404"
}{
"status": 429,
"code": "rate_limit_exceeded",
"message": "Too many requests. Try again after the reset window.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFRATE"
}{
"status": 500,
"code": "internal_error",
"message": "Unexpected error processing request. Please retry.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFFAIL"
}{
"status": 349,
"code": "<string>",
"message": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"requestId": "<string>",
"details": [
{
"field": "<string>",
"issue": "<string>",
"location": "<string>"
}
]
}Data Plane
Domain graph
Upload a zipped repository snapshot to generate the domain model graph.
POST
/
v1
/
graphs
/
domain
cURL
curl -X POST 'https://api.supermodeltools.com/v1/graphs/domain' \
-H 'Idempotency-Key: <idempotency-key>' \
-H 'X-Api-Key: <api-key>' \
-F 'file=@/path/to/your/repo-snapshot.zip;type=application/zip'import { readFile } from 'node:fs/promises';
const baseUrl = process.env.API_BASE_URL || 'https://api.supermodeltools.com';
const apiKey = '<api-key>';
const idempotencyKey = '<idempotency-key>';
const archivePath = '/path/to/your/repo-snapshot.zip';
const buffer = await readFile(archivePath);
const form = new FormData();
form.append('file', new Blob([buffer], { type: 'application/zip' }), 'repo-snapshot.zip');
const res = await fetch(`${baseUrl}/v1/graphs/domain`, {
method: 'POST',
headers: {
'Idempotency-Key': idempotencyKey,
'X-Api-Key': apiKey
},
body: form
});
if (!res.ok) throw new Error(await res.text());
console.log(await res.json());import { Configuration, DefaultApi } from '@supermodel/public-api-typescript';
import { readFile } from 'node:fs/promises';
const baseUrl = process.env.API_BASE_URL || 'https://api.supermodeltools.com';
const apiKey = '<api-key>';
const idempotencyKey = '<idempotency-key>';
const archivePath = '/path/to/your/repo-snapshot.zip';
const buffer = await readFile(archivePath);
const archiveBlob = new Blob([buffer], { type: 'application/zip' });
const configuration = new Configuration({ basePath: baseUrl });
const apiKeyOverride = async ({ init }) => ({
headers: { ...(init.headers ?? {}), 'X-Api-Key': apiKey }
});
const api = new DefaultApi(configuration);
const result = await api.generateDomainGraph(
{ idempotencyKey, file: archiveBlob },
apiKeyOverride
);
console.log(result);import org.openapitools.client.ApiClient;
import org.openapitools.client.api.DefaultApi;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
String baseUrl = System.getenv().getOrDefault("API_BASE_URL", "https://api.supermodeltools.com");
String apiKey = "<api-key>";
String idempotencyKey = "<idempotency-key>";
File archive = new File("/path/to/your/repo-snapshot.zip");
ApiClient client = new ApiClient();
client.updateBaseUri(baseUrl);
client.setRequestInterceptor(rb -> {
rb.header("X-Api-Key", apiKey);
});
DefaultApi api = new DefaultApi(client);
api.generateDomainGraph(idempotencyKey, archive);
}
}import os
from supermodel_public_api import ApiClient, Configuration
from supermodel_public_api.api.default_api import DefaultApi
base_url = os.environ.get("API_BASE_URL", "https://api.supermodeltools.com")
api_key = "<api-key>"
idempotency_key = "<idempotency-key>"
configuration = Configuration(host=base_url)
configuration.api_key["ApiKeyAuth"] = api_key
api_client = ApiClient(configuration)
api = DefaultApi(api_client)
with open("/path/to/your/repo-snapshot.zip", "rb") as f:
payload = f.read()
result = api.generate_domain_graph(idempotency_key, file=payload)
print(result)use bytes::Bytes;
use reqwest::multipart::{Form, Part};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let base_url = std::env::var("API_BASE_URL")
.unwrap_or_else(|_| "https://api.supermodeltools.com".to_string());
let api_key = "<api-key>";
let idempotency_key = "<idempotency-key>";
let archive_bytes = Bytes::from(tokio::fs::read("/path/to/your/repo-snapshot.zip").await?);
let url = format!("{}/v1/graphs/domain", base_url.trim_end_matches('/'));
let file_part = Part::bytes(archive_bytes.to_vec())
.file_name("repo.zip")
.mime_str("application/zip")?;
let form = Form::new().part("file", file_part);
let response = reqwest::Client::new()
.post(url)
.header("Idempotency-Key", idempotency_key)
.header("X-Api-Key", api_key)
.multipart(form)
.send()
.await?;
let status = response.status();
let body = response.bytes().await?;
if status.is_success() {
println!("{}", String::from_utf8_lossy(&body));
} else {
anyhow::bail!(
"Request failed ({}): {}",
status.as_u16(),
String::from_utf8_lossy(&body)
);
}
Ok(())
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.supermodeltools.com/v1/graphs/domain",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data; boundary=---011000010111000001101001",
"Idempotency-Key: <idempotency-key>",
"X-Api-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.supermodeltools.com/v1/graphs/domain"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}require 'uri'
require 'net/http'
url = URI("https://api.supermodeltools.com/v1/graphs/domain")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'multipart/form-data; boundary=---011000010111000001101001'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"status": "completed",
"jobId": "abc-123-def",
"result": {
"runId": "smart-sampling-a1b2c3d4",
"graph": {
"nodes": [
{
"id": "domain:BillingAccount",
"labels": [
"Domain"
],
"properties": {
"name": "BillingAccount",
"description": "Handles billing and account management"
}
},
{
"id": "subdomain:BillingAccount:PaymentProcessing",
"labels": [
"Subdomain"
],
"properties": {
"name": "PaymentProcessing",
"description": "Processes payment transactions"
}
}
],
"relationships": [
{
"id": "domain:BillingAccount->contains->subdomain:BillingAccount:PaymentProcessing",
"type": "contains",
"startNode": "domain:BillingAccount",
"endNode": "subdomain:BillingAccount:PaymentProcessing",
"properties": {}
}
]
},
"metadata": {
"analysisStartTime": "2025-02-05T15:42:10Z",
"analysisEndTime": "2025-02-05T15:42:25Z",
"fileCount": 2,
"languages": [
"typescript"
]
},
"domains": [
{
"name": "BillingAccount",
"descriptionSummary": "Handles billing and account management",
"keyFiles": [
"src/domain/billing.ts",
"src/services/billing.service.ts"
],
"responsibilities": [
"Account creation",
"Payment processing"
],
"subdomains": [
{
"name": "PaymentProcessing",
"descriptionSummary": "Processes payment transactions",
"files": [
"src/services/billing.service.ts"
],
"functions": [
"func-123"
],
"classes": []
}
]
},
{
"name": "UsageSummary",
"descriptionSummary": "Tracks and summarizes usage metrics",
"keyFiles": [
"src/domain/usage.ts"
],
"responsibilities": [
"Usage tracking",
"Metrics aggregation"
],
"subdomains": []
}
],
"relationships": [
{
"from": "BillingAccount",
"to": "UsageSummary",
"type": "aggregates",
"strength": 0.8,
"reason": "BillingAccount aggregates usage data for billing purposes"
}
],
"fileAssignments": [
{
"filePath": "src/domain/billing.ts",
"domainName": "BillingAccount"
},
{
"filePath": "src/domain/usage.ts",
"domainName": "UsageSummary"
}
],
"functionAssignments": [
{
"functionId": "func-123",
"subdomainName": "PaymentProcessing",
"parentDomain": "BillingAccount"
}
],
"unassignedFunctions": [
{
"functionId": "func-456",
"reason": "Utility function with unclear domain association"
}
],
"classAssignments": [
{
"classId": "class-789",
"domainName": "BillingAccount"
}
],
"functionDescriptions": [
{
"functionId": "func-123",
"descriptionSummary": "Processes incoming payment transactions",
"domainName": "BillingAccount"
},
{
"functionId": "func-456",
"descriptionSummary": "Aggregates usage metrics for billing period"
}
],
"stats": {
"nodeCount": 2,
"relationshipCount": 1,
"nodeTypes": {
"Domain": 2,
"Subdomain": 1
},
"relationshipTypes": {
"contains": 1
},
"domainCount": 2,
"subdomainCount": 1,
"assignedFileCount": 1,
"assignedFunctionCount": 1,
"assignedClassCount": 0,
"fileAssignments": 2,
"functionAssignments": 1,
"unassignedFunctions": 1,
"classAssignments": 1
}
}
}{
"status": "processing",
"jobId": "abc-123-def",
"retryAfter": 5
}{
"status": 400,
"code": "invalid_request",
"message": "Missing required query parameter 'repo'.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEF1234",
"details": [
{
"field": "repo",
"issue": "This field is required.",
"location": "query"
}
]
}{
"status": 401,
"code": "unauthorized",
"message": "Provide a valid OAuth token to access this resource.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFXYZ1"
}{
"status": 403,
"code": "forbidden",
"message": "The token lacks the required keys:write scope.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFFORB"
}{
"status": 404,
"code": "not_found",
"message": "API key ak_live_missing was not found.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFF404"
}{
"status": 429,
"code": "rate_limit_exceeded",
"message": "Too many requests. Try again after the reset window.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFRATE"
}{
"status": 500,
"code": "internal_error",
"message": "Unexpected error processing request. Please retry.",
"timestamp": "2025-02-05 16:35:12.000000000 Z",
"requestId": "req_01HZYJ9CE0ABCDEFFAIL"
}{
"status": 349,
"code": "<string>",
"message": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"requestId": "<string>",
"details": [
{
"field": "<string>",
"issue": "<string>",
"location": "<string>"
}
]
}Authorizations
API key issued by the control plane for accessing data plane resources.
Headers
Unique identifier for this request for idempotency and tracing.
Body
multipart/form-data
Zipped repository archive containing the code to analyze.
Response
Domain graph (job completed)
Async response envelope for domain classification operations.
Current status of the job.
Available options:
pending, processing, completed, failed Unique identifier for the job.
Recommended seconds to wait before polling again.
Error message (present when status is failed).
The result (present when status is completed).
Show child attributes
Show child attributes
⌘I