Deployments
The Deployments API enables you to create, monitor, and control deployments programmatically. Use it to integrate Mantis with your CI/CD pipelines and automation workflows.
Endpoints
Section titled “Endpoints”| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/deployments | List all deployments (paginated) |
POST | /api/v1/deployments | Create a new deployment |
POST | /api/v1/deployments/preview | Preview deployment plan (dry-run) |
GET | /api/v1/deployments/{id} | Get deployment details |
POST | /api/v1/deployments/{id}/cancel | Cancel a running deployment |
POST | /api/v1/deployments/{id}/redeploy | Redeploy with same configuration |
GET | /api/v1/deployments/{id}/logs | Stream deployment logs (SSE) |
GET | /api/v1/deployments/{id}/logs/history | Get historical logs |
GET | /api/v1/deployments/{id}/analysis | Get post-deployment analysis |
GET | /api/v1/deployments/pending | List queued deployments |
DELETE | /api/v1/deployments/pending/{id} | Cancel a queued deployment |
List Deployments
Section titled “List Deployments”Retrieve a paginated list of deployments.
GET /api/v1/deployments?page=1&limit=50&tenant_id=<uuid>Authorization: Bearer <token>Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number (default: 1) |
limit | integer | No | Items per page (default: 50, max: 100) |
tenant_id | string (UUID) | No | Filter by tenant ID |
Response
Section titled “Response”{ "data": [ { "id": "d9e8f7c6-b5a4-3210-9876-543210fedcba", "source_type": "solution", "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "solution_name": "Web Application", "solution_version": "2.1.0", "sequence_id": null, "sequence_name": null, "sequence_version": null, "action_id": null, "action_name": null, "action_version": null, "state": "success", "progress": 1.0, "total_steps": 15, "completed_steps": 15, "failed_steps": 0, "tenant_id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890", "tenant_name": "Production", "environment_id": "e7d6c5b4-a3f2-1098-7654-3210fedcba98", "environment_name": "prod", "triggered_by": "jane.operator", "created_at": "2024-01-20T14:30:00Z", "started_at": "2024-01-20T14:30:00Z", "completed_at": "2024-01-20T14:35:12Z", "duration_ms": 312000 } ], "meta": { "total": 247, "page": 1, "limit": 50, "total_pages": 5, "has_next": true, "has_prev": false }}Source Types
Section titled “Source Types”The source_type field indicates what the deployment runs. The matching
*_id, *_name, and *_version fields are populated for that source; the
other two source groups are null.
| Source | Description |
|---|---|
solution | Deploys a full solution |
sequence | Deploys a single sequence |
action | Deploys a single action |
State Values
Section titled “State Values”The state field reflects the deployment lifecycle.
| State | Description |
|---|---|
pending | Deployment created, not yet started |
queued | Awaiting dispatch to a Thorax instance |
running | Currently executing |
success | Completed successfully |
failed | Completed with failures |
cancelled | User-cancelled deployment |
rolling_back | Rolling back after failure |
rolled_back | Rollback completed |
Create Deployment
Section titled “Create Deployment”Create and start a new deployment.
POST /api/v1/deploymentsAuthorization: Bearer <token>Content-Type: application/json
{ "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "override_freeze": false}You must supply at least one of target_ids (explicit UUIDs or SqIds) or
target_tags (key-value pairs). Omitting both returns a 400 validation error.
Request Body
Section titled “Request Body”Deploy to an explicit list of targets (UUIDs or SqIds):
{ "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "target_ids": ["t1-uuid", "t2-uuid", "t3-uuid"]}Deploy to targets matching tag key/value pairs:
{ "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "target_tags": [ { "key": "role", "value": "webserver" }, { "key": "env", "value": "production" } ], "target_tags_match_all": false}Tag filter logic:
target_tags- Array of{ "key": ..., "value": ... }objectstarget_tags_match_all- Iftrue, a target must match ALL pairs (AND logic); iffalse(default), matching ANY pair is sufficient (OR logic)
Deploy a single action or sequence directly (instead of a full solution):
{ "action_id": "act-uuid"}
// Or for a sequence:{ "sequence_id": "seq-uuid"}Request Parameters
Section titled “Request Parameters”| Field | Type | Required | Description |
|---|---|---|---|
solution_id | string | Yes* | Solution to deploy (UUID or SqId) |
action_id | string | Yes* | Action to execute (alternative to solution) |
sequence_id | string | Yes* | Sequence to execute (alternative to solution) |
version_requirement | string | No | Version constraint for the source (e.g. ^1.0.0); latest if omitted |
target_ids | array of string | No | Specific target IDs or SqIds |
target_tags | array of object | No | Tag filter — array of { key, value } pairs |
target_tags_match_all | boolean | No | Require ALL target_tags to match (default: any) |
target_mode | string|object | No | Execution mode: sequential, parallel, or { "rolling": { "batch_size": N } } |
failure_strategy | string | No | stop_on_first_failure, continue_on_failure, or ignore_failures |
rollback_strategy | string | No | none, failed_target_only, or all_executed |
priority | integer | No | Command priority, -100 to 100 (higher = more urgent) |
timeout_seconds | integer | No | Per-command timeout in seconds (1–86400) |
max_retries | integer | No | Max retries per command (0–10) |
deployment_timeout_seconds | integer | No | Overall deployment timeout in seconds (0 = no timeout) |
variables | object | No | Deployment variables (key → value) |
prompted_values | object | No | Values for prompted variables (variable id/name → value) |
tenant_id | string | No | Tenant ID or SqId for tenant-aware deployments |
environment_id | string | Yes* | Environment ID or SqId (*required when tenant_id is provided) |
bypass_cache | boolean | No | Skip the file cache and fetch fresh content from S3/Git |
dry_run | boolean | No | Validate the deployment without executing it |
override_freeze | boolean | No | Bypass active deployment freezes (requires admin role) |
override_reason | string | No | Reason for overriding a freeze (required when override_freeze is true) |
* Exactly one of solution_id, action_id, or sequence_id must be provided.
Execution Tuning Example
Section titled “Execution Tuning Example”{ "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "target_mode": "sequential", "failure_strategy": "stop_on_first_failure", "rollback_strategy": "none", "timeout_seconds": 3600, "max_retries": 2}For rolling waves, pass target_mode as an object:
{ "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "target_mode": { "rolling": { "batch_size": 5 } }}Response (Success)
Section titled “Response (Success)”{ "deployment_id": "d9e8f7c6-b5a4-3210-9876-543210fedcba", "pending": false, "message": "Deployment d9e8f7c6-b5a4-3210-9876-543210fedcba created and started successfully", "deployment": { "id": "d9e8f7c6-b5a4-3210-9876-543210fedcba", "source_type": "solution", "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "solution_name": "API Service", "solution_version": "1.4.2", "sequence_id": null, "sequence_name": null, "sequence_version": null, "action_id": null, "action_name": null, "action_version": null, "state": "running", "progress": 0.0, "total_steps": 3, "completed_steps": 0, "failed_steps": 0, "config": { "target_mode": "parallel", "failure_strategy": "stop_on_first_failure", "rollback_strategy": "none", "priority": 0, "timeout_seconds": 3600, "max_retries": 2, "target_ids": ["5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12"], "target_tags": [], "variables": {}, "tenant_id": null, "environment_id": null }, "plan": { "target_count": 1, "steps": [ { "id": "9b1d2c3e-4a5f-6789-0abc-def123456789", "target_id": "5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12", "target_name": "web-01.prod", "sequence_id": "7a8b9c0d-1e2f-3456-7890-abcdef123456", "sequence_name": "Deploy API", "sequence_order": 1, "action_id": "1a2b3c4d-5e6f-7890-abcd-ef0123456789", "action_name": "Stop Service", "action_order": 1, "state": "pending", "started_at": null, "completed_at": null, "exit_code": null, "error_message": null, "retry_count": 0, "duration_ms": null } ], "resolved_variables": {}, "tenant_name": null, "environment_name": null, "created_at": "2024-12-01T12:00:00Z" }, "tenant_id": null, "tenant_name": null, "environment_id": "e7d6c5b4-a3f2-1098-7654-3210fedcba98", "environment_name": "prod", "triggered_by": "jane.operator", "error_message": null, "created_at": "2024-12-01T12:00:00Z", "started_at": "2024-12-01T12:00:00Z", "completed_at": null, "duration_ms": null, "analysis_enabled": false }}Response (Queued)
Section titled “Response (Queued)”HTTP Status: 202 Accepted
When no Thorax instance is available, the deployment is queued:
{ "pending_request_id": "3c4d5e6f-7a8b-9012-cdef-345678901234", "pending": true, "message": "Deployment request queued - waiting for eligible Thorax instance"}The deployment will be automatically dispatched when a Thorax instance becomes available.
Errors
Section titled “Errors”Preview Deployment
Section titled “Preview Deployment”Preview the execution plan without creating a deployment (dry-run).
POST /api/v1/deployments/previewAuthorization: Bearer <token>Content-Type: application/json
{ "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}Request body: Same as Create Deployment
Response
Section titled “Response”{ "plan": { "target_count": 3, "steps": [ { "id": "9b1d2c3e-4a5f-6789-0abc-def123456789", "target_id": "5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12", "target_name": "web-01.prod", "sequence_id": "7a8b9c0d-1e2f-3456-7890-abcdef123456", "sequence_name": "Deploy API", "sequence_order": 1, "action_id": "1a2b3c4d-5e6f-7890-abcd-ef0123456789", "action_name": "Stop Service", "action_order": 1, "state": "pending", "started_at": null, "completed_at": null, "exit_code": null, "error_message": null, "retry_count": 0, "duration_ms": null } ], "resolved_variables": {}, "tenant_name": null, "environment_name": null, "created_at": "2024-12-01T12:00:00Z" }, "warnings": ["Target web-03.prod is currently offline"], "target_summary": { "total": 3, "online": 2, "offline": 1, "stale": 0 }, "variables": {}, "source_type": "solution", "source_name": "API Service", "source_version": "1.4.2"}Use this endpoint to:
- Validate deployment configuration before execution
- Show users what will happen
- Check for deployment freezes
- Verify target availability
Get Deployment Details
Section titled “Get Deployment Details”Retrieve detailed information about a specific deployment.
GET /api/v1/deployments/{id}Authorization: Bearer <token>Response
Section titled “Response”{ "id": "d9e8f7c6-b5a4-3210-9876-543210fedcba", "source_type": "solution", "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "solution_name": "Web Application", "solution_version": "2.1.0", "sequence_id": null, "sequence_name": null, "sequence_version": null, "action_id": null, "action_name": null, "action_version": null, "state": "running", "progress": 0.56, "total_steps": 9, "completed_steps": 5, "failed_steps": 0, "config": { "target_mode": "parallel", "failure_strategy": "stop_on_first_failure", "rollback_strategy": "none", "priority": 0, "timeout_seconds": 3600, "max_retries": 0, "target_ids": [], "target_tags": [], "variables": {}, "tenant_id": null, "environment_id": null }, "plan": { "target_count": 3, "steps": [ { "id": "5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12", "target_id": "t1-uuid", "target_name": "web-01.prod", "sequence_id": "seq-uuid", "sequence_name": "Deploy Web App", "sequence_order": 0, "action_id": "act-uuid", "action_name": "Restart service", "action_order": 0, "state": "completed", "started_at": "2024-01-20T14:30:05Z", "completed_at": "2024-01-20T14:30:20Z", "exit_code": 0, "error_message": null, "retry_count": 0, "duration_ms": 15000 } ], "resolved_variables": {}, "tenant_name": "Production", "environment_name": "prod", "created_at": "2024-01-20T14:30:00Z" }, "tenant_id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890", "tenant_name": "Production", "environment_id": "e7d6c5b4-a3f2-1098-7654-3210fedcba98", "environment_name": "prod", "triggered_by": "550e8400-e29b-41d4-a716-446655440000", "error_message": null, "created_at": "2024-01-20T14:30:00Z", "started_at": "2024-01-20T14:30:00Z", "completed_at": null, "duration_ms": 45000, "analysis_enabled": false}Cancel Deployment
Section titled “Cancel Deployment”Cancel a running deployment.
POST /api/v1/deployments/{id}/cancelAuthorization: Bearer <token>Content-Type: application/json
{ "reason": "Emergency rollback required"}Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
reason | string | No | Reason for cancellation (for audit log) |
Response
Section titled “Response”Returns the full deployment detail (the same DeploymentDetailResponse shape as
Get Deployment Details) with state updated to
cancelled:
{ "id": "d9e8f7c6-b5a4-3210-9876-543210fedcba", "source_type": "solution", "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "solution_name": "Web Application", "solution_version": "2.1.0", "sequence_id": null, "sequence_name": null, "sequence_version": null, "action_id": null, "action_name": null, "action_version": null, "state": "cancelled", "progress": 0.56, "total_steps": 9, "completed_steps": 5, "failed_steps": 0, "config": { "target_mode": "parallel", "failure_strategy": "stop_on_first_failure", "rollback_strategy": "none", "priority": 0, "timeout_seconds": 3600, "max_retries": 0, "target_ids": [], "target_tags": [], "variables": {}, "tenant_id": null, "environment_id": null }, "plan": null, "tenant_id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890", "tenant_name": "Production", "environment_id": "e7d6c5b4-a3f2-1098-7654-3210fedcba98", "environment_name": "prod", "triggered_by": "jane.operator", "error_message": null, "created_at": "2024-01-20T14:30:00Z", "started_at": "2024-01-20T14:30:00Z", "completed_at": "2024-01-20T14:33:10Z", "duration_ms": 190000, "analysis_enabled": false}Redeploy
Section titled “Redeploy”Re-execute a deployment with the same configuration.
Redeploy re-runs an existing deployment. With an empty body it reuses the original deployment’s configuration; any field you supply overrides the original.
POST /api/v1/deployments/{id}/redeployAuthorization: Bearer <token>Content-Type: application/json
{ "target_ids": ["t1-uuid", "t2-uuid"]}Request Body
Section titled “Request Body”All fields are optional overrides applied on top of the original deployment.
| Field | Type | Description |
|---|---|---|
variables | object | Override variables (merged with the original deployment’s variables) |
environment_id | string | Override environment ID or SqId |
target_ids | array of string | Override target IDs or SqIds |
target_tags | array of object | Override target tag filter — array of { key, value } pairs |
target_mode | string|object | Override execution mode (sequential, parallel, or rolling object) |
failure_strategy | string | Override failure strategy |
rollback_strategy | string | Override rollback strategy |
priority | integer | Override priority (-100 to 100) |
timeout_seconds | integer | Override per-command timeout (1–86400) |
max_retries | integer | Override max retries per command (0–10) |
prompted_values | object | Override prompted variable values |
bypass_cache | boolean | Skip the file cache and fetch fresh content |
override_freeze | boolean | Bypass active freezes (requires admin role) |
override_reason | string | Reason for overriding a freeze (required when override_freeze is true) |
Response
Section titled “Response”HTTP Status: 201 Created
Returns the newly created deployment as a DeploymentDetailResponse (the same
shape as Get Deployment Details). Unlike Create
Deployment, redeploy does not wrap the result in a { deployment_id, pending, message, deployment } envelope — the deployment detail is the entire response
body. Because the new deployment was created from an existing one, it includes a
source_deployment_id referencing the original:
{ "id": "a7b8c9d0-1e2f-3456-7890-abcdef123456", "source_type": "solution", "solution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "solution_name": "Web Application", "solution_version": "2.1.0", "sequence_id": null, "sequence_name": null, "sequence_version": null, "action_id": null, "action_name": null, "action_version": null, "state": "running", "progress": 0.0, "total_steps": 2, "completed_steps": 0, "failed_steps": 0, "config": { "target_mode": "parallel", "failure_strategy": "stop_on_first_failure", "rollback_strategy": "none", "priority": 0, "timeout_seconds": 3600, "max_retries": 0, "target_ids": [ "5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12", "6a4d1b3f-2c8e-5f9b-0d22-3b5c7e9f1a34" ], "target_tags": [], "variables": {}, "tenant_id": null, "environment_id": null }, "plan": null, "tenant_id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890", "tenant_name": "Production", "environment_id": "e7d6c5b4-a3f2-1098-7654-3210fedcba98", "environment_name": "prod", "triggered_by": "jane.operator", "error_message": null, "created_at": "2024-01-20T15:00:00Z", "started_at": "2024-01-20T15:00:00Z", "completed_at": null, "duration_ms": null, "analysis_enabled": false, "source_deployment_id": "d9e8f7c6-b5a4-3210-9876-543210fedcba"}Deployment Logs (Streaming)
Section titled “Deployment Logs (Streaming)”Stream real-time deployment logs via Server-Sent Events (SSE).
GET /api/v1/deployments/{id}/logs?sse_token=<sse-token>Event Stream Format
Section titled “Event Stream Format”Each message is delivered as a single SSE data: line whose payload is a JSON
object with a top-level event discriminator and a nested data object. The
inner data object carries a type field matching event. No named SSE
event: field is set, so browser EventSource clients receive these as default
message events and switch on the parsed event/type value.
data: {"event":"ping","data":{"type":"ping"}}
data: {"event":"log","data":{"type":"log","log":{"timestamp":"2024-01-20T14:30:15+00:00","level":"info","step_id":null,"target_id":"5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12","target_name":"web-01.prod","message":"Starting deployment","metadata":null}}}
data: {"event":"progress","data":{"type":"progress","deployment_id":"d9e8f7c6-b5a4-3210-9876-543210fedcba","progress":0.33,"completed_steps":1,"total_steps":3,"message":"1 of 3 steps complete"}}
data: {"event":"step_update","data":{"type":"step_update","step_id":"9b1d2c3e-4a5f-6789-0abc-def123456789","state":"completed","exit_code":0,"error_message":null,"output":"Service stopped successfully\n"}}
data: {"event":"state_change","data":{"type":"state_change","deployment_id":"d9e8f7c6-b5a4-3210-9876-543210fedcba","old_state":"","new_state":"success","message":"Deployment completed successfully"}}Event Types
Section titled “Event Types”The event (and matching inner data.type) field is one of:
| Event | Inner data fields | Description |
|---|---|---|
ping | (none) | Keep-alive sent when the connection opens |
log | log (object: timestamp, level, step_id, target_id, target_name, message, metadata) | Individual log entry from a target |
progress | deployment_id, progress, completed_steps, total_steps, message | Progress update (progress is 0.0–1.0) |
step_update | step_id, state, exit_code, error_message, output | Step-level status change |
state_change | deployment_id, old_state, new_state, message | Deployment state transition |
The terminal transition (success, failure, cancellation) arrives as a
state_change event with the final new_state; there is no separate complete
event.
JavaScript Client Example
Section titled “JavaScript Client Example”const eventSource = new EventSource( `https://mantis.example.com/api/v1/deployments/${deploymentId}/logs?sse_token=${sseToken}`);
// Events are unnamed SSE messages; parse the payload and switch on `event`.eventSource.onmessage = (message) => { const { event, data } = JSON.parse(message.data);
switch (event) { case 'log': console.log(`[${data.log.level}] ${data.log.message}`); break; case 'progress': updateProgress(data.completed_steps, data.total_steps); break; case 'step_update': console.log(`Step ${data.step_id}: ${data.state}`); break; case 'state_change': console.log(`State -> ${data.new_state}`); if ( ['success', 'failed', 'cancelled', 'rolled_back'].includes( data.new_state ) ) { eventSource.close(); } break; case 'ping': break; // keep-alive }};
eventSource.onerror = (error) => { console.error('SSE connection error:', error);};Historical Logs
Section titled “Historical Logs”Retrieve completed deployment logs. Results are an offset-paginated array ordered chronologically.
GET /api/v1/deployments/{id}/logs/history?offset=0&limit=100Authorization: Bearer <token>Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
offset | integer | No | Number of entries to skip (default: 0) |
limit | integer | No | Max entries to return (default: 100) |
Response
Section titled “Response”The response is a bare JSON array of log entries (not a paginated envelope):
[ { "id": "2b3c4d5e-6f70-8192-a3b4-c5d6e7f80912", "timestamp": "2024-01-20T14:30:15+00:00", "level": "info", "event_type": "log", "step_id": null, "target_id": "5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12", "target_name": "web-01.prod", "message": "Starting deployment", "stdout": null, "stderr": null, "metadata": null, "analysis": null }, { "id": "3c4d5e6f-7081-92a3-b4c5-d6e7f8091223", "timestamp": "2024-01-20T14:30:16+00:00", "level": "info", "event_type": "log", "step_id": "9b1d2c3e-4a5f-6789-0abc-def123456789", "target_id": "5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12", "target_name": "web-01.prod", "message": "Executing action: Stop Service", "stdout": "Service stopped successfully\n", "stderr": null, "metadata": null, "analysis": null }]Deployment Analysis
Section titled “Deployment Analysis”Get per-command results for a deployment, including AI-generated failure analysis
where available. Only failed commands carry an analysis object.
GET /api/v1/deployments/{id}/analysisAuthorization: Bearer <token>Response
Section titled “Response”The response is a bare JSON array of command results ordered by start time. Each
entry corresponds to a single command executed on a target. Optional fields
(target_name, action_name, exit_code, stdout_tail, stderr_tail,
error_message, analysis) are omitted when not present. stdout_tail and
stderr_tail contain only the last 2000 characters of output.
[ { "id": "4d5e6f70-8192-a3b4-c5d6-e7f809122334", "target_id": "5f3c0a2e-1b7d-4e8a-9c11-2a4b6d8e0f12", "target_name": "web-01.prod", "action_name": "Stop Service", "status": "completed", "exit_code": 0, "stdout_tail": "Service stopped successfully\n", "started_at": "2024-01-20T14:30:05+00:00", "completed_at": "2024-01-20T14:30:17+00:00", "duration_ms": 12000 }, { "id": "5e6f7081-92a3-b4c5-d6e7-f80912233445", "target_id": "6a4d1b3f-2c8e-5f9b-0d22-3b5c7e9f1a34", "target_name": "web-03.prod", "action_name": "Restart Service", "status": "failed", "exit_code": 1, "stderr_tail": "systemctl: Failed to restart api.service: Unit not found.\n", "error_message": "Command exited with code 1", "started_at": "2024-01-20T14:31:02+00:00", "completed_at": "2024-01-20T14:31:09+00:00", "duration_ms": 7000, "analysis": { "confidence": 0.92, "summary": "The service restart failed because the api.service unit is not registered with systemd.", "likely_cause": "The api.service unit file was never installed on this target, or was removed before the restart action ran.", "remediation": [ "Verify the api.service unit file exists at /etc/systemd/system/api.service", "Run `systemctl daemon-reload` after installing the unit file", "Re-run the deployment once the unit is registered" ], "analyzed_at": "2024-01-20T14:31:15+00:00", "model_version": "claude-opus-4" } }]Pending Deployments
Section titled “Pending Deployments”List deployments waiting in the dispatch queue.
GET /api/v1/deployments/pending?tenant_id=<uuid>&status=pendingAuthorization: Bearer <token>Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string (UUID) | No | Filter by tenant |
status | string | No | Filter by status: pending, processing, dispatched, cancelled, failed |
Response
Section titled “Response”The response is a bare JSON array of pending dispatch requests. Optional fields
(tenant_id, tenant_name, environment_id, environment_name,
triggered_by, last_retry_at, error_message, deployment_id,
dispatched_at, dispatched_to_instance_id) are omitted when not set — a
freshly queued request typically has none of the dispatch-related fields:
[ { "id": "3c4d5e6f-7a8b-9012-cdef-345678901234", "tenant_id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890", "tenant_name": "Production", "environment_id": "e7d6c5b4-a3f2-1098-7654-3210fedcba98", "environment_name": "prod", "triggered_by": "jane.operator", "queued_at": "2024-01-20 14:35:00", "retry_count": 0, "status": "pending", "created_at": "2024-01-20 14:35:00" }]Cancel Pending Deployment
Section titled “Cancel Pending Deployment”Remove a deployment from the dispatch queue.
DELETE /api/v1/deployments/pending/{id}Authorization: Bearer <token>Response
Section titled “Response”HTTP Status: 200 OK
Returns an empty body on success. A 404 is returned if the pending request does
not exist, and a 409 Conflict if it is already in a terminal state (dispatched, cancelled, or
failed) — only pending or processing requests can be cancelled.
Complete Examples
Section titled “Complete Examples”CI/CD Pipeline Integration (GitHub Actions)
Section titled “CI/CD Pipeline Integration (GitHub Actions)”name: Deploy to Productionon: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy via Mantis API env: MANTIS_URL: ${{ secrets.MANTIS_URL }} MANTIS_API_KEY: ${{ secrets.MANTIS_API_KEY }} SOLUTION_ID: ${{ secrets.SOLUTION_ID }} run: | # Create deployment RESPONSE=$(curl -s -X POST "$MANTIS_URL/api/v1/deployments" \ -H "Authorization: Bearer $MANTIS_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"solution_id\": \"$SOLUTION_ID\", \"target_tags\": [ {\"key\": \"env\", \"value\": \"production\"}, {\"key\": \"role\", \"value\": \"webserver\"} ], \"target_tags_match_all\": true }")
DEPLOYMENT_ID=$(echo "$RESPONSE" | jq -r '.deployment_id') echo "Deployment ID: $DEPLOYMENT_ID"
# Poll until complete (the detail endpoint exposes `state`) while true; do STATE=$(curl -s "$MANTIS_URL/api/v1/deployments/$DEPLOYMENT_ID" \ -H "Authorization: Bearer $MANTIS_API_KEY" \ | jq -r '.state')
echo "State: $STATE"
case "$STATE" in success|rolled_back) echo "Deployment finished: $STATE" exit 0 ;; failed|cancelled) echo "Deployment $STATE" exit 1 ;; *) sleep 10 ;; esac doneTypeScript SDK Example
Section titled “TypeScript SDK Example”interface DeploymentClient { create(options: CreateDeploymentOptions): Promise<Deployment>; get(id: string): Promise<DeploymentDetail>; cancel(id: string, reason?: string): Promise<void>; streamLogs(id: string, onLog: (log: LogEntry) => void): () => void;}
class MantisDeploymentClient implements DeploymentClient { constructor( private baseUrl: string, private apiKey: string ) {}
async create(options: CreateDeploymentOptions): Promise<Deployment> { const response = await fetch(`${this.baseUrl}/api/v1/deployments`, { method: 'POST', headers: { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify(options), });
if (!response.ok) { const error = await response.json(); throw new DeploymentError(error.error.code, error.error.message); }
return response.json(); }
streamLogs(id: string, onLog: (log: LogEntry) => void): () => void { const eventSource = new EventSource( `${this.baseUrl}/api/v1/deployments/${id}/logs?sse_token=${this.sseToken}` );
// Events are unnamed SSE messages: { event, data }. Forward log entries. eventSource.onmessage = (message) => { const { event, data } = JSON.parse(message.data); if (event === 'log') { onLog(data.log); } };
// Return cleanup function return () => eventSource.close(); }}Next Steps
Section titled “Next Steps”- Authentication - Create API keys and SSE tokens for automation
- Pagination - Handle large result sets
- Error Handling - Handle deployment errors
- For the remaining resource endpoints, see the OpenAPI specification
