# DNS

Ler e alterar as zonas DNS dos seus domínios pela API, com cópia antes de cada alteração.

Actualizado em 05/11/2026

A API lê e altera a zona DNS dos domínios activos da sua conta que tenham o DNS ligado. Para ligar o DNS, use o [My MozOut](https://www.my.mozout.com/clientarea.php?language=portuguese-mz&currency=5).

## O que precisa

Uma chave com `dns:read` para ler, e `dns:write` para alterar. Com uma chave `sandbox_`, ou enquanto a API está em preparação, as alterações são simuladas. Veja [Sandbox e Produção](https://docs.mozout.com/pt/api-rules.md).

## Ler a zona

[`GET /v1/domains/{domain}/dns`](https://docs.mozout.com/pt/dns.md) devolve os registos. Os que têm `read_only` a `true`, como os NS da raiz, não se alteram por aqui. Os nameservers mudam-se em [Domínios](https://docs.mozout.com/pt/domains.md).

## Registos novos

**curl**

```bash
curl -X POST "https://api.mozout.com/v1/domains/VALUE/dns" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt" \
  -H "Idempotency-Key: 9f1c2d3e-example" \
  -H "Content-Type: application/json" \
  -d '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}'
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS => '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
        'Idempotency-Key: 9f1c2d3e-example',
        'Content-Type: application/json',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
}
payload = {"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}
r = requests.post("https://api.mozout.com/v1/domains/VALUE/dns", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}),
});
console.log(response.status);
console.log(await response.text());
```


Use `@` no nome para o próprio domínio. Num `TXT`, as aspas à volta de todo o valor saem; aspas ou barras invertidas no meio do texto respondem `422`, porque o servidor de DNS gravaria outro valor. Para conferir um registo sem gravar, use [`POST /v1/domains/{domain}/dns/validate`](https://docs.mozout.com/pt/dns.md).

## Alterar e apagar

- [`PUT /v1/domains/{domain}/dns/{record_id}`](https://docs.mozout.com/pt/dns.md) altera um registo.
- [`DELETE /v1/domains/{domain}/dns/{record_id}`](https://docs.mozout.com/pt/dns.md) apaga um registo.

O `id` de um registo muda quando muda o nome, o tipo, o valor ou a prioridade; mudar só o `ttl` deixa o mesmo `id`. Use sempre o `id` da lista mais recente.

A resposta traz o que ficou na zona. Um endereço `AAAA` vem na forma curta. Um CNAME não pode ficar com outros registos no mesmo nome: responde `409` com `cname_conflict`.

## O domínio do e-mail da conta

O e-mail com que se entra na conta recebe a reposição da senha e o código de entrada. Se esse e-mail, ou o de um utilizador da conta, for deste domínio ou de um subdomínio dele, a API recusa o que decide para onde vai o correio:

- os registos MX desse nome;
- os registos A, AAAA, CNAME e NS do nome para onde os MX apontam ou, sem MX, do próprio nome;
- repor a zona, e restaurar uma cópia que mexa nestes registos.

Estes pedidos respondem `409` com o código `account_email_domain`, também em Sandbox. Faça estas alterações no [My MozOut](https://www.my.mozout.com/clientarea.php?language=portuguese-mz&currency=5). Os outros registos continuam a poder ser alterados pela API.

## Cópias e reposição

Antes de cada alteração fica uma cópia da zona. Ficam as últimas 20 de cada domínio.

- [`GET /v1/domains/{domain}/dns/backups`](https://docs.mozout.com/pt/dns.md) lista as cópias.
- [`POST /v1/domains/{domain}/dns/backups/{id}/restore`](https://docs.mozout.com/pt/dns.md) restaura uma cópia. Se `complete` vier a `false`, um registo da cópia não pôde ficar exactamente como estava: confira a lista.
- [`POST /v1/domains/{domain}/dns/reset`](https://docs.mozout.com/pt/dns.md) deixa a zona sem os seus registos. Precisa do nome do domínio em `confirm`.

## Limite

As alterações têm um limite de 20 por minuto, por conta, além do [limite geral](https://docs.mozout.com/pt/api-rules.md). As leituras da zona têm um limite de 30 por minuto, por conta. A lista pode vir de uma cópia com até 60 segundos, que não conta para esse limite. O que altera pela API aparece logo; o que altera no portal pode demorar esse tempo.


## Operações

8 operações nesta área. Clique numa operação para ver os parâmetros, os exemplos e as respostas, ou para a experimentar no Playground, sem sair da página.

### Listar os registos DNS

`GET https://api.mozout.com/v1/domains/{domain}/dns`

Precisa de `dns:read`. `read_only` marca os registos que não se podem alterar. Limite: 30 por minuto, por conta. A resposta pode vir de uma cópia com até 60 segundos, que não conta para o limite.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:read`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |

#### Exemplos

**curl**

```bash
curl "https://api.mozout.com/v1/domains/VALUE/dns" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt"
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
}
r = requests.get("https://api.mozout.com/v1/domains/VALUE/dns", headers=headers, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns", {
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
  },
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `200`

Listar os registos DNS.

```json
{
  "data": [
    {
      "id": "3f2a91c07d11e4b6",
      "name": "www",
      "type": "A",
      "value": "192.0.2.10",
      "ttl": 14400,
      "priority": 0,
      "read_only": false
    }
  ],
  "meta": {
    "domain": "example.co.mz",
    "dns_enabled": true,
    "total": 1
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `409`

A operação não se pode fazer no estado actual. Veja `details.reason`.

```json
{
  "error": {
    "code": "conflict",
    "message": "This operation only works on an active domain.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "reason": "domain_not_active"
    }
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 409 | `conflict` | A operação não se pode fazer no estado actual. Veja `details.reason`. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).


### Adicionar um registo DNS

`POST https://api.mozout.com/v1/domains/{domain}/dns`

Precisa de `dns:write`. Fica uma cópia da zona antes de cada alteração. Num registo `TXT`, as aspas à volta de todo o valor saem, e aspas ou barras invertidas no meio são recusadas com `422`. A resposta mostra o que ficou na zona: um endereço `AAAA` vem na forma curta. Um CNAME não pode ficar com outros registos no mesmo nome: responde `409` com `cname_conflict`. Se mexer nos MX, ou nos nomes para onde apontam, do domínio do e-mail da conta ou do e-mail de um utilizador dela, responde `409` com o código `account_email_domain`: faça a alteração no portal da conta.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:write`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |
| `Idempotency-Key` | cabeçalho | string | não | Identificador único deste pedido, para o repetir sem o duplicar. |

#### Corpo do pedido

| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `name` | string | sim | O nome, como `www`. Use `@` para o próprio domínio. |
| `type` | string: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA | sim |  |
| `value` | string | sim | SRV: `weight port target`. CAA: `tag value`. |
| `ttl` | integer | não |  |
| `priority` | integer | não | Para MX e SRV. No CAA é a flag. |

#### Exemplos

**curl**

```bash
curl -X POST "https://api.mozout.com/v1/domains/VALUE/dns" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt" \
  -H "Idempotency-Key: 9f1c2d3e-example" \
  -H "Content-Type: application/json" \
  -d '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}'
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS => '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
        'Idempotency-Key: 9f1c2d3e-example',
        'Content-Type: application/json',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
}
payload = {"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}
r = requests.post("https://api.mozout.com/v1/domains/VALUE/dns", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}),
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `201`

Adicionar um registo DNS.

```json
{
  "data": {
    "id": "3f2a91c07d11e4b6",
    "name": "www",
    "type": "A",
    "value": "192.0.2.10",
    "ttl": 14400,
    "priority": 0,
    "read_only": false,
    "simulated": true
  },
  "meta": {}
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `409`

A operação não se pode fazer no estado actual. Veja `details.reason`.

```json
{
  "error": {
    "code": "conflict",
    "message": "This operation only works on an active domain.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "reason": "domain_not_active"
    }
  }
}
```

##### `422`

Alguns dados não são válidos.

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Alguns dados não são válidos.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `502`

O serviço por trás da API não respondeu como esperado.

```json
{
  "error": {
    "code": "upstream_error",
    "message": "The service did not respond as expected. Please try again later.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 409 | `conflict` | A operação não se pode fazer no estado actual. Veja `details.reason`. |
| 422 | `validation_failed` | Alguns dados não são válidos. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 502 | `upstream_error` | O serviço por trás da API não respondeu como esperado. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).


### Validar um registo DNS

`POST https://api.mozout.com/v1/domains/{domain}/dns/validate`

Precisa de `dns:read`. Confere o registo sem gravar nada.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:read`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |
| `Idempotency-Key` | cabeçalho | string | não | Identificador único deste pedido, para o repetir sem o duplicar. |

#### Corpo do pedido

| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `name` | string | sim | O nome, como `www`. Use `@` para o próprio domínio. |
| `type` | string: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA | sim |  |
| `value` | string | sim | SRV: `weight port target`. CAA: `tag value`. |
| `ttl` | integer | não |  |
| `priority` | integer | não | Para MX e SRV. No CAA é a flag. |

#### Exemplos

**curl**

```bash
curl -X POST "https://api.mozout.com/v1/domains/VALUE/dns/validate" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt" \
  -H "Idempotency-Key: 9f1c2d3e-example" \
  -H "Content-Type: application/json" \
  -d '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}'
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns/validate');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS => '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
        'Idempotency-Key: 9f1c2d3e-example',
        'Content-Type: application/json',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
}
payload = {"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}
r = requests.post("https://api.mozout.com/v1/domains/VALUE/dns/validate", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns/validate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}),
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `200`

Validar um registo DNS.

```json
{
  "data": {
    "valid": true,
    "record": {
      "name": "www",
      "type": "A",
      "value": "192.0.2.10",
      "ttl": 14400,
      "priority": 0
    }
  },
  "meta": {}
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `409`

A operação não se pode fazer no estado actual. Veja `details.reason`.

```json
{
  "error": {
    "code": "conflict",
    "message": "This operation only works on an active domain.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "reason": "domain_not_active"
    }
  }
}
```

##### `422`

Alguns dados não são válidos.

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Alguns dados não são válidos.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 409 | `conflict` | A operação não se pode fazer no estado actual. Veja `details.reason`. |
| 422 | `validation_failed` | Alguns dados não são válidos. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).


### Alterar um registo DNS

`PUT https://api.mozout.com/v1/domains/{domain}/dns/{record_id}`

Precisa de `dns:write`. A resposta traz o novo `id`. Num registo `TXT`, as aspas à volta de todo o valor saem, e aspas ou barras invertidas no meio são recusadas com `422`. A resposta mostra o que ficou na zona: um endereço `AAAA` vem na forma curta. Um CNAME não pode ficar com outros registos no mesmo nome: responde `409` com `cname_conflict`. Se mexer nos MX, ou nos nomes para onde apontam, do domínio do e-mail da conta ou do e-mail de um utilizador dela, responde `409` com o código `account_email_domain`: faça a alteração no portal da conta.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:write`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `record_id` | caminho | string | sim | O `id` do registo, da lista. Muda quando o registo muda. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |

#### Corpo do pedido

| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `name` | string | sim | O nome, como `www`. Use `@` para o próprio domínio. |
| `type` | string: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA | sim |  |
| `value` | string | sim | SRV: `weight port target`. CAA: `tag value`. |
| `ttl` | integer | não |  |
| `priority` | integer | não | Para MX e SRV. No CAA é a flag. |

#### Exemplos

**curl**

```bash
curl -X PUT "https://api.mozout.com/v1/domains/VALUE/dns/VALUE" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt" \
  -H "Content-Type: application/json" \
  -d '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}'
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns/VALUE');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_POSTFIELDS => '{"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
        'Content-Type: application/json',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
}
payload = {"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}
r = requests.put("https://api.mozout.com/v1/domains/VALUE/dns/VALUE", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns/VALUE", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"name": "www", "type": "A", "value": "192.0.2.10", "ttl": 14400}),
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `200`

Alterar um registo DNS.

```json
{
  "data": {
    "id": "3f2a91c07d11e4b6",
    "name": "www",
    "type": "A",
    "value": "192.0.2.10",
    "ttl": 14400,
    "priority": 0,
    "read_only": false,
    "simulated": true
  },
  "meta": {}
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `409`

A operação não se pode fazer no estado actual. Veja `details.reason`.

```json
{
  "error": {
    "code": "conflict",
    "message": "This operation only works on an active domain.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "reason": "domain_not_active"
    }
  }
}
```

##### `422`

Alguns dados não são válidos.

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Alguns dados não são válidos.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `502`

O serviço por trás da API não respondeu como esperado.

```json
{
  "error": {
    "code": "upstream_error",
    "message": "The service did not respond as expected. Please try again later.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 409 | `conflict` | A operação não se pode fazer no estado actual. Veja `details.reason`. |
| 422 | `validation_failed` | Alguns dados não são válidos. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 502 | `upstream_error` | O serviço por trás da API não respondeu como esperado. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).


### Apagar um registo DNS

`DELETE https://api.mozout.com/v1/domains/{domain}/dns/{record_id}`

Precisa de `dns:write`. Fica primeiro uma cópia da zona. Se mexer nos MX, ou nos nomes para onde apontam, do domínio do e-mail da conta ou do e-mail de um utilizador dela, responde `409` com o código `account_email_domain`: faça a alteração no portal da conta.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:write`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `record_id` | caminho | string | sim | O `id` do registo, da lista. Muda quando o registo muda. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |

#### Exemplos

**curl**

```bash
curl -X DELETE "https://api.mozout.com/v1/domains/VALUE/dns/VALUE" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt"
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns/VALUE');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
}
r = requests.delete("https://api.mozout.com/v1/domains/VALUE/dns/VALUE", headers=headers, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns/VALUE", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
  },
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `200`

Apagar um registo DNS.

```json
{
  "data": {
    "id": "3f2a91c07d11e4b6",
    "deleted": true,
    "simulated": true
  },
  "meta": {}
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `409`

A operação não se pode fazer no estado actual. Veja `details.reason`.

```json
{
  "error": {
    "code": "conflict",
    "message": "This operation only works on an active domain.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "reason": "domain_not_active"
    }
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `502`

O serviço por trás da API não respondeu como esperado.

```json
{
  "error": {
    "code": "upstream_error",
    "message": "The service did not respond as expected. Please try again later.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 409 | `conflict` | A operação não se pode fazer no estado actual. Veja `details.reason`. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 502 | `upstream_error` | O serviço por trás da API não respondeu como esperado. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).


### Repor a zona DNS

`POST https://api.mozout.com/v1/domains/{domain}/dns/reset`

Precisa de `dns:write`. Deixa a zona sem os seus registos. Fica primeiro uma cópia da zona. Se mexer nos MX, ou nos nomes para onde apontam, do domínio do e-mail da conta ou do e-mail de um utilizador dela, responde `409` com o código `account_email_domain`: faça a alteração no portal da conta.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:write`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |
| `Idempotency-Key` | cabeçalho | string | não | Identificador único deste pedido, para o repetir sem o duplicar. |

#### Corpo do pedido

| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `confirm` | string | sim | O nome do domínio, para confirmar. |

#### Exemplos

**curl**

```bash
curl -X POST "https://api.mozout.com/v1/domains/VALUE/dns/reset" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt" \
  -H "Idempotency-Key: 9f1c2d3e-example" \
  -H "Content-Type: application/json" \
  -d '{"confirm": "example.co.mz"}'
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns/reset');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS => '{"confirm": "example.co.mz"}',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
        'Idempotency-Key: 9f1c2d3e-example',
        'Content-Type: application/json',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
}
payload = {"confirm": "example.co.mz"}
r = requests.post("https://api.mozout.com/v1/domains/VALUE/dns/reset", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns/reset", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"confirm": "example.co.mz"}),
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `200`

Repor a zona DNS.

```json
{
  "data": {
    "domain": "example.co.mz",
    "reset": true,
    "simulated": true
  },
  "meta": {}
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `409`

A operação não se pode fazer no estado actual. Veja `details.reason`.

```json
{
  "error": {
    "code": "conflict",
    "message": "This operation only works on an active domain.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "reason": "domain_not_active"
    }
  }
}
```

##### `422`

Alguns dados não são válidos.

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Alguns dados não são válidos.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `502`

O serviço por trás da API não respondeu como esperado.

```json
{
  "error": {
    "code": "upstream_error",
    "message": "The service did not respond as expected. Please try again later.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 409 | `conflict` | A operação não se pode fazer no estado actual. Veja `details.reason`. |
| 422 | `validation_failed` | Alguns dados não são válidos. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 502 | `upstream_error` | O serviço por trás da API não respondeu como esperado. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).


### Listar as cópias da zona

`GET https://api.mozout.com/v1/domains/{domain}/dns/backups`

Precisa de `dns:read`. As últimas 20 cópias, primeiro as mais recentes.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:read`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |

#### Exemplos

**curl**

```bash
curl "https://api.mozout.com/v1/domains/VALUE/dns/backups" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt"
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns/backups');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
}
r = requests.get("https://api.mozout.com/v1/domains/VALUE/dns/backups", headers=headers, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns/backups", {
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
  },
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `200`

Listar as cópias da zona.

```json
{
  "data": [
    {
      "id": 12,
      "reason": "update",
      "records": 8,
      "created_at": "2026-11-05T09:00:00+02:00"
    }
  ],
  "meta": {
    "total": 1
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).


### Restaurar uma cópia da zona

`POST https://api.mozout.com/v1/domains/{domain}/dns/backups/{id}/restore`

Precisa de `dns:write`. Tira o que não estava na cópia e põe o que faltava. `complete` vem a `false` quando um registo da cópia não pôde ficar exactamente como estava. Se mexer nos MX, ou nos nomes para onde apontam, do domínio do e-mail da conta ou do e-mail de um utilizador dela, responde `409` com o código `account_email_domain`: faça a alteração no portal da conta.

#### Autenticação

Precisa de uma chave válida no cabeçalho `Authorization: Bearer`. Permissão necessária: `dns:write`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `domain` | caminho | string | sim | O nome do domínio ou o seu `id`. |
| `id` | caminho | string | sim | O `id` da cópia. |
| `X-API-Mode` | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com `invalid_request` e a razão `mode_mismatch`. Serve para garantir que um programa nunca corre com a chave errada. |
| `Idempotency-Key` | cabeçalho | string | não | Identificador único deste pedido, para o repetir sem o duplicar. |

#### Exemplos

**curl**

```bash
curl -X POST "https://api.mozout.com/v1/domains/VALUE/dns/backups/00000000-0000-4000-8000-000000000000/restore" \
  -H "Authorization: Bearer $RLX_API_KEY" \
  -H "Accept-Language: pt" \
  -H "Idempotency-Key: 9f1c2d3e-example"
```

**PHP**

```php
<?php
$ch = curl_init('https://api.mozout.com/v1/domains/VALUE/dns/backups/00000000-0000-4000-8000-000000000000/restore');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RLX_API_KEY'),
        'Accept-Language: pt',
        'Idempotency-Key: 9f1c2d3e-example',
    ],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status, PHP_EOL, $body, PHP_EOL;
```

**Python**

```python
import os
import requests

headers = {
    "Authorization": "Bearer " + os.environ["RLX_API_KEY"],
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
}
r = requests.post("https://api.mozout.com/v1/domains/VALUE/dns/backups/00000000-0000-4000-8000-000000000000/restore", headers=headers, timeout=30)
print(r.status_code)
print(r.text)
```

**JavaScript**

```javascript
const response = await fetch("https://api.mozout.com/v1/domains/VALUE/dns/backups/00000000-0000-4000-8000-000000000000/restore", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RLX_API_KEY}`,
    "Accept-Language": "pt",
    "Idempotency-Key": "9f1c2d3e-example",
  },
});
console.log(response.status);
console.log(await response.text());
```


#### Respostas

##### `200`

Restaurar uma cópia da zona.

```json
{
  "data": {
    "domain": "example.co.mz",
    "removed": 1,
    "added": 2,
    "simulated": true,
    "complete": true
  },
  "meta": {}
}
```

| Cabeçalho | Descrição |
|---|---|
| `X-Correlation-ID` | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
| `X-RateLimit-Limit` | Pedidos permitidos por minuto. |
| `X-RateLimit-Remaining` | Pedidos que restam no minuto actual. |
| `X-RateLimit-Reset` | Quando acaba o minuto, em segundos Unix. |
| `X-API-Mode` | O modo da chave que fez o pedido: `sandbox` ou `production`. |

##### `401`

A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Chave da API em falta ou inválida.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `403`

A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`).

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "Esta chave não tem a permissão necessária.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "required": "dns:read"
    }
  }
}
```

##### `404`

Não encontrado.

```json
{
  "error": {
    "code": "not_found",
    "message": "Não encontrado.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `409`

A operação não se pode fazer no estado actual. Veja `details.reason`.

```json
{
  "error": {
    "code": "conflict",
    "message": "This operation only works on an active domain.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "reason": "domain_not_active"
    }
  }
}
```

##### `429`

Demasiados pedidos. Espere o tempo indicado em `Retry-After`.

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Demasiados pedidos. Tente de novo daqui a pouco.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Cabeçalho | Descrição |
|---|---|
| `Retry-After` | Segundos a esperar antes de tentar de novo. |

##### `500`

Ocorreu um erro interno. Indique o `correlation_id` ao suporte.

```json
{
  "error": {
    "code": "internal_error",
    "message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `502`

O serviço por trás da API não respondeu como esperado.

```json
{
  "error": {
    "code": "upstream_error",
    "message": "The service did not respond as expected. Please try again later.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```

##### `503`

A API está desligada.

```json
{
  "error": {
    "code": "disabled",
    "message": "A API está desligada de momento.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {}
  }
}
```


#### Erros

| Estado | Código | Significado |
|---|---|---|
| 401 | `unauthorized` | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | `forbidden`, `insufficient_scope`, `ip_not_allowed` | A conta não pode usar a API (`forbidden`), a chave não tem a permissão necessária (`insufficient_scope`), ou o endereço IP não está na lista da chave (`ip_not_allowed`). |
| 404 | `not_found` | Não encontrado. |
| 409 | `conflict` | A operação não se pode fazer no estado actual. Veja `details.reason`. |
| 429 | `rate_limited` | Demasiados pedidos. Espere o tempo indicado em `Retry-After`. |
| 500 | `internal_error` | Ocorreu um erro interno. Indique o `correlation_id` ao suporte. |
| 502 | `upstream_error` | O serviço por trás da API não respondeu como esperado. |
| 503 | `disabled` | A API está desligada. |

O formato dos erros está explicado em [Erros](https://docs.mozout.com/pt/api-rules.md).
