/v1/auth/signupno authCreate a user, team and default project
| email* | string | |
| password* | string | |
| name* | string | |
| teamName* | string | |
| country | string | |
| locale | string | one of en, tr, ar |
201Created409Conflict
Reference
prgd API 1. Generated from openapi.yaml, which you can also feed to any client generator. Read the API guide first for auth, idempotency and errors.
/v1/auth/signupno authCreate a user, team and default project
| email* | string | |
| password* | string | |
| name* | string | |
| teamName* | string | |
| country | string | |
| locale | string | one of en, tr, ar |
201 Created409 Conflict/v1/auth/loginno authLog in and receive a session token
When the user has two factor sign in, the first call answers 401 totp_required; repeat it with totp set to the six digit authenticator code or an unused recovery code. Team owners must enable two factor when REQUIRE_TOTP_FOR_OWNERS is on; until then console sessions get 403 totp_setup_required on every route except the account and two factor endpoints. API tokens are exempt.
| email* | string | |
| password* | string | |
| totp | string |
200 OK401 Wrong email or password, `totp_required`, or `password_not_set` for an account that signs in only with Google or Microsoft (`details.providers` names them)/v1/auth/verifyno authConfirm an email address with the token from the verification email
| token* | string |
200 OK400 Token invalid or expired (`token_invalid`)/v1/auth/verify/requestSend the verification email again for the signed in user
204 Sent (or already verified)/v1/auth/password/forgotno authSend a password reset link
Always returns 204 so email addresses cannot be probed. Limited to 5 requests per 10 minutes per IP.
| email* | string |
204 Accepted/v1/auth/password/resetno authSet a new password with the token from the reset email
| token* | string | |
| password* | string |
200 OK400 Token invalid or expired (`token_invalid`)/v1/auth/totp/setupStart two factor enrollment
Returns a new secret and an otpauth:// URL to show as a QR code. Nothing is enforced until /auth/totp/enable confirms a code.
201 OK409 Already enabled (`totp_enabled`)/v1/auth/totp/enableConfirm the authenticator and turn two factor on
Returns ten recovery codes exactly once. Each recovery code signs the user in a single time.
| code* | string | Six digit authenticator code |
201 OK401 Code not valid (`totp_invalid`)/v1/auth/totp/disableTurn two factor off (needs a current code or a recovery code)
| code* | string | Six digit authenticator code |
201 OK401 Code not valid (`totp_invalid`)/v1/auth/providersno authSocial sign in providers that are configured (the console shows a button for each)
200 OK/v1/auth/oauth/{provider}/startno authStart sign in with Google or Microsoft (the browser navigates here)
Redirects to the provider with the authorization code flow, PKCE (S256), state and nonce, scopes openid email profile. Sets an HttpOnly, Secure, SameSite=Lax cookie that binds the sign in to this browser; the pending state lives on the server for 10 minutes. intent=link needs a ticket from POST /auth/oauth/link-ticket. Errors redirect to the console /auth/callback?error=<code>.
| provider (path)* | string | one of google, microsoft |
| intent (query) | string | one of login, signup, link |
| return (query) | string | Console path to land on afterwards |
| invite (query) | string | Invitation token; a new account joins that team instead of creating one |
| ticket (query) | string | One time link ticket (intent link) |
| locale (query) | string | one of en, tr, ar |
302 Redirect to the provider/v1/auth/oauth/{provider}/callbackno authProvider redirect URI
Checks state and the browser cookie, exchanges the code with the PKCE verifier, verifies the id token (signature against the provider key set, audience, issuer, nonce) and redirects to the console /auth/callback?code=<one time code> (valid 60 seconds). Session tokens never appear in URLs. Error codes: state_invalid, cancelled, provider_error, token_invalid, link_from_security, identity_in_use, email_missing, account_exists, invite_email_mismatch, invite_invalid, link_session_invalid.
| provider (path)* | string | one of google, microsoft |
302 Redirect to the console/v1/auth/oauth/exchangeno authRedeem the one time code from the console callback
Same answer as /auth/login, plus created and returnTo. Accounts with two factor sign in get { totpRequired, ticket } instead; finish with /auth/oauth/totp.
| code* | string |
200 OK400 Code unknown403 Staff account without two factor sign in (`totp_setup_required`)/v1/auth/oauth/totpno authSecond factor for a social sign in
| ticket* | string | |
| code* | string |
200 OK400 Ticket expired or used (`ticket_invalid`); five wrong codes end it401 Code not valid (`totp_invalid`)/v1/auth/oauth/link-ticketOne time ticket (60 seconds) to link Google or Microsoft to the signed in user
Console sessions only; API tokens get 403. Pass it to /auth/oauth/{provider}/start?intent=link&ticket=….
201 OK/v1/account/identitiesLinked Google and Microsoft accounts, whether a password is set, and which providers can be linked
200 OK/v1/account/identities/{id}Unlink a Google or Microsoft account
| id (path)* | string |
204 Unlinked409 It is the only way left to sign in (`last_sign_in_method`)/v1/accountCurrent user, team, role and scopes
200 OK/v1/projectsList projects
200 OK/v1/projectsCreate a project
| name* | string | |
| slug* | string | |
| spendLimitMinor | integer |
201 Created/v1/tokensList API tokens
200 OK/v1/tokensCreate an API token (human or AI agent)
Agent-safe tokens set isAgent: true and may carry spendCapMinor (monthly hard cap) and requireApprovalFor (e.g. ["servers:delete","servers:resize-down"]). A token can never carry scopes its creator does not have.
| name* | string | |
| scopes* | string[] | |
| projectId | string | |
| isAgent | boolean | |
| spendCapMinor | integer | |
| requireApprovalFor | string[] | e.g. ["servers:delete","servers:resize-down"] |
| expiresInDays | integer |
201 Created — `token` is shown once/v1/tokens/{id}Revoke a token
| id (path)* | string |
204 Revoked/v1/auditTeam audit log (newest 200 entries)
200 OK/v1/interestRegister interest in a roadmap product ("notify me when this launches")
| product* | string | e.g. "inference" |
| note | string |
204 Recorded/v1/ssh-keysList SSH keys
200 OK/v1/ssh-keysAdd an SSH public key
| name* | string | |
| publicKey* | string |
201 Created/v1/ssh-keys/{id}Delete an SSH key
| id (path)* | string |
204 Deleted/v1/approvalsList approval requests (agents see only their own)
| status (query) | string | one of pending, approved, denied, expired, failed |
200 OK/v1/approvals/{id}Get one approval request
| id (path)* | string |
200 OK404 Not found/v1/approvals/{id}/approveApprove and run the parked request
Team owners and admins only, never an agent token. The request runs with the agent token's project scope and spending cap still applied; the audit log records both the person and the token.
| id (path)* | string |
201 Ran403 Forbidden409 Already decided or expired (`invalid_state`)/v1/approvals/{id}/denyDeny the parked request
| id (path)* | string |
| reason | string |
201 Denied/v1/servers/{id}/metricsTime series for a server
One point per minute for 1h, 6h and 24h; hourly averages (with the hour's CPU peak) for 7d and 30d. Network and disk are bytes per second; multiply by 8 and divide by a million for Mbps.
| id (path)* | string | |
| period (query) | string | one of 1h, 6h, 24h, 7d, 30d |
200 OK/v1/alertsList alert rules
200 OK/v1/alertsCreate an alert rule
Fires when the metric, averaged over windowMinutes, is above or below the threshold on any matching server. Empty serverIds and tags means every server in the team. Owners and admins are emailed, plus any addresses in emails; webhooks get alert.triggered and alert.resolved.
| name | string | |
| metric | string | one of cpu, memory, disk, net_in, net_out |
| comparator | string | one of above, below |
| threshold | number | percent for cpu |
| windowMinutes | integer | |
| serverIds | string[] | |
| tags | string[] | |
| emails | string[] | |
| enabled | boolean |
201 Created/v1/alerts/incidentsIncidents (open and recent)
| open (query) | boolean |
200 OK/v1/alerts/{id}Get an alert rule with recent incidents
| id (path)* | string |
200 OK404 Not found/v1/alerts/{id}Update an alert rule (any field, including enabled to mute)
| id (path)* | string |
| name | string | |
| metric | string | one of cpu, memory, disk, net_in, net_out |
| comparator | string | one of above, below |
| threshold | number | percent for cpu |
| windowMinutes | integer | |
| serverIds | string[] | |
| tags | string[] | |
| emails | string[] | |
| enabled | boolean |
200 OK/v1/alerts/{id}Delete an alert rule
| id (path)* | string |
204 Deleted/v1/serversList servers
| project (query) | string | Project id or slug (default `default`) |
| limit (query) | integer | |
| cursor (query) | string | |
| status (query) | string | one of new, provisioning, active, off, rebooting, resizing, rebuilding, deleting, deleted, failed, suspended |
| tag (query) | string |
200 OK/v1/serversCreate a server
Returns 202 immediately with status: new. A durable workflow places the server, reserves a public IP, clones the image, waits for cloud-init, applies the firewall and starts metering. Watch status become active (30–60 s) or subscribe to server.active. The server is never billed unless it reaches active.
| Idempotency-Key (header) | string |
| name* | string | |
| size* | string | e.g. "s-2vcpu-4gb" |
| image* | string | Image id or marketplace app slug |
| region | string | |
| project | string | |
| sshKeys | string[] | |
| userData | string | cloud-init user-data |
| tags | string[] | |
| backups | boolean | |
| managed | boolean | Managed tier |
| firewalls | string[] | |
| appVariables | object | Marketplace app variables |
| avoid | string[] | Server ids to anti-affine from |
202 Accepted402 Spend limit reached (`spend_limit_reached`)403 Quota exceeded (`quota_exceeded`)422 Validation error/v1/servers/{id}Get a server
| id (path)* | string |
200 OK404 Not found/v1/servers/{id}Rename, retag, or turn backups or the managed tier on or off
Turning managed on also turns backups on. A server that never had the care agent gets it on its next rebuild, or right away with the install command from GET /servers/{id}/managed.
| id (path)* | string |
| name | string | |
| tags | string[] | |
| backups | boolean | Daily platform snapshot |
| managed | boolean | Managed tier |
200 OK/v1/servers/{id}Delete a server
Returns 202; the server moves to deleting and is removed by a workflow. Metering stops immediately.
| id (path)* | string | |
| Idempotency-Key (header) | string |
202 Accepted409 Invalid state (`invalid_state`)/v1/servers/{id}/managedManaged tier status
Health from the care agent's last report, the report itself, and the install command while the agent is not reporting.
| id (path)* | string |
200 OK/v1/managed/install/{token}no authCare agent install script
Public, keyed by the server's managed token. Served as a shell script for curl | sh.
| token (path)* | string |
200 OK401 Unknown token/v1/managed/reportno authCare agent report
Posted by the agent inside a managed server every five minutes, authenticated by the X-Prgd-Managed-Token header.
| X-Prgd-Managed-Token (header)* | string |
| agentVersion | integer | |
| hostname | string | |
| kernel | string | |
| uptimeSec | integer | |
| load1 | number | |
| memTotalMb | integer | |
| memUsedMb | integer | |
| diskTotalGb | number | |
| diskUsedGb | number | |
| diskUsedPct | integer | |
| pendingUpdates | integer | |
| securityUpdates | integer | |
| rebootRequired | boolean | |
| lastUpgradeAt | stringnull | |
| failedUnits | string[] | |
| sshBanned | integer | |
| sshPasswordAuth | boolean |
200 OK401 Unknown token/v1/servers/{id}/actionsList recent actions on a server
| id (path)* | string |
200 OK/v1/servers/{id}/actionsRun a lifecycle action
| id (path)* | string | |
| Idempotency-Key (header) | string |
| type* | string | one of start, stop, reboot, resize, rebuild, snapshot |
| size | string | resize: target size id (disk cannot shrink) |
| image | string | rebuild: image id (defaults to current) |
| name | string | snapshot: name |
| force | boolean | stop: power off without ACPI shutdown |
202 Accepted409 Invalid state (`invalid_state`)/v1/regionsno authList regions
200 OK/v1/sizesno authList server sizes
200 OK/v1/imagesno authList images
| kind (query) | string | one of distribution, marketplace |
200 OK/v1/pricingno authPublic price list (USD base; SAR converted at the current exchange rate)
| currency (query) | string | one of USD, SAR |
200 OK/v1/deploysList Git deployments
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/deploysDeploy a Git repository onto a new server
Creates a server whose cloud-init installs Docker, clones the repo, builds (Dockerfile or docker-compose) and serves it on :80. Two ways to name the repository: repoUrl (public, or private with gitToken) returns a per deployment GitHub webhook URL and secret (shown once) to add to the repository; installationId + repo ("owner/name") uses the team's GitHub App installation, needs no token, and redeploys on every push through the app webhook (webhook is null).
| Idempotency-Key (header) | string |
| repoUrl | string | |
| installationId | string | |
| repo | string | e.g. "acme/app" |
| branch | string | |
| name | string | |
| port | integer | |
| size | string | |
| project | string | |
| sshKeys | string[] | |
| env | object | |
| gitToken | string | For private repos; stored only in the server's cloud-init |
202 Accepted; includes `webhook` (url and secret) for URL based deployments/v1/deploys/{id}Get a deployment (refreshes status from the server)
| id (path)* | string |
200 OK/v1/deploys/{id}/redeployRedeploy now
| id (path)* | string |
202 Accepted/v1/deploys/{id}/hookno authGitHub push webhook (verified with X-Hub-Signature-256)
| id (path)* | string | |
| X-Hub-Signature-256 (header)* | string | |
| X-GitHub-Event (header) | string |
200 OK401 Unauthorized/v1/deploys/{id}/logsTail of the last build log
Fetched live from the server when it is reachable, otherwise the last cached copy. Capped at 32 KB.
| id (path)* | string |
200 OK/v1/github/appWhether the GitHub App integration is configured
200 OK/v1/github/connectURL to install the GitHub App for this team
Send the user there. GitHub returns them to the console callback with installation_id and the signed state, which the console posts to /github/installations.
200 OK503 Not configured (`github_app_unavailable`)/v1/github/installationsGitHub App installations linked to the team
200 OK/v1/github/installationsLink an installation after the GitHub redirect
| installationId* | integer | |
| state* | string |
201 Linked401 State invalid or expired/v1/github/installations/{id}Unlink and uninstall
| id (path)* | string |
204 Removed/v1/github/installations/{id}/reposRepositories the installation can reach
| id (path)* | string |
200 OK/v1/github/webhookno authGitHub App webhook (push, installation)
One URL for every installation, verified with X-Hub-Signature-256 and the app webhook secret. A push redeploys every deployment on that repository and branch.
200 OK/v1/firewallsList firewalls
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/firewallsCreate a firewall
| name* | string | |
| project | string | |
| rules* | object[] |
201 Created/v1/firewalls/{id}Get a firewall
| id (path)* | string |
200 OK/v1/firewalls/{id}Delete a firewall
| id (path)* | string |
204 Deleted/v1/firewalls/{id}/rulesReplace all rules (re-applied to attached servers immediately)
| id (path)* | string |
| rules* | object[] |
200 OK/v1/firewalls/{id}/serversAttach a server
| id (path)* | string |
| serverId* | string |
204 Attached/v1/firewalls/{id}/servers/{serverId}Detach a server
| id (path)* | string | |
| serverId (path)* | string |
204 Detached/v1/public-ipsList public IPs in a project
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/snapshotsList snapshots
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/snapshots/{id}Delete a snapshot
| id (path)* | string |
202 Accepted/v1/volumesList volumes
| project (query) | string | Project id or slug (default `default`) |
| server (query) | string | Only volumes attached to this server |
200 OK/v1/volumesCreate a volume
Allocates a block volume in the region. Returns 202; the volume becomes available within seconds, or attached when serverId is given.
| Idempotency-Key (header) | string |
| name* | string | |
| sizeGb* | integer | |
| region | string | Defaults to the platform region |
| project | string | |
| serverId | string | Attach right after creation |
202 Accepted403 Forbidden/v1/volumes/{id}Get a volume
| id (path)* | string |
200 OK404 Not found/v1/volumes/{id}Delete a volume
The volume must be detached. Data is gone for good.
| id (path)* | string |
202 Accepted409 Still attached/v1/volumes/{id}/attachAttach to a server
Hot plugs the volume. The server must be in the same region and active or off. The guest sees the disk at device.
| id (path)* | string |
| serverId* | string |
202 Accepted/v1/volumes/{id}/detachDetach from its server
Unmount the file system in the guest first.
| id (path)* | string |
202 Accepted/v1/volumes/{id}/resizeGrow a volume
Volumes only grow. An attached volume grows live; extend the file system in the guest afterwards.
| id (path)* | string |
| sizeGb* | integer |
202 Accepted/v1/load-balancersList load balancers
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/load-balancersCreate a load balancer
Reserves a public IP, creates one to three HAProxy nodes and pushes the forwarding rules. Returns 202; status becomes active once every node runs the config.
| Idempotency-Key (header) | string |
| name* | string | |
| region | string | |
| project | string | |
| nodes | integer | |
| algorithm | string | one of round_robin, least_conn |
| forwardingRules* | object[] | |
| healthCheck | object | |
| stickySessions | object | |
| redirectHttpToHttps | boolean | |
| proxyProtocol | boolean | |
| serverIds | string[] | |
| tag | string |
202 Accepted403 Forbidden/v1/load-balancers/{id}Get a load balancer with target health
| id (path)* | string |
200 OK404 Not found/v1/load-balancers/{id}Change rules
| id (path)* | string |
| name | string | |
| algorithm | string | one of round_robin, least_conn |
| forwardingRules | object[] | |
| healthCheck | object | |
| stickySessions | object | |
| redirectHttpToHttps | boolean | |
| proxyProtocol | boolean | |
| tag | string |
202 Accepted/v1/load-balancers/{id}Delete a load balancer
Deletes the nodes and releases the IP.
| id (path)* | string |
202 Accepted/v1/load-balancers/{id}/serversAdd target servers
| id (path)* | string |
| serverIds* | string[] |
202 Accepted/v1/load-balancers/{id}/servers/{serverId}Remove a target server
| id (path)* | string | |
| serverId (path)* | string |
202 Accepted/v1/certificatesList certificates
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/certificatesAdd a certificate
Either an uploaded PEM pair (custom) or a list of domains the load balancer gets issued by Let's Encrypt (letsencrypt). Point the domains at the load balancer IP first.
| name* | string | |
| type* | string | one of custom, letsencrypt |
| certPem | string | |
| keyPem | string | |
| domains | string[] | |
| project | string |
201 Created/v1/certificates/{id}Delete a certificate
| id (path)* | string |
200 Deleted409 In use by a load balancer/v1/domainsList hosted zones
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/domainsAdd a domain
Creates the zone on our nameservers. Set the domain's nameservers at the registrar to the ones returned. Free.
| name* | string | e.g. "example.com" |
| ip | string | Creates an apex A record |
| project | string |
201 Created409 Name taken/v1/domains/{name}Get a zone with its records
| name (path)* | string |
200 OK404 Not found/v1/domains/{name}Delete a zone and its records
| name (path)* | string |
200 Deleted/v1/domains/{name}/zone-fileThe zone in BIND format
| name (path)* | string |
200 OK/v1/domains/{name}/recordsAdd a record
| name (path)* | string |
| name* | string | e.g. "www" |
| type* | string | one of A, AAAA, CNAME, MX, TXT, NS, SRV, CAA |
| content* | string | A: IPv4; CNAME/MX/NS: hostname; SRV: weight port target; CAA: flags tag value; TXT: text |
| ttl | integer | |
| priority | integer | MX and SRV |
201 Created409 CNAME conflict/v1/domains/{name}/records/{id}Change a record
| name (path)* | string | |
| id (path)* | string |
| name | string | |
| content | string | |
| ttl | integer | |
| priority | integer |
200 OK/v1/domains/{name}/records/{id}Delete a record
| name (path)* | string | |
| id (path)* | string |
200 Deleted/v1/public-ips/{id}/reverse-dnsSet reverse DNS (PTR) for a public IP
| id (path)* | string |
| name | string | Hostname |
200 OK/v1/bucketsList buckets
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/bucketsCreate a bucket
Names are global and DNS safe (3 to 63 lowercase letters, digits, hyphens). Billed per GB per month.
| name* | string | |
| region | string | |
| project | string | |
| public | boolean | Anyone can read objects |
201 Created409 Name taken/v1/buckets/{name}Get a bucket
| name (path)* | string |
200 OK404 Not found/v1/buckets/{name}Change public read
| name (path)* | string |
| public | boolean |
200 OK/v1/buckets/{name}Delete an empty bucket
| name (path)* | string |
200 Deleted409 Not empty/v1/buckets/{name}/objectsList objects under a prefix
| name (path)* | string | |
| prefix (query) | string | |
| token (query) | string |
200 OK/v1/buckets/{name}/objectsDelete one object
| name (path)* | string | |
| key (query)* | string |
200 Deleted/v1/buckets/{name}/presignPresigned URL for GET
| name (path)* | string |
| key* | string | |
| method | string | one of GET, PUT, DELETE |
| expiresSeconds | integer | |
| contentType | string |
200 OK/v1/storage-keysList S3 access keys (no secrets)
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/storage-keysCreate an access key; the secret is returned once
| name* | string | |
| project | string |
201 Created/v1/storage-keys/{id}Revoke an access key
| id (path)* | string |
200 Revoked/v1/databasesList managed database clusters
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/databasesCreate a cluster
One node, or three nodes with automatic failover. Returns 202; the cluster becomes active in a few minutes. Priced per node per month.
| Idempotency-Key (header) | string |
| name* | string | |
| engine* | string | one of postgres, valkey, mysql |
| version | string | |
| size* | string | A server size id with at least 1 GB of memory |
| nodes | integer | one of 1, 3 |
| region | string | |
| project | string | |
| trustedSources | string[] | |
| backupHourUtc | integer |
202 Accepted/v1/databases/enginesEngines and versions on offer
200 OK/v1/databases/{id}Get a cluster with connection details and secrets
| id (path)* | string |
200 OK404 Not found/v1/databases/{id}Change trusted sources or the backup hour
| id (path)* | string |
| trustedSources | string[] | |
| backupHourUtc | integer |
202 Accepted/v1/databases/{id}Delete a cluster and its nodes
| id (path)* | string |
202 Accepted/v1/databases/{id}/usersAdd a user (password returned once)
| id (path)* | string |
| name* | string |
201 Created/v1/databases/{id}/users/{userId}Delete a user
| id (path)* | string | |
| userId (path)* | string |
200 Deleted/v1/databases/{id}/users/{userId}/reset-passwordReset a user's password (returned once)
| id (path)* | string | |
| userId (path)* | string |
200 OK/v1/databases/{id}/dbsAdd a database
| id (path)* | string |
| name* | string |
201 Created/v1/databases/{id}/dbs/{dbId}Remove a database from the cluster
| id (path)* | string | |
| dbId (path)* | string |
200 Deleted/v1/databases/{id}/backupsList backups
| id (path)* | string |
200 OK/v1/databases/{id}/backupsTake a backup now
| id (path)* | string |
202 Accepted/v1/kubernetes/versionsKubernetes versions on offer
200 OK/v1/kubernetes/clustersList clusters
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/kubernetes/clustersCreate a cluster
Returns 202 with status creating. One control plane node is included; ha gives three behind one address for a flat monthly fee. Worker pools are sized like servers (at least 2 GB of memory) and billed as servers. Bootstrapping takes about ten minutes; poll until active, then fetch the kubeconfig.
| Idempotency-Key (header) | string |
| name* | string | |
| version | string | e.g. "1.31" |
| region | string | |
| project | string | |
| ha | boolean | |
| controlSize | string | |
| pools* | object[] |
202 Accepted402 Spend limit (`spend_limit_reached`)429 Quota (`quota_exceeded`)/v1/kubernetes/clusters/{id}Get a cluster with its pools
| id (path)* | string |
200 OK404 Not found/v1/kubernetes/clusters/{id}Rename a cluster
| id (path)* | string |
| name | string |
200 OK/v1/kubernetes/clusters/{id}Delete a cluster with its nodes and the load balancers and volumes it created
| id (path)* | string |
202 Accepted/v1/kubernetes/clusters/{id}/kubeconfigAdmin kubeconfig as YAML
Needs kubernetes:write. Treat it like a password.
| id (path)* | string |
200 OK409 Cluster not bootstrapped yet (`invalid_state`)/v1/kubernetes/clusters/{id}/poolsAdd a worker pool
| id (path)* | string |
| name* | string | |
| size* | string | Server size id with at least 2 GB of memory |
| count* | integer | |
| labels | object | |
| taints | object[] |
202 Accepted/v1/kubernetes/clusters/{id}/pools/{poolId}Scale a pool
Growing adds servers; shrinking drains and removes the highest numbered nodes first.
| id (path)* | string | |
| poolId (path)* | string |
| count* | integer |
202 Accepted/v1/kubernetes/clusters/{id}/pools/{poolId}Remove a pool and its nodes
| id (path)* | string | |
| poolId (path)* | string |
202 Accepted400 The last pool cannot be removed/v1/app-platform/sizesContainer sizes
200 OK/v1/app-platform/appsList apps
| project (query) | string | Project id or slug (default `default`) |
200 OK/v1/app-platform/appsCreate an app
Push code, get a URL. Returns 202 with status creating; the platform picks a shared host (or starts one), builds the repository (a Dockerfile at the root, or a generated one for Node, Python, Go and static projects), runs instances containers of size and serves them at https://<name>.<apps domain> with TLS. Name the repository with repoUrl (and gitToken for a private one) or with installationId and repo from the GitHub App, which also redeploys on every push. Poll until live; on failed, read the build log.
| Idempotency-Key (header) | string |
| name* | string | Hostname label |
| repoUrl | string | |
| installationId | string | |
| repo | string | e.g. "acme/app" |
| gitToken | string | |
| branch | string | |
| port | integer | |
| size | string | one of app-xs, app-s, app-m, app-l |
| instances | integer | |
| env | object | |
| healthPath | string | |
| region | string | |
| project | string |
202 Accepted409 Name taken (`name_taken`)/v1/app-platform/apps/{id}Get an app
| id (path)* | string |
200 OK404 Not found/v1/app-platform/apps/{id}Change configuration and deploy again
env replaces the whole set. A bigger size or more instances checks the spend limit and the host's room.
| id (path)* | string |
| branch | string | |
| port | integer | |
| size | string | one of app-xs, app-s, app-m, app-l |
| instances | integer | |
| env | object | |
| healthPath | string | |
| gitToken | string |
202 Accepted/v1/app-platform/apps/{id}Delete an app
| id (path)* | string |
202 Accepted/v1/app-platform/apps/{id}/deployBuild and deploy the branch head now
| id (path)* | string |
202 Accepted/v1/app-platform/apps/{id}/stopStop the instances and the charge
| id (path)* | string |
200 OK/v1/app-platform/apps/{id}/startStart a stopped app
| id (path)* | string |
200 OK/v1/app-platform/apps/{id}/deploysDeploy history
| id (path)* | string |
200 OK/v1/app-platform/apps/{id}/logsBuild or runtime log
Fetched live from the host when reachable; the build log is cached on the app otherwise. Capped at 32 KB.
| id (path)* | string | |
| type (query) | string | one of build, runtime |
200 OK/v1/app-platform/apps/{id}/domainsAttach a custom domain
Point a CNAME at the app hostname; the certificate is issued on the first request.
| id (path)* | string |
| domain* | string |
200 OK409 Domain attached to another app (`domain_taken`)/v1/app-platform/apps/{id}/domains/{domain}Detach a custom domain
| id (path)* | string | |
| domain (path)* | string |
200 OK/v1/appsno authList marketplace apps
| category (query) | string |
200 OK/v1/apps/categoriesno authApp categories with counts
200 OK/v1/apps/{slug}no authGet an app (its `variables` describe the one-click form)
| slug (path)* | string |
200 OK404 Not found/v1/billing/topupStart a card payment that becomes prepaid credit
Returns the hosted Moyasar payment page (mada, Visa, Mastercard, Apple Pay) to send the person to. Agents cannot call this.
| amountMinor* | integer | USD 5 to 5000, SAR 200 to 200000 |
201 Created/v1/billing/invoices/{id}/payPay an open invoice by card
| id (path)* | string |
201 Created409 Invoice is not open (`invalid_state`)/v1/billing/invoices/{id}/pdfInvoice as PDF
| id (path)* | string |
200 PDF/v1/billing/paymentsCard payments of the team
200 OK/v1/billing/payments/moyasar/webhookno authMoyasar webhook (payment events
200 OK/v1/billing/payments/moyasar/callbackno authMoyasar callback after the hosted page (result verified by retrieving the invoice)
302 Redirect to the console/v1/billing/balanceCredit balance
200 OK/v1/billing/usageRated usage per resource
| project (query) | string | Project id or slug (default `default`) |
| from (query) | string | |
| to (query) | string |
200 OK/v1/billing/invoicesList invoices
200 OK/v1/billing/invoices/{id}Get an invoice with its usage lines
| id (path)* | string |
200 OK/v1/support/plansno authSupport plan catalog
Public. Plans with first response targets per priority (hours, null when the priority is not allowed on the plan) and the monthly price in the requested currency.
| currency (query) | string | one of USD, SAR |
200 OK/v1/support/planThe team's support plan
200 OK/v1/support/planChange the support plan
Needs billing:write. An upgrade checks the spend limit on the team's oldest project; a downgrade applies at once. Open tickets keep the targets of the plan they were opened under.
| plan* | string | one of free, developer, standard, premium |
200 OK/v1/support/ticketsList tickets
| status (query) | string | one of open, answered, closed, all |
| limit (query) | integer | |
| cursor (query) | string |
200 OK/v1/support/ticketsOpen a ticket
Priority must be allowed on the team's plan (400 with the allowed list otherwise). resource names what the ticket is about and must belong to the team. Owners and the opener get every answer by email.
| subject* | string | |
| body* | string | |
| priority | string | one of low, normal, high, urgent |
| resource | string | "server:<id>", "database:<id>", "load_balancer:<id>", "volume:<id>", "domain:<id>", "bucket:<id>" or "invoice:<id>" |
201 Created429 Open ticket limit for the plan (`quota_exceeded`)/v1/support/tickets/{id}Get a ticket with its messages
| id (path)* | string |
200 OK404 Not found/v1/support/tickets/{id}/messagesReply on a ticket
Reopens a closed ticket for up to 14 days after it was closed.
| id (path)* | string |
| body* | string |
201 Created/v1/support/tickets/{id}/closeClose a ticket
| id (path)* | string |
200 OK/v1/managed/plansActive managed cloud plans
Prices exclude VAT. priceMinor is null for a custom plan. Targets are minutes per priority; on BUSINESS_HOURS plans they count working minutes (09:00 to 17:00 on working days of the contract calendar, public holidays excluded).
200 OK/v1/managed/contractsThe team's contracts
Team owners only.
200 OK403 Forbidden/v1/managed/contractsRequest a managed cloud plan
Team owners only. Creates a DRAFT contract with the default responsibility matrix. A support lead reviews it, signs it and starts onboarding; the contract becomes ACTIVE, and billing starts, when onboarding is complete. One pending request per team.
| plan* | string | e.g. "ESSENTIAL" |
| calendar | string | Business hours calendar; defaults from the team countryone of SA, TR |
| notes | string |
201 Created409 A request is already pending (`request_pending`)422 Validation error/v1/managed/contracts/{id}Contract detail with SLA, responsibility matrix, onboarding progress and this month's engineer time
Team owners only.
| id (path)* | string |
200 OK404 Not found/v1/managed/contracts/{id}/assetsAssets under management with health
| id (path)* | string |
200 OK404 Not found/v1/managed/contracts/{id}/assetsAsk for an asset to be managed
Team owners only. The asset stays PENDING until an engineer approves it. PLATFORM_SERVER needs serverId; EXTERNAL_SERVER and SITE need address. Limited by the plan's maxAssets.
| id (path)* | string |
| kind* | string | one of PLATFORM_SERVER, EXTERNAL_SERVER, SITE |
| name* | string | |
| serverId | string | |
| address | string | Public IP, hostname or site URL |
| provider | string | |
| os | string | |
| notes | string |
201 Created403 Not an owner, or the plan's asset limit is reached (`quota_exceeded`)/v1/managed/assetsEvery managed asset of the team
200 OK/v1/managed/contracts/{id}/reportsMonthly reports that were sent
Team owners only. Reports are drafted on the 1st and sent by the 3rd.
| id (path)* | string |
200 OK/v1/managed/contracts/{id}/reports/{reportId}/pdfDownload a monthly report as PDF
| id (path)* | string | |
| reportId (path)* | string |
200 OK404 Not found/v1/managed/ticketsManaged cloud tickets
| status (query) | string | one of open, answered, closed, all |
| priority (query) | string | one of P1, P2, P3, P4 |
| contractId (query) | string | |
| limit (query) | integer | |
| cursor (query) | string |
200 OK/v1/managed/ticketsOpen a ticket
Due times come from the plan's targets and the contract calendar. P1 and P2 page the engineer on call. contractId is needed only when the team has more than one contract; assetId implies it. Not allowed while the contract is suspended.
| subject* | string | |
| body* | string | |
| priority | object | |
| contractId | string | |
| assetId | string |
201 Created409 The contract is not onboarding or active (`invalid_state`)/v1/managed/tickets/{id}A ticket with its messages
Internal engineer notes are never included.
| id (path)* | string |
200 OK404 Not found/v1/managed/tickets/{id}/messagesReply on a ticket
Reopens a closed ticket for up to 14 days after it was closed.
| id (path)* | string |
| body* | string |
201 Created/v1/managed/tickets/{id}/closeClose a ticket
| id (path)* | string |
200 OK/v1/webhooksList webhooks
200 OK/v1/webhooksCreate a webhook
Deliveries are signed with X-Prgd-Signature: sha256=<hmac> using the secret returned once at creation.
| url* | string | |
| events* | string[] |
201 Created/v1/webhooks/eventsList subscribable event names
200 OK/v1/webhooks/{id}Delete a webhook
| id (path)* | string |
204 DeletedEvery error is { "error": { "code", "message", "details?" } } with one of these codes.
invalid_requestunauthorizedforbiddenapproval_requirednot_foundconflictinvalid_statequota_exceededspend_limit_reachedverification_requiredaccount_suspendedidempotency_key_reusedrate_limitedworkflow_unavailableinternal_error