curl --request PUT \
--url https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"policy_id": "ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41"
}
'import requests
url = "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy"
payload = { "policy_id": "ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({policy_id: 'ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41'})
};
fetch('https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'policy_id' => 'ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy"
payload := strings.NewReader("{\n \"policy_id\": \"ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"policy_id\": \"ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"policy_id\": \"ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41\"\n}"
response = http.request(request)
puts response.read_body{
"policy_id": "ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41",
"name": "github",
"document": {
"allowlist": [
"github.com",
"api.github.com"
],
"rules": {
"api.github.com": [
{
"request": {
"set": {
"headers": {
"authorization": "Bearer ${secrets.GITHUB_TOKEN}"
}
}
}
}
]
}
}
}{
"error": {
"message": "policy_id or document is required",
"type": "invalid_request_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Invalid API key",
"type": "authentication_error",
"param": null,
"code": "invalid_api_key"
}
}{
"error": {
"message": "Your API key has been disabled due to insufficient credits. Visit https://app.sailresearch.com/billing to add credits.",
"type": "billing_error",
"param": null,
"code": "credits_exhausted",
"billing_url": "https://app.sailresearch.com/billing"
}
}{
"error": {
"message": "sailboxes require an organization-scoped API key",
"type": "permission_error",
"param": null,
"code": null
}
}{
"error": {
"message": "egress policy ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41 not found",
"type": "not_found_error",
"param": null,
"code": null
}
}{
"error": {
"message": "a Sailbox with exposed ports cannot be cut off from the network; remove its listeners first",
"type": "conflict_error",
"param": null,
"code": null
}
}{
"error": {
"message": "request body too large",
"type": "invalid_request_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Too many concurrent requests. Please retry after some of your organization's in-flight requests complete.",
"type": "rate_limit_error",
"param": null,
"code": "rate_limited"
}
}{
"error": {
"message": "the egress policy was saved but not yet applied to the network path; retry to apply it",
"type": "server_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Authentication service unavailable",
"type": "server_error",
"param": null,
"code": null
}
}Set a Sailbox's egress policy
Replaces the Sailbox’s whole policy with a saved policy or an inline document. It works on a running, paused, or sleeping Sailbox. Connections opened after the call follow the new policy; a connection that is already open keeps the policy it was opened under until it closes. A Sailbox with exposed ports cannot be given no_network; remove its listeners first.
curl --request PUT \
--url https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"policy_id": "ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41"
}
'import requests
url = "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy"
payload = { "policy_id": "ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({policy_id: 'ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41'})
};
fetch('https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'policy_id' => 'ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy"
payload := strings.NewReader("{\n \"policy_id\": \"ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"policy_id\": \"ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/egress-policy")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"policy_id\": \"ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41\"\n}"
response = http.request(request)
puts response.read_body{
"policy_id": "ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41",
"name": "github",
"document": {
"allowlist": [
"github.com",
"api.github.com"
],
"rules": {
"api.github.com": [
{
"request": {
"set": {
"headers": {
"authorization": "Bearer ${secrets.GITHUB_TOKEN}"
}
}
}
}
]
}
}
}{
"error": {
"message": "policy_id or document is required",
"type": "invalid_request_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Invalid API key",
"type": "authentication_error",
"param": null,
"code": "invalid_api_key"
}
}{
"error": {
"message": "Your API key has been disabled due to insufficient credits. Visit https://app.sailresearch.com/billing to add credits.",
"type": "billing_error",
"param": null,
"code": "credits_exhausted",
"billing_url": "https://app.sailresearch.com/billing"
}
}{
"error": {
"message": "sailboxes require an organization-scoped API key",
"type": "permission_error",
"param": null,
"code": null
}
}{
"error": {
"message": "egress policy ep_6f3a8d21-4b7c-4e90-a125-9d2f6c8b3a41 not found",
"type": "not_found_error",
"param": null,
"code": null
}
}{
"error": {
"message": "a Sailbox with exposed ports cannot be cut off from the network; remove its listeners first",
"type": "conflict_error",
"param": null,
"code": null
}
}{
"error": {
"message": "request body too large",
"type": "invalid_request_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Too many concurrent requests. Please retry after some of your organization's in-flight requests complete.",
"type": "rate_limit_error",
"param": null,
"code": "rate_limited"
}
}{
"error": {
"message": "the egress policy was saved but not yet applied to the network path; retry to apply it",
"type": "server_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Authentication service unavailable",
"type": "server_error",
"param": null,
"code": null
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
Lets an organization admin operate a private Sailbox someone else created. Say why in plain text; the reason goes into your organization's audit log, and the operation is refused without it. Ignored on Sailboxes you could already operate.
Pause, resume, sleep, scheduled wake, upgrade, and terminate accept an override. Setting an egress policy accepts one too. Running commands and moving files accept one through an SDK or the CLI. Publishing and unpublishing ports, adding and removing custom domains, checkpointing, and creating from a checkpoint stay with the creator.
^[ -~]*$Path Parameters
Id of the Sailbox, as returned by create. It is sb_ followed by a UUID.
Body
- Option 1
- Option 2
ID of a saved policy, as returned by create. Send this or document, not both.
^(?:ep|hp)_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$A policy document written inline. It cannot use secrets; save it as a policy first.
Show child attributes
Show child attributes
Response
The Sailbox's new policy.
ID of the saved policy the Sailbox uses, or null when its policy was written inline or it was created without one.
^(?:ep|hp)_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$Display name of the saved policy, or null when policy_id is null.
The policy document the Sailbox runs under. {} when every host is reachable and no rules apply.
Show child attributes
Show child attributes