Sites

Create Site Transfer

Starts handing a site to someone outside your organization by emailing them a transfer link.

POST /api/sites/:site/transfer

Emails the recipient a link that lets them move the site into one of their own organizations. Nothing moves until they accept. A site has at most one pending transfer: creating a new one cancels the previous link. The link expires after 7 days.

The link is also returned in the response, so you can pass it on yourself if the email doesn't arrive.

Permissions: the admin role or above in the site's organization. API keys need the sites:write scope. A transfer must be started by a person, so organization API keys are rejected with 401.

Path Parameters

Prop

Type

Request Body

Prop

Type

Response

Returns 201 with the pending transfer.

Prop

Type

Error Responses

Errors use the standard body { error, code, message, resolution }.

Prop

Type

Request
curl -X POST "https://app.rybbit.io/api/sites/123/transfer" \
  -H "Authorization: Bearer your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "tay@example.org"
  }'
Request
const response = await fetch(
  'https://app.rybbit.io/api/sites/123/transfer',
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer your_api_key_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      email: 'tay@example.org'
    })
  }
);

const data = await response.json();
Request
import requests

response = requests.post(
    'https://app.rybbit.io/api/sites/123/transfer',
    json={
        'email': 'tay@example.org'
    },
    headers={
        'Authorization': 'Bearer your_api_key_here'
    }
)

data = response.json()
Request
$body = [
    'email' => 'tay@example.org'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://app.rybbit.io/api/sites/123/transfer');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer your_api_key_here',
    'Content-Type: application/json'
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
Request
require 'net/http'
require 'json'

uri = URI('https://app.rybbit.io/api/sites/123/transfer')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer your_api_key_here'
request['Content-Type'] = 'application/json'
request.body = {
  email: 'tay@example.org'
}.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

data = JSON.parse(response.body)
Request
body := map[string]interface{}{
    "email": "tay@example.org",
}
jsonBody, _ := json.Marshal(body)

req, _ := http.NewRequest("POST", "https://app.rybbit.io/api/sites/123/transfer", bytes.NewBuffer(jsonBody))
req.Header.Set("Authorization", "Bearer your_api_key_here")
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()

var data map[string]interface{}
json.NewDecoder(resp.Body).Decode(&data)
Request
let body = serde_json::json!({
  "email": "tay@example.org"
});

let client = reqwest::Client::new();
let res = client
    .post("https://app.rybbit.io/api/sites/123/transfer")
    .header("Authorization", "Bearer your_api_key_here")
    .json(&body)
    .send()
    .await?;

let data: serde_json::Value = res.json().await?;
Request
String json = """
{
  "email": "tay@example.org"
}
""";

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://app.rybbit.io/api/sites/123/transfer"))
    .header("Authorization", "Bearer your_api_key_here")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(json))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
Request
var body = new
{
    email = "tay@example.org"
};

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer your_api_key_here");

var content = new StringContent(
    JsonSerializer.Serialize(body),
    Encoding.UTF8,
    "application/json");

var response = await client.PostAsync("https://app.rybbit.io/api/sites/123/transfer", content);
var data = await response.Content.ReadAsStringAsync();
Response
{
  "id": "q3Zt8xK2mVb7Lp0RfY1nWc4sHd9eJg6a",
  "recipientEmail": "tay@example.org",
  "createdAt": "2026-10-31T14:22:05.000Z",
  "expiresAt": "2026-11-07T14:22:05.000Z",
  "url": "https://app.rybbit.io/transfer/q3Zt8xK2mVb7Lp0RfY1nWc4sHd9eJg6a"
}