# Release (transfer out)

Release a domain to another registrar by setting the gaining registrar's tag.

Release a domain to another registrar by setting the gaining registrar's tag (IPS tag). Use this to transfer a domain out of Hostraha to a different registrar.

`POST /domains/{domain}/release`

<Warning>
  Releasing a domain hands control to the gaining registrar and is irreversible from the API. Once released, the domain leaves your reseller account. Confirm the gaining registrar tag before you call this.
</Warning>

## Parameters

<ParamField path="domain" type="text" required>
  The domain to release, for example `example.com`.
</ParamField>
<ParamField body="transfertag" type="text" required>
  The gaining registrar's tag (IPS tag) to release the domain to.
</ParamField>

## Request

<CodeGroup>
```bash cURL
API_KEY="your-api-key"
EMAIL="you@example.com"
ENDPOINT="https://portal.hostraha.com/modules/addons/DomainsReseller/api/index.php"
TS=$(date -u +"%y-%m-%d %H")
TOKEN=$(printf '%s' "$API_KEY" \
  | openssl dgst -sha256 -hmac "$EMAIL:$TS" -hex \
  | sed 's/^.*= //' | tr -d '\n' | base64 -w0)
curl -s "$ENDPOINT/domains/example.com/release" \
  -H "username: $EMAIL" \
  -H "token: $TOKEN" \
  --data "transfertag=GAINING-TAG"
```

```php PHP
<?php
$apiKey   = "your-api-key";
$email    = "you@example.com";
$endpoint = "https://portal.hostraha.com/modules/addons/DomainsReseller/api/index.php";

$token = base64_encode(hash_hmac("sha256", $apiKey, "{$email}:" . gmdate("y-m-d H")));

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "{$endpoint}/domains/example.com/release");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query(["transfertag" => "GAINING-TAG"]));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
    "username: {$email}",
    "token: {$token}",
]);
echo curl_exec($curl);
curl_close($curl);
```

```python Python
from datetime import datetime, timezone

API_KEY  = "your-api-key"
EMAIL    = "you@example.com"
ENDPOINT = "https://portal.hostraha.com/modules/addons/DomainsReseller/api/index.php"

def token() -> str:
    ts = datetime.now(timezone.utc).strftime("%y-%m-%d %H")
    digest = hmac.new(f"{EMAIL}:{ts}".encode(), API_KEY.encode(), hashlib.sha256).hexdigest()
    return base64.b64encode(digest.encode()).decode()

resp = requests.post(f"{ENDPOINT}/domains/example.com/release",
                     headers={"username": EMAIL, "token": token()},
                     data={"transfertag": "GAINING-TAG"})
print(resp.status_code, resp.json())
```

```javascript Node.js

const API_KEY  = "your-api-key";
const EMAIL    = "you@example.com";
const ENDPOINT = "https://portal.hostraha.com/modules/addons/DomainsReseller/api/index.php";

function token() {
  const ts = new Date().toISOString().slice(2, 13).replace("T", " "); // "yy-mm-dd HH" UTC
  const digest = crypto.createHmac("sha256", `${EMAIL}:${ts}`).update(API_KEY).digest("hex");
  return Buffer.from(digest, "utf8").toString("base64");
}

const body = new URLSearchParams({ transfertag: "GAINING-TAG" });

const res = await fetch(`${ENDPOINT}/domains/example.com/release`, {
  method: "POST",
  headers: { username: EMAIL, token: token() },
  body,
});
console.log(res.status, await res.json());
```

```go Go
package main

	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"
)

const (
	apiKey   = "your-api-key"
	email    = "you@example.com"
	endpoint = "https://portal.hostraha.com/modules/addons/DomainsReseller/api/index.php"
)

func token() string {
	ts := time.Now().UTC().Format("06-01-02 15") // yy-mm-dd HH
	mac := hmac.New(sha256.New, []byte(email+":"+ts))
	mac.Write([]byte(apiKey))
	return base64.StdEncoding.EncodeToString([]byte(hex.EncodeToString(mac.Sum(nil))))
}

func main() {
	form := url.Values{}
	form.Set("transfertag", "GAINING-TAG")

	req, _ := http.NewRequest("POST", endpoint+"/domains/example.com/release", strings.NewReader(form.Encode()))
	req.Header.Set("username", email)
	req.Header.Set("token", token())
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
```
</CodeGroup>

## Response

On success, the API returns a success status once the release is submitted to the registry. This call was not run against the sandbox because it is destructive. Expect the same success shape as other management writes:

```json
{"status":"success","message":"","success":"success"}
```
