API reference
Ports and SSH API
Expose guest ports as HTTPS URLs, issue access tokens for private ports, and install an SSH key.
- List exposed ports:
GET /v1/machines/{machine_id}/ports - Expose a port:
POST /v1/machines/{machine_id}/ports - Close a port:
DELETE /v1/machines/{machine_id}/ports/{port} - Issue a port access token:
POST /v1/machines/{machine_id}/ports/{port}/token - Install an SSH key:
PUT /v1/machines/{machine_id}/ssh-key - Remove the SSH key:
DELETE /v1/machines/{machine_id}/ssh-key
List exposed ports
GET /v1/machines/{machine_id}/ports
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id | path | string (uuid) | Yes | |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | PortListDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
404 | Not found in this organization (resource_not_found). | ProblemDetails |
503 | ingress_unavailable: no edge is configured | ProblemDetails |
curl "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"items": [
{
"localhost": false,
"port": 0,
"public": false,
"url": "https://hooks.example.com/vmyard"
}
],
"label": "k7f2mq3x9a1b"
}Expose a port
POST /v1/machines/{machine_id}/ports
- API key:
Authorization: Bearer vmy_…with presetuse_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner, Admin, or Operator.
- Idempotency: send a unique
Idempotency-Key; replaying the same key and body returns the same operation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id | path | string (uuid) | Yes | |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Request body (application/json, ExposePortRequest)
| Field | Type | Required | Description |
|---|---|---|---|
port | integer | Yes | Guest TCP port, 1-65535 except 22 (use the SSH key for SSH) and the desktop's 5907 and 5908 (open the desktop instead). |
localhost | boolean | No | Relay the guest's addresses to a service bound to 127.0.0.1/[::1]. |
public | boolean | No | Reachable without a token. Private ports (the default) need a token from POST /v1/machines/{machine_id}/ports/{port}/token. |
Responses
| Status | Description | Body |
|---|---|---|
202 | The port is exposed by the operation; the machine must be running | OperationAccepted |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
404 | Not found in this organization (resource_not_found). | ProblemDetails |
409 | port_limit_reached (16 ports), or idempotency_conflict | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
503 | ingress_unavailable: no edge is configured | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"port": 8080,
"public": false
}'{
"machine_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_url": "/v1/operations/6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"requested_action": "port_expose",
"status": "pending"
}Close a port
DELETE /v1/machines/{machine_id}/ports/{port}
- API key:
Authorization: Bearer vmy_…with presetuse_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner, Admin, or Operator.
- Idempotency: send a unique
Idempotency-Key; replaying the same key and body returns the same operation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id | path | string (uuid) | Yes | |
port | path | integer | Yes | |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
202 | The port is closed by the operation; it fails if the port is not exposed | OperationAccepted |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
404 | Not found in this organization (resource_not_found). | ProblemDetails |
409 | Conflicts with the current state, such as a reused idempotency key with another body (idempotency_conflict). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
503 | ingress_unavailable: no edge is configured | ProblemDetails |
curl -X DELETE "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports/$PORT" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"{
"machine_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_url": "/v1/operations/6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"requested_action": "port_unexpose",
"status": "pending"
}Issue a port access token
POST /v1/machines/{machine_id}/ports/{port}/token
- API key:
Authorization: Bearer vmy_…with presetuse_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner, Admin, or Operator.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id | path | string (uuid) | Yes | |
port | path | integer | Yes | |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Request body (application/json, PortTokenRequest)
| Field | Type | Required | Description |
|---|---|---|---|
ttl_seconds | integer | null | No | Token lifetime, 1-3600 seconds; default 900. 1–3600. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | PortTokenDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
404 | Unknown machine, or port_not_exposed | ProblemDetails |
409 | machine_not_running: the machine has no running or sleeping sandbox to bind the token to | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
503 | ingress_unavailable: no edge is configured; runtime_unavailable: the fleet could not name the machine's sandbox | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports/$PORT/token" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ttl_seconds": 900
}'{
"expires_at": "string",
"header_token": "string",
"url": "https://hooks.example.com/vmyard",
"url_with_token": "string"
}Install an SSH key
PUT /v1/machines/{machine_id}/ssh-key
- API key:
Authorization: Bearer vmy_…with presetuse_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner, Admin, or Operator.
- Idempotency: send a unique
Idempotency-Key; replaying the same key and body returns the same operation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id | path | string (uuid) | Yes | |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Request body (application/json, SetSshKeyRequest)
| Field | Type | Required | Description |
|---|---|---|---|
public_key | string | Yes | One OpenSSH public key line: ssh-ed25519, ecdsa-sha2-nistp256/384/521, or ssh-rsa of at least 3072 bits, with an optional comment, without a trailing newline. |
Responses
| Status | Description | Body |
|---|---|---|
202 | The key is installed and an SSH port allocated by the operation; the machine must be running | OperationAccepted |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
404 | Not found in this organization (resource_not_found). | ProblemDetails |
409 | Conflicts with the current state, such as a reused idempotency key with another body (idempotency_conflict). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
503 | ingress_unavailable: no edge is configured | ProblemDetails |
curl -X PUT "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ssh-key" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGq8n3nXxk0x3Sx3kq9dTq0bS4Cq3k0y8Gx4h0b7Y2pd you@laptop"
}'{
"machine_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_url": "/v1/operations/6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"requested_action": "ssh_key_set",
"status": "pending"
}Remove the SSH key
DELETE /v1/machines/{machine_id}/ssh-key
- API key:
Authorization: Bearer vmy_…with presetuse_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner, Admin, or Operator.
- Idempotency: send a unique
Idempotency-Key; replaying the same key and body returns the same operation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id | path | string (uuid) | Yes | |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
202 | The key is removed and the SSH port released by the operation; the machine must be running | OperationAccepted |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
404 | Not found in this organization (resource_not_found). | ProblemDetails |
409 | Conflicts with the current state, such as a reused idempotency key with another body (idempotency_conflict). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
503 | ingress_unavailable: no edge is configured | ProblemDetails |
curl -X DELETE "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ssh-key" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"{
"machine_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"operation_url": "/v1/operations/6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"requested_action": "ssh_key_revoke",
"status": "pending"
}