API Reference¶
ConTree provides a REST API for managing sandboxed container execution with Git-like branching.
Base URL: https://api.contree.dev/v1
Authentication: Bearer JWT token (required for all endpoints)
Images¶
Manage OCI container images for sandbox execution.
List Images¶
GET /images
Parameters:
Name |
Type |
Default |
Description |
|---|---|---|---|
limit |
integer |
100 |
Number of results (1-1000) |
offset |
integer |
0 |
Pagination offset |
tagged |
boolean |
— |
Filter by tagged images only |
tag |
string |
— |
Filter by tag prefix |
since |
string |
— |
Filter by creation time (ISO 8601 or relative: |
until |
string |
— |
Upper bound for creation time |
Response: 200 OK — Array of Image objects
Import Image¶
POST /images/import
Import an OCI image filesystem from a container registry.
Request Body:
{
"registry": "docker.io/library/python:3.12-slim",
"credentials": {
"username": "user",
"password": "token"
},
"tag": "python-slim",
"timeout": 300
}
Note
Only the filesystem is imported. OCI metadata (ENV, ENTRYPOINT, CMD) is not preserved.
Response: 202 Accepted with Location header pointing to the operation.
Update Image Tag¶
PATCH /images/{imageUUID}/tag
Request Body:
{"tag": "my-custom-tag"}
Tags are unique per account. Reassigning a tag moves it to the new image.
Response: 200 OK — Updated Image object
Remove Image Tag¶
DELETE /images/{imageUUID}/tag
Response: 200 OK — Image object with tag removed
Files¶
Upload and manage input files for sandbox execution.
Upload File¶
POST /files
Content-Type: application/octet-stream
<binary file content>
Response: 201 Created
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
Check File Exists¶
HEAD /files?uuid={fileUUID}
Response: 200 OK if exists, 404 Not Found otherwise
Get File by Hash¶
GET /files?sha256={hash}
Response: 200 OK — FileResponse object
Instances¶
Spawn and manage sandbox container instances.
Spawn Instance¶
POST /instances
Create a new sandboxed execution instance.
Request Body:
{
"image": "tag:python-slim",
"command": "python /input/script.py",
"shell": true,
"env": {
"PYTHONPATH": "/app"
},
"cwd": "/root",
"timeout": 60,
"files": {
"/input/script.py": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"mode": "0644"
}
},
"truncate_output_at": 1048576,
"stdin": "base64:SGVsbG8gV29ybGQ="
}
Key Parameters:
Name |
Type |
Default |
Description |
|---|---|---|---|
image |
string |
required |
Image UUID or |
command |
string |
required |
Executable path or shell expression |
shell |
boolean |
false |
Run command through shell |
env |
object |
— |
Environment variables |
cwd |
string |
/root |
Working directory |
timeout |
integer |
— |
Max execution time in seconds |
files |
object |
— |
Map of paths to file UUIDs with permissions |
truncate_output_at |
integer |
1 MiB |
Output size limit (max 10 MiB) |
stdin |
string |
— |
Input data (ASCII or |
hostname |
string |
— |
Custom hostname |
disposable |
boolean |
— |
Auto-cleanup after execution |
Response: 201 Created with Location header
{
"uuid": "instance-uuid-here"
}
Operations¶
Track async operations (image imports, instance executions).
List Operations¶
GET /operations
Parameters:
Name |
Type |
Default |
Description |
|---|---|---|---|
limit |
integer |
100 |
Number of results (1-1000) |
offset |
integer |
0 |
Pagination offset |
status |
string |
— |
Filter: PENDING, EXECUTING, SUCCESS, FAILED, CANCELLED |
kind |
string |
— |
Filter: |
since |
string |
— |
Time filter (ISO 8601 or relative) |
until |
string |
— |
Upper bound time filter |
Response: 200 OK — Array of Operation objects
Get Operation Status¶
GET /operations/{operationId}
Response: 200 OK
{
"id": "operation-uuid",
"status": "SUCCESS",
"kind": "instance",
"created_at": "2024-01-15T10:30:00Z",
"result": {
"exit_code": 0,
"stdout": {"content": "Hello World", "encoding": "ascii", "truncated": false},
"stderr": {"content": "", "encoding": "ascii", "truncated": false},
"cpu_time_ms": 150,
"memory_bytes": 52428800,
"timed_out": false
}
}
Headers: Retry-After indicates recommended polling interval.
Cancel Operation¶
DELETE /operations/{operationId}
Response: 202 Accepted
Inspection¶
Inspect image contents and download files from executed instances.
Find Image by Tag¶
GET /inspect/?tag={tagName}
Response: 302 Found — Redirect to /inspect/{imageUUID}/
Get Image Metadata¶
GET /inspect/{imageUUID}/
Response: 200 OK
{
"uuid": "image-uuid",
"tag": "python-slim",
"created_at": "2024-01-15T10:00:00Z"
}
List Directory¶
GET /inspect/{imageUUID}/list?path=/output
Parameters:
Name |
Type |
Default |
Description |
|---|---|---|---|
path |
string |
required |
Directory path to list |
text |
boolean |
false |
Return plain text (ls-style) format |
Response: 200 OK
{
"path": "/output",
"items": [
{
"name": "result.json",
"size": 1024,
"mode": "0644",
"is_regular": true,
"modified_at": "2024-01-15T10:35:00Z"
}
]
}
Download File¶
GET /inspect/{imageUUID}/download?path=/output/result.json
Parameters:
Name |
Type |
Default |
Description |
|---|---|---|---|
path |
string |
required |
File path (URL-encoded) |
text |
boolean |
false |
Force text/plain content type |
Response: 200 OK — File content with appropriate Content-Type
Check Path Exists¶
HEAD /inspect/{imageUUID}/?path=/some/path
Response: 200 OK if exists, 404 Not Found otherwise
Error Responses¶
All endpoints return standard error responses:
{
"error": "validation_error",
"message": "Invalid image UUID format",
"details": {}
}
Common Status Codes:
Code |
Description |
|---|---|
400 |
Bad Request — Invalid parameters |
401 |
Unauthorized — Missing or invalid token |
403 |
Forbidden — Insufficient permissions |
404 |
Not Found — Resource doesn’t exist |
409 |
Conflict — Operation state conflict |
422 |
Unprocessable Entity — Invalid path |
Interactive Sandbox¶
Try the API directly in your browser using the Swagger UI:
OpenAPI Specification¶
The complete OpenAPI specification is available at: