# Sync

Refresh a domain's status, expiry, and nameservers from the registrar, and poll a pending transfer.

Pull the latest state of a domain from the registrar. Use domain sync to refresh a registered domain's status, expiry date, and nameservers, and transfer sync to poll a pending inbound transfer.

## Domain sync

Refresh the stored status, expiry date, and nameservers of a domain from the registrar.

`POST /domains/{domain}/sync`

### Parameters

<ParamField path="domain" type="text" required>
  The domain to refresh, for example `example.com`.
</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/sync" \
  -H "username: $EMAIL" \
  -H "token: $TOKEN" \
  -X POST
```

```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/sync");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
    "username: {$email}",
    "token: {$token}",
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```

```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/sync",
                     headers={"username": EMAIL, "token": token()})
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 res = await fetch(`${ENDPOINT}/domains/example.com/sync`, {
  method: "POST",
  headers: { username: EMAIL, token: token() },
});
console.log(res.status, await res.json());
```

```go Go
package main

	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"io"
	"net/http"
	"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() {
	req, _ := http.NewRequest("POST", endpoint+"/domains/example.com/sync", nil)
	req.Header.Set("username", email)
	req.Header.Set("token", token())
	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 an active domain, sync updates the stored record from the registrar and returns a success status. If the registrar does not recognise the domain, it returns a `500` with the registrar's message:

```json
{"error":"Registrar Error: Domain example.com not found in this registrar."}
```

<Note>
  A `500` "Registrar Error: Domain ... not found in this registrar" appears while the domain is still pending, before it is provisioned to the registrar backing your account. Sync succeeds once the domain is active. See [Credits and billing](/guides/credits-and-billing).
</Note>

## Transfer sync

Poll the progress of a pending inbound transfer and update its status from the registrar.

`POST /domains/{domain}/transfersync`

### Parameters

<ParamField path="domain" type="text" required>
  The domain whose transfer you are polling, for example `example.com`.
</ParamField>

### Request

<CodeGroup>
```bash cURL
curl -s "$ENDPOINT/domains/example.com/transfersync" \
  -H "username: $EMAIL" \
  -H "token: $TOKEN" \
  -X POST
```

```php PHP
<?php
// Reuse the auth setup from the domain sync example above.
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "{$endpoint}/domains/example.com/transfersync");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
    "username: {$email}",
    "token: {$token}",
]);
echo curl_exec($curl);
curl_close($curl);
```

```python Python
resp = requests.post(f"{ENDPOINT}/domains/example.com/transfersync",
                     headers={"username": EMAIL, "token": token()})
print(resp.status_code, resp.json())
```

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

```go Go
req, _ := http.NewRequest("POST", endpoint+"/domains/example.com/transfersync", nil)
req.Header.Set("username", email)
req.Header.Set("token", token())
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
```
</CodeGroup>

### Response

Transfer sync returns the updated transfer status once the domain and its transfer order are active in your account. Until the domain is provisioned to the registrar, expect the same registrar-not-found error as domain sync.
