REST API Reference
The Reforge REST API provides server-side CGM-to-SVG conversion, batch job management, and profile detection.
Licence requirement
API access requires an Enterprise licence. All endpoints return 403 Forbidden without it.
Authentication
X-Api-Key: your-api-key
Base URL
https://your-server/api/v1
Endpoints
Health check
GET /api/v1/health — No authentication required.
Convert by file path
POST /api/v1/convert
{
"filePath": "/mnt/files/input.cgm",
"outputDirectory": "/mnt/output",
"companionFilePath": "/mnt/files/input.xcf",
"settings": { "profile": "auto", "dpi": 96 }
}
Response: { success, outputPath, profile, conversionDurationMs, hasWatermark }
Convert — upload
POST /api/v1/convert/upload — multipart/form-data
| Field | Required | Description |
|---|---|---|
file |
Yes | CGM file (max 100 MB) |
companionFile |
No | XCF or IMF companion |
settings |
No | JSON string of conversion settings |
Response: Content-Type: image/svg+xml
Batch convert
POST /api/v1/convert/batch
{
"filePaths": ["/mnt/files/fig-001.cgm", "/mnt/files/fig-002.cgm"],
"outputDirectory": "/mnt/output",
"settings": { "profile": "s1000d" },
"callbackUrl": "https://your-server/webhooks/reforge",
"callbackSecret": "your-hmac-secret"
}
| Field | Required | Description |
|---|---|---|
filePaths |
Yes | 1–500 absolute server-side paths |
outputDirectory |
No | Defaults to directory of first file |
maxParallelFiles |
No | 1–16, default 4 |
errorHandling |
No | SkipFile (default) · TryConvertAnyway · StopBatch |
settings |
No | Conversion settings applied to all files |
callbackUrl |
No | URL to POST when the job reaches a terminal state |
callbackSecret |
No | HMAC-SHA256 secret for webhook signature verification |
Response (202 Accepted): { jobId, status, totalFiles, statusUrl }
Job status
GET /api/v1/jobs/{jobId}
{
"jobId": "3fa85f64-...",
"status": "PartiallyCompleted",
"totalFiles": 100,
"succeededFiles": 80,
"failedFiles": 20,
"successRate": 0.80,
"progressPercent": 100,
"submittedAt": "2026-03-23T14:00:00Z",
"completedAt": "2026-03-23T14:22:00Z"
}
Status values: Queued · Running · Completed · PartiallyCompleted · Failed · Cancelled
Completed— all files succeededPartiallyCompleted— at least one file succeeded and at least one failedFailed— every file failed (or an unhandled error aborted the job)
Job results
GET /api/v1/jobs/{jobId}/results — Returns 202 if still running, 200 with results when complete.
Each entry in the results array:
| Field | Type | Description |
|---|---|---|
inputPath |
string | Original input file path |
success |
bool | Whether conversion succeeded |
outputPath |
string? | Output SVG path (null on failure) |
outputSizeBytes |
long | Output SVG byte size (0 on failure) |
profile |
string? | Detected or applied CGM profile |
durationMs |
long | Conversion time in milliseconds |
companionFileUsed |
bool | Whether an XCF/IMF companion was applied |
errorCode |
string? | Structured error code (e.g. EngineError, ValidationFailure) |
error |
string? | Human-readable error message |
warnings |
array | Quality warnings (see below) |
Each warning object:
| Field | Values | Description |
|---|---|---|
code |
string | Machine-readable code (e.g. CONVERSION_WARNING) |
severity |
"Warning" · "Info" |
Severity level |
message |
string | Human-readable description |
Cancel job
DELETE /api/v1/jobs/{jobId} — Returns 204 No Content.
Retry failed files
POST /api/v1/jobs/{jobId}/retry
Submits a new job containing only the files that failed in the original job. The original job’s results are not modified — both jobs can be queried independently.
Optional request body (all fields override the original job’s values):
{
"outputDirectory": "/mnt/output/retry",
"settings": { "dpi": 150 }
}
Response (202 Accepted):
{
"originalJobId": "3fa85f64-...",
"retryJobId": "7cb29a11-...",
"retryingFiles": 20,
"statusUrl": "https://your-server/api/v1/jobs/7cb29a11-..."
}
Error responses:
| Status | Condition |
|---|---|
404 |
Original job not found |
409 Conflict |
Job is still Queued or Running |
400 Bad Request |
Job has no failed files |
List profiles
GET /api/v1/profiles — Array of { name, displayName, description }.
Detect profile
POST /api/v1/detect
{ "filePath": "/mnt/files/fig-001.cgm" }
Response: { "detectedProfile": "S1000Dv6" }
Validate
POST /api/v1/validate
{ "filePath": "/mnt/files/fig-001.cgm", "profile": "s1000d" }
Response: { isValid, detectedProfile, issues: [{ severity, code, message }] }
Settings object
| Field | Default | Description |
|---|---|---|
profile |
"auto" |
Input profile |
dpi |
96 |
Resolution (72–600) |
hotspotsEncoding |
"both" |
"svgAnchors" "dataAttributes" "both" |
textHandling |
"preserve" |
"preserve" or "paths" |
rasterEncoding |
"png" |
"png" "jpeg" "base64" "none" |
companionFileMode |
"auto" |
"auto" "xcfOnly" "ignore" |
Webhook callbacks
When a callbackUrl is supplied on batch submission, the server POSTs the following JSON to that URL when the job reaches a terminal state:
{
"jobId": "3fa85f64-...",
"status": "PartiallyCompleted",
"totalFiles": 100,
"succeededFiles": 80,
"failedFiles": 20,
"completedAt": "2026-03-23T14:22:00Z",
"resultsUrl": "jobs/3fa85f64-.../results"
}
Signature verification
When callbackSecret is set, each callback request includes:
X-Reforge-Signature: sha256=<hex>
The hex value is HMAC-SHA256(requestBody, callbackSecret). Verify it on your server before processing the payload.
Delivery retries
The server retries failed deliveries up to 3 times with exponential backoff (1 s, 2 s, 4 s).
Webhook delivery is best-effort — use GET /jobs/{jobId} to confirm the final state if reliability is critical.