Zaroz
Zaroz Cloud Kernel Open API

List Service Instance Custom Domains

GET
/api/v2/service-instances/{id}/custom-domains

The hostnames this service answers on: the free platform host it always has, and every domain the customer has attached. Each attachment carries a status of pending, active or failed; pending is the ordinary state between accepting a name and cert-manager completing its HTTP-01 challenge, which cannot finish until the customer's own DNS points here, so a client should render it as waiting on DNS rather than as an error. platformHost is null for a service that publishes no HTTP ingress, and also when its cluster could not be resolved: the attached names are correct either way, and a placement fault does not fail this read. platformUrl is https://{platformHost} and is set exactly when platformHost is -- the shared wildcard certificate covers every platform host, so unlike an attached domain's own url it is never waiting on a certificate to issue. 404 for a service whose product does not offer this capability, which is the same answer a service belonging to somebody else gives, and the same answer an id that was never issued gives.

List Service Instance Custom Domains › path Parameters

id
​string · uuid · required · style: simple

List Service Instance Custom Domains › Responses

This instance's platform host and attached domains

Everything the domains panel renders for one service.
​CustomDomainResponse[] · required
limit
​integer · uint · min: 0 · required

How many hostnames this service may hold at once, so a panel can disable its own add control instead of discovering the ceiling at a refusal.

platform_host
​string | null

The free platform hostname this service always answers on, or null when it publishes no HTTP ingress at all.

Also null when the instance's cluster could not be resolved, which is a different cause with the same rendering on purpose: the listing of attached domains is correct either way, and failing the whole read because a placement lookup faulted would blind a customer to the names they have already attached.

platform_url
​string | null

https://{platform_host}, present exactly when platform_host is. The shared wildcard certificate covers every platform host, so unlike a CustomDomainResponse.url this one is never waiting on a certificate to issue -- a client can render it as a ready link (copy and open-in-new-tab) the moment platform_host is non-null.


Attach Service Instance Custom Domain

POST
/api/v2/service-instances/{id}/custom-domains

Points a hostname the customer owns at this service: a Traefik ingress route and a managed HTTP-01 TLS certificate, in front of the same backend the service's platform host already serves. The hostname is validated for shape and then authorized against the caller's organization before anything is persisted, so a refusal leaves nothing to clean up. Three kinds of name get three answers: a name inside the platform's own DNS zone is refused permanently and no proof can unlock it; a single label under a parent domain staff registered is allowed if no other organization holds that label; anything else must have proven domain control first, through POST /organizations/{id}/domains/{domain}/check. A host another organization has already claimed is refused with exactly the same message an unproven domain gets, deliberately, so this route cannot be used to discover which names are in use here. Idempotent for a name already attached to this service: the existing attachment is re-applied and returned rather than duplicated. Refused with a business-rule error when the service publishes no HTTP ingress to attach to, and when it already holds the maximum number of domains the listing reports as limit. Answering 200 means the ingress and the certificate request were accepted, not that the certificate has been issued; poll the listing's status for that. A service belonging to somebody else answers 404, the same as one that does not exist.

Attach Service Instance Custom Domain › path Parameters

id
​string · uuid · required · style: simple

Attach Service Instance Custom Domain › Request Body

Point one hostname at this service. One field, and no `is_primary`. A Traefik router matches a `Host()` rule and every attached name is matched equally, so a primary flag would be a field the platform stores and never acts on -- exactly the kind of promise `capabilities.rs::validate_parameters` refuses to let a product author make. If a canonical-host redirect is wanted later it is a real behaviour with a real field, not this one.
hostname
​string · required

The fully-qualified hostname, for example shop.acme.com.

Validated as a hostname before anything is persisted: trimmed, lowercased and stripped of a trailing dot, then refused if it is empty, longer than 253 characters, an IP address literal, a single label with no dot in it, or carries a label that is empty, longer than 63 characters, hyphen-terminated, or holds anything outside [a-z0-9-].

Attach Service Instance Custom Domain › Responses

The attachment as it now stands

One hostname attached to this service.
hostname
​string · required

Normalized: lowercase, no trailing dot.

id
​string · uuid · required

The id DELETE /service-instances/{id}/custom-domains/{route_id} names. It is the ingress resource's own id, so detaching addresses the exact row that was created rather than the hostname string, which a customer could otherwise re-send in a different case or with a trailing dot and miss.

status
​string · required

pending, active or failed.

pending is not a synonym for broken. It is the ordinary state between accepting the name and cert-manager completing an HTTP-01 challenge, and that challenge cannot complete until the customer's own DNS points here -- so a client should render it as "waiting on your DNS", never as an error.

url
​string · required

https://{hostname}, assembled here so every client renders the same link rather than each concatenating its own.


Check Service Instance Custom Domain Availability

GET
/api/v2/service-instances/{id}/custom-domains/availability

