Deploy Actions
Action endpoints trigger async operations on environments (deploy, restart, start, stop). All action endpoints return 202 Accepted immediately with a task_id. The actual work happens in the background.
Base URL: https://api.oec.sh/api/public/v1
All action endpoints require a full_access API key. Read-only keys return 403 Forbidden.
Async Pattern
All action endpoints follow the same pattern:
- POST the action → receive a
task_idandpoll_urlimmediately (202) - GET the
poll_urlto check progress - Poll until
statusreaches a terminal state:completedorfailed
Task Status Values
| Status | Terminal? | Meaning |
|---|---|---|
pending | No | Task created, not yet queued. |
queued | No | Waiting in the work queue. |
running | No | Worker is actively executing. |
completed | Yes | Task finished successfully. |
failed | Yes | Task finished with an error. |
cancelled | Yes | Task was cancelled before completion. |
Idempotency
All action endpoints support the Idempotency-Key header. Supply a unique string to safely retry on network errors without triggering duplicate operations. Idempotency results are cached for 24 hours.
Concurrency Protection
Only one action may be queued or running for an environment at a time. If another task is already active, the endpoint returns 409 Conflict with error code task_in_progress.
Trigger a Deployment
POST /environments/{env_id}/deployTriggers a full redeployment (pull latest Git code, update containers, run database migrations).
Path Parameters
| Parameter | Type | Description |
|---|---|---|
env_id | UUID | The environment ID. |
Headers
| Header | Required | Description |
|---|---|---|
Idempotency-Key | No | Unique string to deduplicate retries. |
Response — 202 Accepted
{
"task_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"status": "queued",
"environment_id": "YOUR_ENV_ID",
"poll_url": "/api/public/v1/deployments/a1b2c3d4-5678-90ab-cdef-1234567890ab"
}Response Fields
| Field | Type | Description |
|---|---|---|
task_id | UUID | Use this to poll for status. |
status | string | Initial task status, always "queued". |
environment_id | UUID | The environment being deployed. |
poll_url | string | Relative URL to GET for task status. |
Example
curl -X POST "https://api.oec.sh/api/public/v1/environments/YOUR_ENV_ID/deploy" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Idempotency-Key: deploy-$(date +%s)"Restart Environment
POST /environments/{env_id}/restartRestarts the environment's containers without redeploying code. The environment must be in running status.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
env_id | UUID | The environment ID. |
Headers
| Header | Required | Description |
|---|---|---|
Idempotency-Key | No | Unique string to deduplicate retries. |
Response — 202 Accepted
Returns the same action response shape as deploy.
Error Cases
| Status | Error Code | Reason |
|---|---|---|
409 | environment_not_running | Environment is not in running status. |
409 | task_in_progress | Another task is already active. |
Example
curl -X POST "https://api.oec.sh/api/public/v1/environments/YOUR_ENV_ID/restart" \
-H "Authorization: Bearer YOUR_API_KEY"Start Environment
POST /environments/{env_id}/startStarts a stopped environment. The environment must be in stopped status.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
env_id | UUID | The environment ID. |
Headers
| Header | Required | Description |
|---|---|---|
Idempotency-Key | No | Unique string to deduplicate retries. |
Response — 202 Accepted
Returns the same action response shape as deploy.
Error Cases
| Status | Error Code | Reason |
|---|---|---|
409 | environment_not_stopped | Environment is not in stopped status. |
409 | task_in_progress | Another task is already active. |
Example
curl -X POST "https://api.oec.sh/api/public/v1/environments/YOUR_ENV_ID/start" \
-H "Authorization: Bearer YOUR_API_KEY"Stop Environment
POST /environments/{env_id}/stopStops a running environment's containers. Data is preserved. The environment must be in running status.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
env_id | UUID | The environment ID. |
Headers
| Header | Required | Description |
|---|---|---|
Idempotency-Key | No | Unique string to deduplicate retries. |
Response — 202 Accepted
Returns the same action response shape as deploy.
Error Cases
| Status | Error Code | Reason |
|---|---|---|
409 | environment_not_running | Environment is not in running status. |
409 | task_in_progress | Another task is already active. |
Example
curl -X POST "https://api.oec.sh/api/public/v1/environments/YOUR_ENV_ID/stop" \
-H "Authorization: Bearer YOUR_API_KEY"List Deployments
GET /environments/{env_id}/deploymentsReturns the deployment history for an environment, newest first. Only includes deploy and redeploy task types.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
env_id | UUID | The environment ID. |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Results per page. Min 1, max 100. Default 20. |
cursor | string | Pagination cursor from previous response. |
Response — 200 OK
{
"data": [
{
"id": "a1b2c3d4-...",
"type": "deploy",
"status": "completed",
"environment_id": "YOUR_ENV_ID",
"progress_percent": 100,
"current_step": null,
"steps_completed": 12,
"total_steps": 12,
"started_at": "2026-03-01T12:00:00Z",
"completed_at": "2026-03-01T12:05:00Z",
"duration_seconds": 300,
"error_message": null,
"triggered_by": null
}
],
"pagination": {
"has_more": false,
"next_cursor": null,
"total": 5
}
}Deployment Object Fields
| Field | Type | Description |
|---|---|---|
id | UUID | Task ID. Use with Get Deployment Status. |
type | string | Task type: "deploy" or "redeploy". |
status | string | Current or final status. See Task Status Values. |
environment_id | UUID|null | The environment this task ran on. |
progress_percent | integer | Progress 0–100. |
current_step | string|null | Human-readable description of the current step. |
steps_completed | integer | Number of steps that have finished. |
total_steps | integer | Total number of steps. |
started_at | ISO 8601|null | When the worker started executing. |
completed_at | ISO 8601|null | When the task reached a terminal state. |
duration_seconds | integer|null | Total execution time in seconds. |
error_message | string|null | Human-readable error if status is "failed". |
triggered_by | string|null | User ID if triggered by a user, null if triggered by API key. |
Get Deployment Status
GET /deployments/{task_id}Returns the current status of a single deployment task. Use this to poll after triggering an action.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
task_id | UUID | The task ID returned by any action endpoint. |
Response — 200 OK
Returns the Deployment object.
Complete Polling Example
Deploy an environment and wait for it to finish:
import requests
import time
BASE_URL = "https://api.oec.sh/api/public/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
ENV_ID = "YOUR_ENV_ID"
# Step 1: Trigger deploy
response = requests.post(
f"{BASE_URL}/environments/{ENV_ID}/deploy",
headers=HEADERS,
)
response.raise_for_status()
data = response.json()
task_id = data["task_id"]
print(f"Deploy queued. Task ID: {task_id}")
# Step 2: Poll until complete
while True:
status_response = requests.get(
f"{BASE_URL}/deployments/{task_id}",
headers=HEADERS,
)
task = status_response.json()
print(f"Status: {task['status']} ({task['progress_percent']}%)")
if task["status"] in ("completed", "failed", "cancelled"):
break
time.sleep(5)
# Step 3: Check result
if task["status"] == "completed":
print("Deploy succeeded!")
else:
print(f"Deploy failed: {task['error_message']}")For production workflows, consider using webhooks instead of polling. Subscribe to deploy.completed and deploy.failed events to receive a push notification when the deployment finishes.