Save a service's configuration. With deploymentId, roll it out too. Changes to its domains go live without a deploy once it has been deployed.
API key access: full.
apiKeyAuthorizationBearer <pyo_…>An API key from the dashboard's API keys page: Authorization: Bearer pyo_…. Keys can expire, and an expired one gets a 401.
application/jsonSave a service's configuration. With deploymentId, roll it out too. Changes to its domains go live without a deploy once it has been deployed.
API key access: full.
op*"saveService""saveService"service*The whole service, as in the snapshot.
Its ports: name, containerPort, protocol ("HTTP", "TCP" or "UDP"), exposure ("internal", "http" for a website, "nodeport", or "loadbalancer" for a public TCP or UDP port) and publicPort.
A public TCP or UDP port goes through the gateway unless proxy is false. Then, for TCP only, it can have ipFilter ({"mode": "allow" or "deny", "cidrs": [...]}), connectionLimit (open connections on the port, from everyone together), sendProxyProtocol ("V1" or "V2", to the service) and acceptProxyProtocol (read the visitor's address from a header sent by a load balancer in front, while connections without one still work). Ports 22, 53, 80, 443 and a few others can't be public. Each public port belongs to one service on its cluster.
Its healthCheck, which says when a replica is ready: type ("http" for a request to path on port answered with 2xx or 3xx, "tcp" for port accepting connections, "exec" to run command, or "none" so deploys don't wait for it), initialDelaySeconds and periodSeconds. With auto ("default" or "static") Pyo picks it from what each build finds: a static site or single-page app gets an HTTP check of /. A check without auto is kept as it is.
A Git source has buildArgs ([{"key": …, "value": …}]), used by its next build: Dockerfile build arguments, or Railpack settings such as RAILPACK_BUILD_CMD. They can end up in the image, so no secrets.
deploymentId?string|nulltrigger?string|nullconfirm?booleanGo ahead with a very large replica change: without it, one that goes to 20 or more replicas and to more than 10 times what the service had, or more than twice what its servers have room for, is refused with 409 and needsConfirm: true. Ask the user before sending it.
Done. Always ok: true, and some operations add more, such as a new API key or a join command. A warning comes with a change that went through but won't fully take effect yet, such as more replicas than the servers have room for.
application/jsoncurl -X POST 'https://your-pyo.example.com/api/v1/ops' \
-H 'Content-Type: application/json' \
-d '{
"op": "saveService",
"service": {
"clusterId": "cl_8kq2x7ad",
"domains": [],
"env": [],
"id": "svc_8kq2x7ad",
"name": "web",
"ports": [
{
"containerPort": 80,
"exposure": "http",
"name": "http",
"protocol": "TCP"
},
{
"containerPort": 6379,
"exposure": "loadbalancer",
"ipFilter": {
"cidrs": [
"203.0.113.0/24"
],
"mode": "allow"
},
"name": "redis",
"protocol": "TCP",
"proxy": true,
"publicPort": 6379
}
],
"projectId": "prj_8kq2x7ad",
"replicas": 2,
"source": {
"image": "nginx:1.29",
"type": "image"
}
}
}'{}