curl --request POST \
--url https://sailbox-api.sailresearch.com/v1/egress-policies \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "github",
"document": {
"allowlist": [
"github.com",
"api.github.com"
],
"rules": {
"api.github.com": [
{
"request": {
"set": {
"headers": {
"authorization": "Bearer ${secrets.GITHUB_TOKEN}"
}
}
}
}
]
}
}
}
'import requests
url = "https://sailbox-api.sailresearch.com/v1/egress-policies"
payload = {
"name": "github",
"document": {
"allowlist": ["github.com", "api.github.com"],
"rules": { "api.github.com": [{ "request": { "set": { "headers": { "authorization": "Bearer ${secrets.GITHUB_TOKEN}" } } } }] }
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'github',
document: {
allowlist: ['github.com', 'api.github.com'],
rules: {
'api.github.com': [{request: {set: {headers: {authorization: 'Bearer ${secrets.GITHUB_TOKEN}'}}}}]
}
}
})
};
fetch('https://sailbox-api.sailresearch.com/v1/egress-policies', 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/egress-policies",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'github',
'document' => [
'allowlist' => [
'github.com',
'api.github.com'
],
'rules' => [
'api.github.com' => [
[
'request' => [
'set' => [
'headers' => [
'authorization' => 'Bearer ${secrets.GITHUB_TOKEN}'
]
]
]
]
]
]
]
]),
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/egress-policies"
payload := strings.NewReader("{\n \"name\": \"github\",\n \"document\": {\n \"allowlist\": [\n \"github.com\",\n \"api.github.com\"\n ],\n \"rules\": {\n \"api.github.com\": [\n {\n \"request\": {\n \"set\": {\n \"headers\": {\n \"authorization\": \"Bearer ${secrets.GITHUB_TOKEN}\"\n }\n }\n }\n }\n ]\n }\n }\n}")
req, _ := http.NewRequest("POST", 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.post("https://sailbox-api.sailresearch.com/v1/egress-policies")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"github\",\n \"document\": {\n \"allowlist\": [\n \"github.com\",\n \"api.github.com\"\n ],\n \"rules\": {\n \"api.github.com\": [\n {\n \"request\": {\n \"set\": {\n \"headers\": {\n \"authorization\": \"Bearer ${secrets.GITHUB_TOKEN}\"\n }\n }\n }\n }\n ]\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sailbox-api.sailresearch.com/v1/egress-policies")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"github\",\n \"document\": {\n \"allowlist\": [\n \"github.com\",\n \"api.github.com\"\n ],\n \"rules\": {\n \"api.github.com\": [\n {\n \"request\": {\n \"set\": {\n \"headers\": {\n \"authorization\": \"Bearer ${secrets.GITHUB_TOKEN}\"\n }\n }\n }\n }\n ]\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"org_id": "<string>",
"name": "<string>",
"document": {
"no_network": true,
"allowlist": [
"<string>"
],
"blocked": [
"<string>"
],
"rules": {},
"missing_alpn": {}
},
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": {
"message": "name 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": "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": "create egress policy failed",
"type": "server_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Authentication service unavailable",
"type": "server_error",
"param": null,
"code": null
}
}Create an egress policy
Saves a named policy for your organization. Every secret named in the document must already exist. A saved policy’s document cannot change after creation, but its name can.
curl --request POST \
--url https://sailbox-api.sailresearch.com/v1/egress-policies \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "github",
"document": {
"allowlist": [
"github.com",
"api.github.com"
],
"rules": {
"api.github.com": [
{
"request": {
"set": {
"headers": {
"authorization": "Bearer ${secrets.GITHUB_TOKEN}"
}
}
}
}
]
}
}
}
'import requests
url = "https://sailbox-api.sailresearch.com/v1/egress-policies"
payload = {
"name": "github",
"document": {
"allowlist": ["github.com", "api.github.com"],
"rules": { "api.github.com": [{ "request": { "set": { "headers": { "authorization": "Bearer ${secrets.GITHUB_TOKEN}" } } } }] }
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'github',
document: {
allowlist: ['github.com', 'api.github.com'],
rules: {
'api.github.com': [{request: {set: {headers: {authorization: 'Bearer ${secrets.GITHUB_TOKEN}'}}}}]
}
}
})
};
fetch('https://sailbox-api.sailresearch.com/v1/egress-policies', 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/egress-policies",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'github',
'document' => [
'allowlist' => [
'github.com',
'api.github.com'
],
'rules' => [
'api.github.com' => [
[
'request' => [
'set' => [
'headers' => [
'authorization' => 'Bearer ${secrets.GITHUB_TOKEN}'
]
]
]
]
]
]
]
]),
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/egress-policies"
payload := strings.NewReader("{\n \"name\": \"github\",\n \"document\": {\n \"allowlist\": [\n \"github.com\",\n \"api.github.com\"\n ],\n \"rules\": {\n \"api.github.com\": [\n {\n \"request\": {\n \"set\": {\n \"headers\": {\n \"authorization\": \"Bearer ${secrets.GITHUB_TOKEN}\"\n }\n }\n }\n }\n ]\n }\n }\n}")
req, _ := http.NewRequest("POST", 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.post("https://sailbox-api.sailresearch.com/v1/egress-policies")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"github\",\n \"document\": {\n \"allowlist\": [\n \"github.com\",\n \"api.github.com\"\n ],\n \"rules\": {\n \"api.github.com\": [\n {\n \"request\": {\n \"set\": {\n \"headers\": {\n \"authorization\": \"Bearer ${secrets.GITHUB_TOKEN}\"\n }\n }\n }\n }\n ]\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sailbox-api.sailresearch.com/v1/egress-policies")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"github\",\n \"document\": {\n \"allowlist\": [\n \"github.com\",\n \"api.github.com\"\n ],\n \"rules\": {\n \"api.github.com\": [\n {\n \"request\": {\n \"set\": {\n \"headers\": {\n \"authorization\": \"Bearer ${secrets.GITHUB_TOKEN}\"\n }\n }\n }\n }\n ]\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"org_id": "<string>",
"name": "<string>",
"document": {
"no_network": true,
"allowlist": [
"<string>"
],
"blocked": [
"<string>"
],
"rules": {},
"missing_alpn": {}
},
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": {
"message": "name 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": "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": "create egress policy failed",
"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.
Body
Display name. It does not need to be unique. It must contain visible text and cannot contain tabs, line breaks, or other control characters. At most 128 characters after surrounding whitespace is trimmed.
1^(?=[\t-\r\u0020\u0085\u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]*[^\t-\r\u0020\u0085\u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000])[\t-\r\u0020\u0085\u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]*[^\u0000-\u001F\u007F-\u009F]+[\t-\r\u0020\u0085\u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]*$An egress policy: what a Sailbox may connect to (no_network, allowlist, and blocked) and what happens to the HTTPS requests it sends (rules). Every field is optional. The empty document {} allows every destination and applies no rules. Sail saves a normalized form (for example, host names are lowercased and defaults are filled in), so reading a policy back can return a different shape with the same behavior. At most 64 KiB when encoded. Guide: https://docs.sailresearch.com/sailboxes-egress-policy
Show child attributes
Show child attributes
Response
The policy.
Stable policy ID.
^(?: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}$Organization that owns the policy.
Display name.
An egress policy: what a Sailbox may connect to (no_network, allowlist, and blocked) and what happens to the HTTPS requests it sends (rules). Every field is optional. The empty document {} allows every destination and applies no rules. Sail saves a normalized form (for example, host names are lowercased and defaults are filled in), so reading a policy back can return a different shape with the same behavior. At most 64 KiB when encoded. Guide: https://docs.sailresearch.com/sailboxes-egress-policy
Show child attributes
Show child attributes
When the policy was created.
When the policy name last changed.