Services
Web services, private services, background workers, static sites and cron jobs: CRUD, lifecycle actions (restart, suspend, resume, scale, rollback), status and runtime logs.
/api/v1/servicesEvery service with its computed fields. The state of live services reflects their running instances (degraded when some are down), from counts refreshed at most every few seconds.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Response Body
application/json
application/json
application/json
curl -X GET "https://example.com/api/v1/services" \ -H "Authorization: Bearer $FERRY_TOKEN"[ { "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string" }]/api/v1/servicesCreates the service with its own variables and env group links, then queues a first deploy (trigger create) when it has a repository or an image, unless deploy is false. Services and datastores share one namespace of names. memory_limit_mb (MiB, 16 MiB to 1 TiB) and cpu_limit (CPUs, 0.01 to 512, rounded to 0.01) limit every instance and job run of the service; omitted or 0 = the server default (see GET /api/v1/info).
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
POST /api/v1/services
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/services" \ -H "Authorization: Bearer $FERRY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "string" }'{ "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string"}/api/v1/services/{id}An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/api/v1/services/string" \ -H "Authorization: Bearer $FERRY_TOKEN"{ "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string"}/api/v1/services/{id}Every field is optional; for optional string settings an empty string clears the value. instances scales, suspended suspends or resumes, custom_domains refreshes the routes; build settings take effect on the next deploy. Resource limits (memory_limit_mb, cpu_limit; 0 = back to the server default) are only saved: they take effect with the next deploy or restart, this request doesn't redeploy. Switching between a git repository and an image requires clearing the other source in the same request. When a side effect fails after the settings were saved, the error message says so.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
PATCH /api/v1/services/{id} — every field optional. For optional string
settings, an empty string clears the value. Changing instances scales,
suspended suspends/resumes, custom_domains refreshes routes; build
settings and resource limits take effect on the next deploy.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PATCH "https://example.com/api/v1/services/string" \ -H "Authorization: Bearer $FERRY_TOKEN" \ -H "Content-Type: application/json" \ -d '{}'{ "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string"}/api/v1/services/{id}Removes its containers, routes, deploys and variables. Refused while other services reference it in their env (${{service.NAME...}}), unless force=true.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Query Parameters
Delete even though other services reference it (they will fail to deploy or restart).
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X DELETE "https://example.com/api/v1/services/string" \ -H "Authorization: Bearer $FERRY_TOKEN"/api/v1/services/{id}/restartRolls out the live deploy's image again (a new deploy with trigger restart), picking up changed variables.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/services/string/restart" \ -H "Authorization: Bearer $FERRY_TOKEN"{ "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create"}/api/v1/services/{id}/suspendStops its containers; settings, variables and deploys stay until it is resumed.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/services/string/suspend" \ -H "Authorization: Bearer $FERRY_TOKEN"{ "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string"}/api/v1/services/{id}/resumeStarts the live deploy's containers again.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/services/string/resume" \ -H "Authorization: Bearer $FERRY_TOKEN"{ "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string"}/api/v1/services/{id}/scaleSets the number of instances. Cron jobs can't be scaled, and services with a disk run 1 instance.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
POST /api/v1/services/{id}/scale
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/services/string/scale" \ -H "Authorization: Bearer $FERRY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "instances": 0 }'{ "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string"}/api/v1/services/{id}/rollbackQueues a deploy (trigger rollback) reusing the image of an earlier deploy of this service that went live.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
POST /api/v1/services/{id}/rollback
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/services/string/rollback" \ -H "Authorization: Bearer $FERRY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "deploy_id": "string" }'{ "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create"}/api/v1/services/{id}/deploy-hook/rotateReplaces the secret of the service's deploy hook URL: the old URL stops working, the new one is the returned deploy_hook_path.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/v1/services/string/deploy-hook/rotate" \ -H "Authorization: Bearer $FERRY_TOKEN"{ "auto_deploy": true, "branch": "string", "build_command": "string", "cpu_limit": 0, "created_at": "2019-08-24T14:15:22Z", "custom_domains": [ "string" ], "deploy_hook_key": "string", "disk_mount_path": "string", "dockerfile_path": "string", "health_check_path": "string", "id": "string", "image": "string", "instances": 0, "live_deploy_id": "string", "memory_limit_mb": 0, "name": "string", "port": 0, "publish_dir": "string", "repo_url": "string", "root_dir": "string", "runtime": "auto", "schedule": "string", "start_command": "string", "suspended": true, "type": "web_service", "updated_at": "2019-08-24T14:15:22Z", "deploy_hook_path": "string", "env_groups": [ "string" ], "hosts": [ "string" ], "internal_host": "string", "internal_port": 0, "latest_deploy": { "commit_message": "string", "commit_sha": "string", "created_at": "2019-08-24T14:15:22Z", "error": "string", "finished_at": "2019-08-24T14:15:22Z", "id": "string", "image": "string", "port": 0, "service_id": "string", "source": { "branch": "string", "commit": "string", "kind": "git", "repo_url": "string" }, "started_at": "2019-08-24T14:15:22Z", "status": "queued", "trigger": "create" }, "state": "not_deployed", "url": "string"}/api/v1/services/{id}/statusThe live state of each container: Docker state, host port, restarts, CPU and memory.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/api/v1/services/string/status" \ -H "Authorization: Bearer $FERRY_TOKEN"{ "desired_instances": 0, "instances": [ { "container_id": "string", "cpu_limit": 0, "cpu_percent": 0, "deploy_id": "string", "exit_code": 0, "host_port": 0, "memory_bytes": 0, "memory_limit_bytes": 0, "name": "string", "oom_killed": true, "restart_count": 0, "started_at": "string", "state": "string" } ], "service_id": "string", "state": "not_deployed"}/api/v1/services/{id}/logsThe merged output of the service's current containers (instance names the container). Cron jobs have no long-running containers: their stream is a few system lines pointing at the job logs.
An API token: one created in the dashboard or by ferry login, or the server token stored in <data-dir>/api_token. GET requests may send it as ?access_token= instead.
In: header
Path Parameters
Service id or name.
Query Parameters
Keep the stream open and send new lines as they are written.
Start with at most this many recent lines per container.
0 <= valueResponse Body
text/event-stream
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/api/v1/services/string/logs" \ -H "Authorization: Bearer $FERRY_TOKEN""event: log\ndata: {\"ts\":\"2026-01-01T12:00:00Z\",\"stream\":\"system\",\"line\":\"==> Build succeeded\"}\n\nevent: end\ndata: \n\n"auth
The account of the server (its administrator), signing in and out of the dashboard, the sessions and the API tokens, and ferry login (a terminal asks, the dashboard approves). The status, the first-run setup, signing in and out, and the two calls of a terminal need no authentication; the others only accept the dashboard's session, never an API token.
Deploys
Deploy history, manual deploys, source uploads (ferry up), cancellation and build logs.