Whether hostname could be attached to this service right now, without attaching it. status is available; taken when another service already holds the name (only ever said for a name the caller's organization may use, so it is not a way to list what other organizations hold); invalid for a malformed name; platform_zone for a name inside the platform's own DNS zone; not_verified when the organization has not proven control of the domain, which is also the answer for a name another organization holds. Gated like the attach it precedes, on the permission to change the service.

Check Service Instance Custom Domain Availability › path Parameters

id
​string · uuid · required · style: simple

Check Service Instance Custom Domain Availability › query Parameters

hostname
​string · required · style: form

The hostname the customer is thinking of attaching.

The hostname the customer is thinking of attaching.

Check Service Instance Custom Domain Availability › Responses

Whether the hostname could be attached

Whether a hostname could be attached right now (v1's `/custom-domain/availability`).
status
​string · required

available, taken, invalid, platform_zone or not_verified. A string on the wire, like status above, so a new state does not break a generated client.


Detach Service Instance Custom Domain

DELETE
/api/v2/service-instances/{id}/custom-domains/{route_id}

Removes one attached hostname: its ingress route, its managed TLS certificate, and its claim on the name, so the customer can attach the same domain again later -- leaving the claim behind would make their own domain permanently unusable to them after removing it once. The service's free platform host is not an attachment and cannot be removed through this route: a routeId naming it answers 404, the same as one naming another tenant's row and the same as one that never existed, because a distinguishable refusal would say which resource ids exist on this platform.

Detach Service Instance Custom Domain › path Parameters

route_id
​string · uuid · required · style: simple

The attachment being removed.

The attachment being removed.

id
​string · uuid · required · style: simple

Detach Service Instance Custom Domain › Responses

Detached

No data returned

GET
/api/v2/service-instances/{id}/domain-connect

The Domain Connect links of this service: customer-owned domains connected through the customer's own DNS provider. supported is false when the service's product does not offer Domain Connect (only products that declare an SRV record and a template do), and a client should then hide the section. Each link carries the applyUrl the browser is sent to, which is signed when a signing key is configured.

List Service Instance Domain Connect Links › path Parameters

id
​string · uuid · required · style: simple

List Service Instance Domain Connect Links › Responses

Whether the product offers Domain Connect, and its links

​DomainConnectLinkResponse[] · required
supported
​boolean · required

Whether this service's product offers Domain Connect. A client hides the section when false.


POST
/api/v2/service-instances/{id}/domain-connect/discover

Discovers a customer-owned domain's Domain Connect support (its _domainconnect TXT record and the provider's settings) and creates a pending link for this service. Never writes DNS itself: the response carries the applyUrl the browser must be sent to, where the customer approves the records at their own DNS provider. An empty host points the apex at the server. Refused when the product does not offer Domain Connect, the domain belongs to the platform, the pair is already linked, the service already holds 20 links, or the provider has no synchronous flow.

id
​string · uuid · required · style: simple
domain
​string · required

The customer's registrable domain, e.g. example.com.

host
​string · required

The subdomain label (e.g. play), or empty to point the apex at the server.

The new pending link

One Domain Connect link.
created_at
​string · date-time · required
domain
​string · required

The customer's registrable domain, e.g. example.com.

host
​string · required

The subdomain label, or empty for the apex.

hostname
​string · required

What players connect to: {host}.{domain}, or {domain} for the apex.

id
​string · uuid · required
status
​string · required

pending, active or failed. pending is the ordinary state until the customer approves the change at their DNS provider and the records propagate; render it as waiting, not as an error.

apply_url
​string | null

The browser URL that applies the template at the customer's DNS provider, or null when Domain Connect is not configured on this platform.

dns_provider_display_name
​string | null

The detected DNS provider's display name, when it publishes one.

last_error
​string | null
last_verified_at
​string | null · date-time
template_confirmed
​boolean | null

Whether the DNS provider recognizes our template: true, false, or null when the provider did not answer consistently.


DELETE
/api/v2/service-instances/{id}/domain-connect/{link_id}

Releases one Domain Connect link. Kernel never wrote DNS for it, so nothing is cleaned up at the DNS provider; the customer removes the records there. A link of another service answers 404, the same as one that never existed.

Release Service Instance Domain Connect Link › path Parameters

link_id
​string · uuid · required · style: simple

The Domain Connect link.

The Domain Connect link.

id
​string · uuid · required · style: simple

Release Service Instance Domain Connect Link › Responses

Released

No data returned

POST
/api/v2/service-instances/{id}/domain-connect/{link_id}/verify

Re-checks live DNS for one link: whether the SRV record the template creates is published and points at the expected host and port. active once it matches, failed when a different record is found, and pending while nothing has propagated yet.

Verify Service Instance Domain Connect Link › path Parameters

link_id
​string · uuid · required · style: simple

The Domain Connect link.

The Domain Connect link.

id
​string · uuid · required · style: simple

Verify Service Instance Domain Connect Link › Responses

The link after the check

One Domain Connect link.
created_at
​string · date-time · required
domain
​string · required

The customer's registrable domain, e.g. example.com.

host
​string · required

The subdomain label, or empty for the apex.

hostname
​string · required

What players connect to: {host}.{domain}, or {domain} for the apex.

id
​string · uuid · required
status
​string · required

pending, active or failed. pending is the ordinary state until the customer approves the change at their DNS provider and the records propagate; render it as waiting, not as an error.

apply_url
​string | null

The browser URL that applies the template at the customer's DNS provider, or null when Domain Connect is not configured on this platform.

dns_provider_display_name
​string | null

The detected DNS provider's display name, when it publishes one.

last_error
​string | null
last_verified_at
​string | null · date-time
template_confirmed
​boolean | null

Whether the DNS provider recognizes our template: true, false, or null when the provider did not answer consistently.


List Service Instance Game Subdomains

GET
/api/v2/service-instances/{id}/game-subdomains

This service's game subdomain (<subdomain>.<zone> pointing at its public address, with an SRV record carrying the port for games that read one) and the platform zones a new one may be taken under. A service holds at most limit (one). pending is the ordinary state until the records are created; failed is retried automatically. 404 for a service without external access, a suspended or ended one, somebody else's, or an id that was never issued.

List Service Instance Game Subdomains › path Parameters

id
​string · uuid · required · style: simple

List Service Instance Game Subdomains › Responses

The service's game subdomains and the zones on offer

Everything the game-subdomain section renders for one service.
limit
​integer · uint · min: 0 · required

How many subdomains one service may hold (1), so a client can hide its add control.

​GameSubdomainResponse[] · required
​GameSubdomainZoneResponse[] · required

The zones a new subdomain may be taken under. Empty when none is enabled.


Create Service Instance Game Subdomain

POST
/api/v2/service-instances/{id}/game-subdomains

Takes a game subdomain for this service and creates its DNS records right away when possible (the answer is then active; otherwise pending or failed, retried automatically). Refused with 422 and details zone_unavailable, invalid_subdomain, subdomain_taken or already_has_subdomain. Requires the permission to change the service's external access.

Create Service Instance Game Subdomain › path Parameters

id
​string · uuid · required · style: simple

Create Service Instance Game Subdomain › Request Body

Create a subdomain, or rename one.
parent_domain_id
​string · uuid · required
subdomain
​string · required

3-32 characters: a-z, 0-9 and inner hyphens. Normalized to lowercase.

Create Service Instance Game Subdomain › Responses

The new game subdomain

A game subdomain: `<subdomain>.<zone>` pointing at this service's public address.
created_at
​string · date-time · required
has_srv_record
​boolean · required

Whether an SRV record carries the port, so players can connect with the hostname alone. false means they must add :record_port.

hostname
​string · required

<subdomain>.<parent_domain_name>, what players connect to.

id
​string · uuid · required

Changes on a rename: a rename replaces the subdomain.

parent_domain_id
​string · uuid · required
parent_domain_name
​string · required
​GameSubdomainStatusResponse · required

Where a game subdomain's DNS records are.

subdomain
​string · required
last_synced_at
​string | null · date-time
record_ip
​string | null

The address the records point at, once they were pushed.

record_port
​integer | null · uint16 · min: 0 · max: 65535

The port players need when there is no SRV record carrying it.


Check Game Subdomain Availability

GET
/api/v2/service-instances/{id}/game-subdomains/availability

Whether a subdomain may be taken under a zone: available, taken, invalid (with the reason) or zone_unavailable. A name stays taken while a previous holder's records are being removed.

Check Game Subdomain Availability › path Parameters

id
​string · uuid · required · style: simple

Check Game Subdomain Availability › query Parameters

parent_domain_id
​string · uuid · required · style: form
subdomain
​string · required · style: form

Check Game Subdomain Availability › Responses

The availability answer

status
​GameSubdomainAvailabilityStatus · enum · required
Enum values:
available
taken
invalid
zone_unavailable
​

Set when status is invalid.


Delete Service Instance Game Subdomain

DELETE
/api/v2/service-instances/{id}/game-subdomains/{subdomain_id}

Releases this service's game subdomain and removes its DNS records (right away when possible, otherwise automatically shortly after).

Delete Service Instance Game Subdomain › path Parameters

subdomain_id
​string · uuid · required · style: simple

The game subdomain.

The game subdomain.

id
​string · uuid · required · style: simple

Delete Service Instance Game Subdomain › Responses

Released

No data returned

Rename Service Instance Game Subdomain

PATCH
/api/v2/service-instances/{id}/game-subdomains/{subdomain_id}

Replaces this service's game subdomain with a new name (and zone): the old records are removed and the new ones created. The answer carries a NEW id. Same refusals as create.

Rename Service Instance Game Subdomain › path Parameters

subdomain_id
​string · uuid · required · style: simple

The game subdomain.

The game subdomain.

id
​string · uuid · required · style: simple

Rename Service Instance Game Subdomain › Request Body

Create a subdomain, or rename one.
parent_domain_id
​string · uuid · required
subdomain
​string · required

3-32 characters: a-z, 0-9 and inner hyphens. Normalized to lowercase.

Rename Service Instance Game Subdomain › Responses

The replacement game subdomain

A game subdomain: `<subdomain>.<zone>` pointing at this service's public address.
created_at
​string · date-time · required
has_srv_record
​boolean · required

Whether an SRV record carries the port, so players can connect with the hostname alone. false means they must add :record_port.

hostname
​string · required

<subdomain>.<parent_domain_name>, what players connect to.

id
​string · uuid · required

Changes on a rename: a rename replaces the subdomain.

parent_domain_id
​string · uuid · required
parent_domain_name
​string · required
​GameSubdomainStatusResponse · required

Where a game subdomain's DNS records are.

subdomain
​string · required
last_synced_at
​string | null · date-time
record_ip
​string | null

The address the records point at, once they were pushed.

record_port
​integer | null · uint16 · min: 0 · max: 65535

The port players need when there is no SRV record carrying it.


List Service Instance External Access

GET
/api/v2/service-instances/{id}/external-access

Port allocations and quota info for this service instance. Answers from kernel state alone and never contacts a Warden node, so it is unaffected by relay health. Each allocation's protection_state is therefore the not-loaded sentinel (unknown for a protection-managed allocation, not_managed otherwise); read the live value from GET /service-instances/{id}/external-access/live. extra_slots is the staff grant on this service instance (0 without one); free_slots + extra_slots is the ceiling a new port request is refused at. 404 for a service whose product does not offer this capability, which is the same answer a service belonging to somebody else gives.

List Service Instance External Access › path Parameters

id
​string · uuid · required · style: simple

List Service Instance External Access › Responses

This instance's port allocations and quota

​PortAllocationResponse[] · required
extra_slots
​integer · int32 · required

Extra slots staff granted this service instance on top of free_slots (0 without a grant). free_slots + extra_slots is the ceiling a new port request on a shared pool is refused at.

free_slots
​integer · int32 · required
http_ingress_ips
​string[] · required
is_dedicated_ip
​boolean · required

True when this instance's ports are served from an exclusive (dedicated) IP, where the requested port becomes the public port. On a shared pool the external port is drawn at random and cannot be chosen.

used
​integer · uint · min: 0 · required

Request Service Instance Port Allocation

POST
/api/v2/service-instances/{id}/external-access

Opens one new external port on this service instance and consumes a quota slot. With matchPort false the caller names the internalPort their software listens on and the public port is drawn at random; with matchPort true the drawn port becomes both, and internalPort is ignored. The new port lands on the same public IP as every other allocation on this service, because it is pinned to the pool the instance's primary allocation already sits on -- a service whose ports were split across two IPs is a service whose players connect to one address and whose egress leaves from another. Refused with a business-rule error when the quota is spent (three slots; there is no service-instance quota override yet, so the total is the same one the listing reports), when the internal port and protocol are already allocated, when the pool has no free port, and, under relay exposure, when the workload's protected egress cannot be established -- opening a public port on an unprotected egress publishes the cluster's own address. A service belonging to somebody else answers 404, the same as one that does not exist.

Request Service Instance Port Allocation › path Parameters

id
​string · uuid · required · style: simple

Request Service Instance Port Allocation › Request Body

Ask for one new external port on this service instance (`docs/V2Plan/tracker/issues/ZC-0302-external-access-v2-has-no-write-path.md`). Two mutually exclusive shapes in one body, which is `/v1`'s own shape kept deliberately: with `match_port` false the caller names the port their software listens on inside the container and the public port is drawn at random; with `match_port` true neither is named and the drawn port becomes both, so the customer configures their software to the number they are given. `internal_port` is required in the first case and ignored in the second. On an instance served from an exclusive (dedicated) IP the public port equals the requested port, which is the point of buying one; `internal_port` there must be between 1024 and 65535, because everything below that is reserved on the node the traffic lands on.
protocol
​PortProtocol · enum · required
Enum values:
Tcp
Udp
Both
internal_port
​integer | null · uint16 · min: 0 · max: 65535

Required when match_port is false. Ignored when it is true.

match_port
​boolean
Default: false

Request Service Instance Port Allocation › Responses

The allocation that was opened

allocated_at
​string · date-time · required
external_ip
​string · required
external_port
​integer · uint16 · min: 0 · max: 65535 · required
id
​string · uuid · required
internal_port
​integer · uint16 · min: 0 · max: 65535 · required
is_primary
​boolean · required
is_system
​boolean · required
network_protection_mode
​string · required
protection_managed
​boolean · required

True when protection is auto-managed by the edge (Warden) and manual modes do not apply. Static, comes from the pool this allocation sits on, and is what a panel's "Protected" flag reads.

protection_state
​string · required

Always unknown for a protection-managed allocation on this route, and not_managed otherwise. The live detector value (normal / pressure / attack) is served separately by GET /service-instances/{id}/external-access/live, so this listing never waits on a Warden node.

protocol
​string · required
display
​string | null
​

Get Service Instance External Access Live State

GET
/api/v2/service-instances/{id}/external-access/live

The live protection state of this instance's protection-managed port allocations, read from the Warden nodes that serve them and only those. Best effort by design: a node that is unreachable, saturated, or slow is abandoned after a short per-node timeout, and its allocations are omitted with degraded set rather than reported as normal. Never fails because a relay is unavailable, so a client should render an absent allocation as unavailable, not as healthy. An instance with no protection-managed allocations contacts no relay and returns an empty list.

Get Service Instance External Access Live State › path Parameters

id
​string · uuid · required · style: simple

Get Service Instance External Access Live State › Responses

Live Warden protection state for this instance's managed allocations

Live protection state for a service instance's protection-managed allocations. Deliberately partial. Every entry is a state a node reported; a protection-managed allocation with no entry has no current state, and the client renders that as unavailable rather than as normal. `degraded` says a node serving this instance did not answer in time or could not be resolved, which is expected during an attack on the serving relay and is not an error.
​AllocationProtectionStateResponse[] · required
degraded
​boolean · required

List Service Instance Network Protection Modes

GET
/api/v2/service-instances/{id}/external-access/network-protection-modes

The network protection modes this service may choose from, for game port allocations and for a VPS's dedicated IP, and the default. Today every pool offers "normal" only: Warden expresses protection as policy documents and the external relay layer the other values came from is retired. The PATCH routes beside it accept exactly this list.

List Service Instance Network Protection Modes › path Parameters

id
​string · uuid · required · style: simple

List Service Instance Network Protection Modes › Responses

The modes on offer and the default

The protection modes a service may choose from (v1's `/network-protection-modes`).
default_mode
​string · required

The mode a new allocation starts in.

game
​string[] · required

Modes accepted for a game port allocation.

vps
​string[] · required

Modes accepted for a VPS's dedicated IP.


Release Service Instance Port Allocation

DELETE
/api/v2/service-instances/{id}/external-access/{allocation_id}

Releases one external port allocation and frees its quota slot. Any HTTP domain attached to the port is torn down first and that teardown is not best effort: an ingress route that outlived the port it targets is a public router pointing at nothing, so a failure to remove it fails the whole release and leaves the operation retryable. A system allocation -- the primary port provisioning created, which is how players reach the service at all -- is refused with a business-rule error rather than released. An allocationId naming an allocation that does not exist, or one belonging to a different service instance, is a 404: the same answer either way, since a distinguishable refusal would say which allocation ids exist.

Release Service Instance Port Allocation › path Parameters

allocation_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Release Service Instance Port Allocation › Responses

Released

No data returned

Configure Service Instance HTTP Domain

POST
/api/v2/service-instances/{id}/external-access/{allocation_id}/http

Publishes an HTTP domain in front of one TCP-capable port: a Traefik ingress route and a managed HTTP-01 TLS certificate. The domain is authorized against the caller's organization before anything is persisted, so a refusal leaves nothing to clean up. Three kinds of name get three answers: a name inside the platform's own DNS zone is refused permanently and no proof can unlock it; a single label under a parent domain staff registered is allowed if no other organization holds that label; anything else must have proven domain control first. A host another organization has already claimed is refused with exactly the same message an unproven domain gets, deliberately, so this route cannot be used to discover which names are in use here. Answering 200 means the ingress and the certificate request were accepted, not that the certificate has been issued; poll the listing's http.status for that.

Configure Service Instance HTTP Domain › path Parameters

allocation_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Configure Service Instance HTTP Domain › Request Body

Publish an HTTP domain in front of one TCP-capable allocation.
domain
​string · required

Configure Service Instance HTTP Domain › Responses

The exposure as it now stands

domain
​string · required
status
​string · required
url
​string · required

Remove Service Instance HTTP Domain

DELETE
/api/v2/service-instances/{id}/external-access/{allocation_id}/http

Removes the port's ingress route and managed TLS certificate, and releases its hostname claim so the customer can use the same name again later -- leaving the claim behind would make their own domain permanently unusable to them after removing it once. Idempotent: a port with no HTTP domain succeeds. An allocationId belonging to a different service instance is a 404, the same as one that does not exist.

Remove Service Instance HTTP Domain › path Parameters

allocation_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Remove Service Instance HTTP Domain › Responses

Removed

No data returned

Update Service Instance Allocation Network Protection Mode

PATCH
/api/v2/service-instances/{id}/external-access/{allocation_id}/network-protection-mode

Persists the network protection mode for one port allocation. "normal" is the only mode any pool accepts today: Warden expresses protection as policy documents and publishes no mode list, and the external relay layer the other values came from is retired, so anything else is refused with a business-rule error rather than silently stored. The route and the field stay because this is where a Warden policy selector will surface. An allocationId belonging to a different service instance is a 404.

Update Service Instance Allocation Network Protection Mode › path Parameters

allocation_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Update Service Instance Allocation Network Protection Mode › Request Body

Choose the network protection mode for one allocation, or for the instance's dedicated IP. `"normal"` is the only mode any pool accepts today: Warden expresses protection as policy documents and publishes no mode list, and the external relay layer this field's other values came from is retired. The field stays because it is where a Warden policy selector will surface.
mode
​string · required

Update Service Instance Allocation Network Protection Mode › Responses

The allocation as it now stands

allocated_at
​string · date-time · required
external_ip
​string · required
external_port
​integer · uint16 · min: 0 · max: 65535 · required
id
​string · uuid · required
internal_port
​integer · uint16 · min: 0 · max: 65535 · required
is_primary
​boolean · required
is_system
​boolean · required
network_protection_mode
​string · required
protection_managed
​boolean · required

True when protection is auto-managed by the edge (Warden) and manual modes do not apply. Static, comes from the pool this allocation sits on, and is what a panel's "Protected" flag reads.

protection_state
​string · required

Always unknown for a protection-managed allocation on this route, and not_managed otherwise. The live detector value (normal / pressure / attack) is served separately by GET /service-instances/{id}/external-access/live, so this listing never waits on a Warden node.

protocol
​string · required
display
​string | null
​

Update Service Instance Dedicated IP Network Protection Mode

PATCH
/api/v2/service-instances/{id}/dedicated-ip/network-protection-mode

Persists the network protection mode for this service instance's exclusive IPv4 address. Same single accepted mode as the per-allocation route above and for the same reason. A service instance that has not bought an exclusive IP has no assignment to change and answers 404, which is also what a service belonging to somebody else answers.

Update Service Instance Dedicated IP Network Protection Mode › path Parameters

id
​string · uuid · required · style: simple

Update Service Instance Dedicated IP Network Protection Mode › Request Body

Choose the network protection mode for one allocation, or for the instance's dedicated IP. `"normal"` is the only mode any pool accepts today: Warden expresses protection as policy documents and publishes no mode list, and the external relay layer this field's other values came from is retired. The field stays because it is where a Warden policy selector will surface.
mode
​string · required

Update Service Instance Dedicated IP Network Protection Mode › Responses

The assignment as it now stands

The dedicated IP assignment's protection mode after a change. Names the assignment rather than the instance because one instance's exclusive IP is one assignment row, and the id is what a subsequent read of the assignment keys on.
assignment_id
​string · uuid · required
network_protection_mode
​string · required

List Service Instance Firewall Rules

GET
/api/v2/service-instances/{id}/resources/{resource_id}/firewall/rules

Every firewall rule on this machine, ordered the way the datapath evaluates them: ingress before egress, then ascending priority. maxRulesPerDirection is the ceiling a create or replace is refused against, published here so a panel never holds it as a literal. Rules are desired state: a change made here reaches the machine when Warden next reconciles, roughly a minute later, and this listing shows what was asked for rather than what the node is currently enforcing. A machine with no rules and a machine on a shared pool both answer with an empty list; nothing on this route reports whether a dedicated IP is assigned. 404 for a resource that is not a virtual machine, for one belonging to somebody else, and for a service whose product does not offer this capability, which are deliberately the same answer.

List Service Instance Firewall Rules › path Parameters

resource_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

List Service Instance Firewall Rules › Responses

This machine's rules, in evaluation order

The whole ruleset for one machine, in the order it is evaluated. A wrapper object rather than a bare array, unlike `/v1`'s listing. A top-level array cannot grow a field without breaking every generated client, and this one already has something to say beyond the rows: `max_rules_per_direction` is the limit a `POST` will refuse against, and a panel that does not know it can only discover the ceiling by hitting it.
max_rules_per_direction
​integer · uint32 · min: 0 · required

How many rules one direction may hold. Kernel's own constant, published rather than duplicated as a frontend literal.

​FirewallRuleResponse[] · required

Replace Service Instance Firewall Rules

PUT
/api/v2/service-instances/{id}/resources/{resource_id}/firewall/rules

Replaces this machine's entire ruleset with the one supplied, atomically: every existing rule is dropped and the new set is written in one repository operation, so there is no window in which the machine is filtered by half of each. Rule ids are not preserved -- a replacement mints new ones, because the request describes a ruleset rather than an edit to particular rows. Refused whole if any rule is invalid, including one malformed cidr: a partially applied replacement would be a ruleset the customer never wrote, on a filter whose default action is allow. An empty rules array is a legitimate request and removes every rule. The audit entry names the count and not the rules.

Replace Service Instance Firewall Rules › path Parameters

resource_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Replace Service Instance Firewall Rules › Request Body

The whole ruleset, replacing whatever is stored.

Replace Service Instance Firewall Rules › Responses

The new ruleset, in evaluation order

The whole ruleset for one machine, in the order it is evaluated. A wrapper object rather than a bare array, unlike `/v1`'s listing. A top-level array cannot grow a field without breaking every generated client, and this one already has something to say beyond the rows: `max_rules_per_direction` is the limit a `POST` will refuse against, and a panel that does not know it can only discover the ceiling by hitting it.
max_rules_per_direction
​integer · uint32 · min: 0 · required

How many rules one direction may hold. Kernel's own constant, published rather than duplicated as a frontend literal.

​FirewallRuleResponse[] · required

Create Service Instance Firewall Rule

POST
/api/v2/service-instances/{id}/resources/{resource_id}/firewall/rules

Adds one rule to this machine's firewall. A tcp or udp rule must carry a port range and an icmp or any rule must not, which is the domain's rule rather than this route's, so an omitted port is a validation refusal rather than a rule matching every port. cidr is IPv4 only and no broader than /8; absent, null or blank all mean any source. Refused with a quota error once a direction holds maxRulesPerDirection rules -- ingress and egress are counted separately. Takes effect when Warden next reconciles, roughly a minute later, not on the response. The audit entry names the rule, its direction and its action.

Create Service Instance Firewall Rule › path Parameters

resource_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Create Service Instance Firewall Rule › Request Body

action
​FirewallAction · enum · required
Enum values:
allow
block
direction
​FirewallDirection · enum · required
Enum values:
ingress
egress
priority
​integer · uint16 · min: 0 · max: 65535 · required

Lower runs first. Ties are broken by the datapath, not here, so two rules sharing a priority have no defined order between them.

protocol
​FirewallProtocol · enum · required
Enum values:
tcp
udp
icmp
any
description
​string | null
Default: null
cidr
​string | null

The source range this rule matches, IPv4 only and no broader than /8. Absent, null, or empty all mean "any source".

Default: null
enabled
​boolean

Defaults to true: a rule created disabled is almost always a mistake in the client rather than an intention, and /v1 defaults the same way.

Default: true
port_from
​integer | null · uint16 · min: 0 · max: 65535

Required for tcp and udp, refused for icmp and any. The domain enforces that (FirewallRule::create), so an omitted port on a TCP rule is a validation refusal rather than a rule that matches every port.

Default: null
port_to
​integer | null · uint16 · min: 0 · max: 65535
Default: null

Create Service Instance Firewall Rule › Responses

The saved rule

One saved rule.
action
​FirewallAction · enum · required
Enum values:
allow
block
created_at
​string · date-time · required
direction
​FirewallDirection · enum · required
Enum values:
ingress
egress
enabled
​boolean · required
id
​string · uuid · required
priority
​integer · uint16 · min: 0 · max: 65535 · required
protocol
​FirewallProtocol · enum · required
Enum values:
tcp
udp
icmp
any
resource_id
​string · uuid · required

The machine this rule filters traffic to. /v1 calls this provision_id; see this module's header.

updated_at
​string · date-time · required
description
​string | null
cidr
​string | null

Rendered back as it is stored, canonicalised by ipnetwork, so a caller who wrote 10.0.0.5/8 reads 10.0.0.0/8 and can see what the rule will actually match.

port_from
​integer | null · uint16 · min: 0 · max: 65535
port_to
​integer | null · uint16 · min: 0 · max: 65535

Delete Service Instance Firewall Rule

DELETE
/api/v2/service-instances/{id}/resources/{resource_id}/firewall/rules/{rule_id}

Removes one rule. On a machine whose firewall defaults to allow, deleting a block rule opens the port it was closing, roughly a minute later when Warden reconciles; a client should say so before sending this rather than treating it as an undo. Returns no body, because there is no row left to return; read the remaining set from the listing. 404 for a rule belonging to another machine and for a rule id naming nothing, deliberately the same answer, so this path cannot be used to discover which rule ids exist. The audit entry names the rule's direction and action as well as its id, since the row itself is gone.

Delete Service Instance Firewall Rule › path Parameters

resource_id
​string · uuid · required · style: simple
rule_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Delete Service Instance Firewall Rule › Responses

Rule removed

No data returned

Update Service Instance Firewall Rule

PATCH
/api/v2/service-instances/{id}/resources/{resource_id}/firewall/rules/{rule_id}

Changes the fields named in the body and leaves the rest alone. A field sent as null is cleared rather than ignored, and that distinction matters: cidr: null widens the rule to any source, which on a block rule stops it protecting the range it was written for and on an allow rule opens the port to the internet. Moving a rule to a direction that is already full is refused with a quota error and the rule is left where it was. The result is re-validated as a whole, so a patch that removes the ports from a tcp rule is refused rather than saved as a rule matching every port. Takes effect when Warden next reconciles, roughly a minute later. 404 for a rule belonging to another machine, which is the same answer a rule id naming nothing gives.

Update Service Instance Firewall Rule › path Parameters

resource_id
​string · uuid · required · style: simple
rule_id
​string · uuid · required · style: simple
id
​string · uuid · required · style: simple

Update Service Instance Firewall Rule › Request Body

A partial update. Every field is a double option: absent leaves the stored value alone, `null` clears it. The distinction is load-bearing rather than pedantic. `cidr: null` means "match any source", which on a `Block` rule is a *widening* of what the rule stops and on an `Allow` rule opens the port to the internet. A single `Option` would have made a client that omits the field indistinguishable from one that clears it, and the safer of those two readings is not the one a PATCH usually wants.
description
​string | null
Default: null
​
Default: null
cidr
​string | null
Default: null
​
Default: null
enabled
​boolean | null
Default: null
port_from
​integer | null · uint16 · min: 0 · max: 65535
Default: null
port_to
​integer | null · uint16 · min: 0 · max: 65535
Default: null
priority
​integer | null · uint16 · min: 0 · max: 65535
Default: null
​
Default: null

Update Service Instance Firewall Rule › Responses

The rule as it now stands

One saved rule.
action
​FirewallAction · enum · required
Enum values:
allow
block
created_at
​string · date-time · required
direction
​FirewallDirection · enum · required
Enum values:
ingress
egress
enabled
​boolean · required
id
​string · uuid · required
priority
​integer · uint16 · min: 0 · max: 65535 · required
protocol
​FirewallProtocol · enum · required
Enum values:
tcp
udp
icmp
any
resource_id
​string · uuid · required

The machine this rule filters traffic to. /v1 calls this provision_id; see this module's header.

updated_at
​string · date-time · required
description
​string | null
cidr
​string | null

Rendered back as it is stored, canonicalised by ipnetwork, so a caller who wrote 10.0.0.5/8 reads 10.0.0.0/8 and can see what the rule will actually match.

port_from
​integer | null · uint16 · min: 0 · max: 65535
port_to
​integer | null · uint16 · min: 0 · max: 65535

List Service Instance Server Imports

GET
/api/v2/service-instances/{id}/server-imports

The most recent imports into this service, newest first, finished ones included. An import that is still running is the first item with a status of preparing, running or cleaning_up.

List Service Instance Server Imports › path Parameters

id
​string · uuid · required · style: simple

List Service Instance Server Imports › Responses

The service's recent imports

`GET .../server-imports`: the most recent imports, newest first.
​ServerImportResponse[] · required

Start Service Instance Server Import

POST
/api/v2/service-instances/{id}/server-imports

Starts copying a remote SFTP server's files into this service's data volume. The service must already be stopped: the import does not stop it, and answers 409 if it is running. The transfer runs in the background as a job next to the volume, after the service's other workloads on that volume (the file sidecar, SFTP) are paused; they are started again when it ends, however it ends. By default files are copied over what is there; deleteExtraneous makes the data directory match the remote exactly, deleting files the remote does not have. The remote host must be a public address: private, loopback and link-local addresses are refused with 422. The password is stored encrypted until the transfer ends and is never returned. 409 while another operation or import holds the service. Follow progress with GET .../server-imports/{import_id}.

Start Service Instance Server Import › path Parameters

id
​string · uuid · required · style: simple

Start Service Instance Server Import › Request Body

`POST .../server-imports` body.
host
​string · required

The remote server's host name or public IP address. Private, loopback and link-local addresses are refused.

password
​string · required

The remote account's password. Stored encrypted for the length of the transfer and never returned.

username
​string · required
delete_extraneous
​boolean

Also delete files in the service's data directory that the remote server does not have (a sync rather than a copy). Defaults to false.

Default: false
port
​integer | null · uint16 · min: 0 · max: 65535

The remote SFTP port. Defaults to 22.

Default: null
remote_path
​string

The directory on the remote server to copy from. Defaults to the account's root.

Default:

Start Service Instance Server Import › Responses

The import has been opened and is preparing

One import, as it stands.
bytes_transferred
​integer · int64 · required
cancel_requested
​boolean · required

The customer asked to stop. The import is still running until it moves to cleaning_up, then cancelled.

created_at
​string · date-time · required
delete_extraneous
​boolean · required
files_transferred
​integer · int64 · required
host
​string · required
id
​string · uuid · required
remote_path
​string · required
​ServerImportStatusResponse · required

Where an import is.

target_path
​string · required

The directory in the service the files are copied into.

updated_at
​string · date-time · required
username
​string · required
bytes_total
​integer | null · int64
completed_at
​string | null · date-time
current_file
​string | null

The file being copied now, when the transfer has reported one.

error
​string | null

Why the import failed, in words a customer can act on.

files_total
​integer | null · int64
port
​integer | null · uint16 · min: 0 · max: 65535
progress_percent
​number | null · double

0 to 100, by bytes when the total is known, otherwise by files.


Get Service Instance Server Import

GET
/api/v2/service-instances/{id}/server-imports/{import_id}

One import with its progress: bytes and files transferred against the totals rclone has reported so far, the file being copied, and a percentage. Poll it while the status is preparing, running or cleaning_up. A failed import carries error. An import of another service answers 404, the same as one that was never issued.

Get Service Instance Server Import › path Parameters

import_id
​string · uuid · required · style: simple

The import.

The import.

id
​string · uuid · required · style: simple

Get Service Instance Server Import › Responses

The import

One import, as it stands.
bytes_transferred
​integer · int64 · required
cancel_requested
​boolean · required

The customer asked to stop. The import is still running until it moves to cleaning_up, then cancelled.

created_at
​string · date-time · required
delete_extraneous
​boolean · required
files_transferred
​integer · int64 · required
host
​string · required
id
​string · uuid · required
remote_path
​string · required
​ServerImportStatusResponse · required

Where an import is.

target_path
​string · required

The directory in the service the files are copied into.

updated_at
​string · date-time · required
username
​string · required
bytes_total
​integer | null · int64
completed_at
​string | null · date-time
current_file
​string | null

The file being copied now, when the transfer has reported one.

error
​string | null

Why the import failed, in words a customer can act on.

files_total
​integer | null · int64
port
​integer | null · uint16 · min: 0 · max: 65535
progress_percent
​number | null · double

0 to 100, by bytes when the total is known, otherwise by files.


Cancel Service Instance Server Import

DELETE
/api/v2/service-instances/{id}/server-imports/{import_id}

Asks an unfinished import to stop. The transfer is stopped within a few seconds, the job and credentials are removed and the paused workloads are started again, after which the status becomes cancelled. Files already copied stay. The response is the import as it stands, usually still running with cancelRequested set. Cancelling an import that has finished is a business-rule refusal.

Cancel Service Instance Server Import › path Parameters

import_id
​string · uuid · required · style: simple

The import.

The import.

id
​string · uuid · required · style: simple

Cancel Service Instance Server Import › Responses

The import, with the cancel recorded

One import, as it stands.
bytes_transferred
​integer · int64 · required
cancel_requested
​boolean · required

The customer asked to stop. The import is still running until it moves to cleaning_up, then cancelled.

created_at
​string · date-time · required
delete_extraneous
​boolean · required
files_transferred
​integer · int64 · required
host
​string · required
id
​string · uuid · required
remote_path
​string · required
​ServerImportStatusResponse · required

Where an import is.

target_path
​string · required

The directory in the service the files are copied into.

updated_at
​string · date-time · required
username
​string · required
bytes_total
​integer | null · int64
completed_at
​string | null · date-time
current_file
​string | null

The file being copied now, when the transfer has reported one.

error
​string | null

Why the import failed, in words a customer can act on.

files_total
​integer | null · int64
port
​integer | null · uint16 · min: 0 · max: 65535
progress_percent
​number | null · double

0 to 100, by bytes when the total is known, otherwise by files.


Get Service Instance SFTP

GET
/api/v2/service-instances/{id}/sftp

Connection details for this service's SFTP account: username, its currently-resolved public host and port, and whether it is enabled. Never the password -- rotate it with POST .../sftp/rotate to see it once. host and port are null when the account's public port has not resolved yet; the rest of the read still succeeds. A business-rule refusal when SFTP has not been provisioned for this service yet (a fresh purchase still awaiting its first deployment, or a product with no data volume at all). 404 for a service whose product does not offer file access, the same answer a service belonging to somebody else gives, and the same answer an id that was never issued gives.

Get Service Instance SFTP › path Parameters

id
​string · uuid · required · style: simple

Get Service Instance SFTP › Responses

The account's current connection details

Connection details for a service instance's SFTP account. Never a password -- see this module's header.
enabled
​boolean · required

Whether the account is currently reachable.

username
​string · required

The single account name every SFTP deployment is provisioned with.

host
​string | null

null when the account's public port has not resolved yet (a placement fault, or the external allocation is still landing) -- the read itself still succeeds, the same rendering CustomDomainsResponse.platformHost uses for the same situation.

port
​integer | null · uint16 · min: 0 · max: 65535

Update Service Instance SFTP

PUT
/api/v2/service-instances/{id}/sftp

Enables or disables this service's SFTP account by scaling its Deployment, the same mechanism a service instance's own Start/Stop uses on its primary resource. Idempotent: setting the state it already holds still scales and still returns 200. A business-rule refusal when SFTP has not been provisioned for this service yet, and a 409 naming the operation in the way when another write is already in progress on this instance. A service belonging to somebody else answers 404, the same as one that does not exist.

Update Service Instance SFTP › path Parameters

id
​string · uuid · required · style: simple

Update Service Instance SFTP › Request Body

`PUT .../sftp` body: replaces the account's enabled state, the same `{enabled}`-field shape `schedules`' own `paused` field models a toggle with, rather than splitting into `/enable` and `/disable` verbs.
enabled
​boolean · required

Update Service Instance SFTP › Responses

The account's connection details, reflecting the new state

Connection details for a service instance's SFTP account. Never a password -- see this module's header.
enabled
​boolean · required

Whether the account is currently reachable.

username
​string · required

The single account name every SFTP deployment is provisioned with.

host
​string | null

null when the account's public port has not resolved yet (a placement fault, or the external allocation is still landing) -- the read itself still succeeds, the same rendering CustomDomainsResponse.platformHost uses for the same situation.

port
​integer | null · uint16 · min: 0 · max: 65535

Rotate Service Instance SFTP Credentials

POST
/api/v2/service-instances/{id}/sftp/rotate

Generates a new password for this service's SFTP account, writes it and rolls the account's pod so it takes effect, and returns it. The password is shown here once: neither this response nor any later GET .../sftp will carry it again. A business-rule refusal when SFTP has not been provisioned for this service yet, and a 409 naming the operation in the way when another write is already in progress on this instance.

Rotate Service Instance SFTP Credentials › path Parameters

id
​string · uuid · required · style: simple

Rotate Service Instance SFTP Credentials › Responses

The account's connection details and its new password

[`SftpConnectionResponse`] plus the password, returned only in the response to `POST .../sftp/rotate`, and only to the caller who just rotated it.
enabled
​boolean · required
password
​string · required

The new password. Shown here once; it is never returned by a subsequent read.

username
​string · required
host
​string | null
port
​integer | null · uint16 · min: 0 · max: 65535