curl --request GET \
--url https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port} \
--header 'Authorization: Bearer <token>'import requests
url = "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}', 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}/listeners/{guest_port}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"guest_port": 123,
"protocol": "<string>",
"route_status": "<string>",
"public_url": "https://sb-9c8f1e2a-3b4d-4f5a-8c7e-1d2f3a4b5c6d-8000.sail.box",
"public_host": "<string>",
"public_port": 123,
"allowlist": [
"<string>"
]
}{
"error": {
"message": "memory_limit_gib must be between 8 and 256 for 4 vCPUs",
"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": "sailbox \"sb_9c8f1e2a-3b4d-4f5a-8c7e-1d2f3a4b5c6d\" not found",
"type": "not_found_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": "failed to fetch sailbox",
"type": "server_error",
"param": null,
"code": null
}
}{
"error": {
"message": "Authentication service unavailable",
"type": "server_error",
"param": null,
"code": null
}
}Retrieve a published port
Returns one listener of a published port and the address to reach it: the http or tcp listener, or the one protocol names.
curl --request GET \
--url https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port} \
--header 'Authorization: Bearer <token>'import requests
url = "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}', 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}/listeners/{guest_port}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://sailbox-api.sailresearch.com/v1/sailboxes/{sailbox_id}/listeners/{guest_port}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"guest_port": 123,
"protocol": "<string>",
"route_status": "<string>",
"public_url": "https://sb-9c8f1e2a-3b4d-4f5a-8c7e-1d2f3a4b5c6d-8000.sail.box",
"public_host": "<string>",
"public_port": 123,
"allowlist": [
"<string>"
]
}{
"error": {
"message": "memory_limit_gib must be between 8 and 256 for 4 vCPUs",
"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": "sailbox \"sb_9c8f1e2a-3b4d-4f5a-8c7e-1d2f3a4b5c6d\" not found",
"type": "not_found_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": "failed to fetch sailbox",
"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.
Path Parameters
Id of the Sailbox, as returned by create. It is sb_ followed by a UUID.
Port inside the Sailbox that the listener sends traffic to.
1 <= x <= 65535Query Parameters
The listener to return. Leave it out for the port's http or tcp listener; pass udp for its UDP listener.
http, tcp, udp Response
The published port.
Port inside the Sailbox that traffic is sent to.
Protocol the listener serves. Values in use today are http, tcp, and udp. New values can appear over time, so treat this as an open set.
Whether the Sailbox behind this listener is up. LISTENER_ROUTE_STATUS_ACTIVE means it is running and traffic is being routed to it. LISTENER_ROUTE_STATUS_PENDING means it is still starting. LISTENER_ROUTE_STATUS_UNAVAILABLE means the address is held for the Sailbox but nothing is routed there, which is what you see any time it is not running, such as while it is paused or sleeping. This tracks the Sailbox, not the process inside it, so an active route with nothing listening on the port still fails to answer. New values can appear over time, so treat this as an open set.
HTTPS URL for an http listener.
"https://sb-9c8f1e2a-3b4d-4f5a-8c7e-1d2f3a4b5c6d-8000.sail.box"
Host to reach a tcp or udp listener at.
Port to reach a tcp or udp listener at.
Sources allowed to reach the listener: addresses, ranges, and app names.