# API rules

The rules that apply to every operation: errors, limits, pagination, retries and the Sandbox and Production modes.

Updated on 5 November 2026

These rules apply to every operation of the API. On this page:

- [Errors](https://docs.mozout.com/en/api-rules.md): The error format, the list of codes and what to do in each case.
- [Limits](https://docs.mozout.com/en/api-rules.md): How many requests you can make, how to see how many are left and what to do when you exceed the limit.
- [Pagination](https://docs.mozout.com/en/api-rules.md): How list operations split results into pages.
- [Retries (Idempotency-Key)](https://docs.mozout.com/en/api-rules.md): How to repeat a request safely, without doing the same thing twice.
- [Sandbox and Production](https://docs.mozout.com/en/api-rules.md): The two API modes: what sandbox_ and prod_ keys do, and how to confirm the mode on each request.

## Errors

### Format

Every error has the same shape:

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Please try again shortly.",
    "correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "details": {
      "retry_after": 42
    }
  }
}
```

| Field | What it is |
|---|---|
| `code` | A stable code, in English. Use this field in your programs. |
| `message` | Text for people, in the language of `Accept-Language`. It can change: do not compare against it. |
| `correlation_id` | The request identifier. It is the same as the `X-Correlation-ID` header. |
| `details` | Extra data about the error. It may be empty. |

### Codes

| Status | Code | What it means | What to do |
|---|---|---|---|
| 400 | `invalid_request` | The request is not valid, for example the body is not JSON or the connection is not HTTPS. | Fix the request. |
| 401 | `unauthorized` | The key is missing, not valid, revoked or expired, or the person who created it no longer has access to the account. | Check the key or create another. |
| 402 | `insufficient_credit` | The account does not have enough credit. Nothing was charged. | Top up the credit and try again. |
| 403 | `forbidden` | The account cannot use the API at the moment. | Contact support. |
| 403 | `insufficient_scope` | The key does not have the required permission. | Create a key with that permission. |
| 403 | `ip_not_allowed` | The source IP is not on the key's list. | Use an IP on the list or create another key. |
| 403 | `spending_limit_exceeded` | The operation goes over the spending limit of the key. Nothing was charged. | Create a key with a higher limit. |
| 403 | `sms_reseller_required` | This account does not have an active SMS reseller plan. | Turn on the SMS reseller plan in the brand portal. |
| 404 | `not_found` | The resource does not exist or is not in your account. | Check the address and the identifier. |
| 405 | `method_not_allowed` | The method is not accepted on this path. | See the `Allow` header. |
| 409 | `conflict` | The operation cannot be done in the current state. The reason is in `details.reason`. | See the reason and fix it. |
| 409 | `account_email_domain` | The request touches the mail of the domain of the account email, or of a user of the account: mailboxes, forwarders, default address, MX records or nameservers. | Make the change in the account portal. |
| 409 | `idempotency_conflict` | The `Idempotency-Key` was used on another request, or the first request is still in progress. | See [Retries](https://docs.mozout.com/en/api-rules.md). |
| 422 | `validation_failed` | Some of the data is not valid. | Fix the data, with the help of `details`. |
| 429 | `rate_limited` | The request limit was exceeded. | Wait for the time in `Retry-After`. See [Limits](https://docs.mozout.com/en/api-rules.md). |
| 500 | `internal_error` | A failure on our side. | Try again later and give the `correlation_id` to support. |
| 502 | `upstream_error` | The service behind the API did not respond as expected. | Try again later and give the `correlation_id` to support. |
| 503 | `disabled` | The API is switched off at the moment. | Try again later. |

### Retry or not

- **Worth retrying, after a wait:** `429`, `500`, `502` and `503`.
- **Not worth retrying without changing something:** all the others.

On a `POST` request, always send [`Idempotency-Key`](https://docs.mozout.com/en/api-rules.md) from the first attempt and retry with the same value.

### Report a problem

Give support the `correlation_id`, the time of the request and the operation. Never send the key: support does not need it.

## Limits

### Request limits

| Who is asking | Limit |
|---|---|
| With a valid key | 90 requests per minute, per key |
| The whole account, adding up its keys | 300 requests per minute |
| Checking domain names | 30 per minute, per account |
| Reading nameservers, lock, contacts and the DNS zone | 30 per minute, per account; answers from the 60-second copy do not count |
| Changing domains and DNS | 20 per minute, per account |
| Buying domains | 5 per minute, per account |
| Requesting the transfer code | 3 per hour, per account |
| Opening tickets | 10 per hour, per account |
| Replying to tickets | 30 per hour, per account |
| Downloading an invoice PDF | 20 per minute, per account |
| Searching the Knowledge Base | 30 per minute, per account |
| Requesting a cancellation | 5 per hour, per account |
| Without a valid key | 30 requests per minute, per IP |

These are the current values and they can change. In your programs, read the headers instead of hard-coding the numbers. `GET /v1/ping` and `GET /v1/openapi.json` always count per IP, even with a key.

### Headers

Responses include:

| Header | What it is |
|---|---|
| `X-RateLimit-Limit` | Requests allowed per minute. |
| `X-RateLimit-Remaining` | Requests left in this minute. |
| `X-RateLimit-Reset` | When the minute ends, in Unix seconds. |

The [`GET /v1/limits`](https://docs.mozout.com/en/key-status.md) operation shows the same values, plus the key's spending limit.

### When you exceed the limit

The API answers `429` with the code `rate_limited` and the `Retry-After` header, which says how many seconds to wait.

- Wait at least that long before retrying.
- If the `429` comes back, wait longer on each attempt.
- Avoid very fast polling loops.

### Request size

A request body can have up to 1048576 bytes (1 MB).

## Pagination

### Parameters

| Parameter | What it is |
|---|---|
| `page` | The page number. The first one is 1. |
| `per_page` | How many results per page, from 1 to 100. The default is 10. |

An example of what is added to the address:

```text
?page=2&per_page=50
```

### Response

The results come in `data`, and `meta` says where you are:

```json
{
  "data": [],
  "meta": {
    "page": 2,
    "per_page": 50,
    "total": 120,
    "total_pages": 3
  }
}
```

| Field | What it is |
|---|---|
| `page` | The page returned. |
| `per_page` | Results per page. |
| `total` | Results in total. |
| `total_pages` | Pages in total. |

### Read all pages

Start at `page=1` and continue while `page` is lower than `total_pages`. Each page counts as one request towards the [limits](https://docs.mozout.com/en/api-rules.md).

## Retries (Idempotency-Key)

> **Note:**
>
> It applies to sending SMS, [`POST /v1/sms/messages`](https://docs.mozout.com/en/sms.md), and to domain purchases, where it is required. All operations that create or charge follow these rules.

### What it is for

If the connection fails halfway through a request, you do not know whether it went through. With the `Idempotency-Key` header, you can repeat the request with no risk of registering or charging twice.

### How to use it

Generate a unique value for each operation and send it on a `POST` request:

```text
Idempotency-Key: 0f8fad5b-d9cb-469f-a165-70867728950e
```

The value can have up to 255 visible characters. A UUID works well. Repeat the same value only when you repeat the same operation.

### What happens

The value stays reserved for each key for 24 hours.

| Situation | Response |
|---|---|
| First request with this value | The operation runs normally. |
| Same value and same body | The saved response comes back, with the `Idempotent-Replayed: true` header. Nothing is done again. |
| Same value and a different body | `409` with the code `idempotency_conflict`. |
| Same value, with the first request still in progress | `409` with the code `idempotency_conflict`. |

### After a failure

- **If you got no response:** repeat the request with the same value.
- **If you got `409` because the first is still in progress:** wait a little and repeat.
- **If you got `409` because the body is different:** use a new value, if it really is a different operation.

## Sandbox and Production

### Two modes

The address is the same in both modes: the key decides.

| | Sandbox (`sandbox_`) | Production (`prod_`) |
|---|---|---|
| Reads | Actual account data | Actual account data |
| Writes | Simulated | Change the account |
| Charges | Never | Yes, within the [spending limit](https://docs.mozout.com/en/permissions.md) |

> **Warning:**
>
> A `sandbox_` key reads actual data from your account. Keep it as carefully as a `prod_` key.

### What the response says

- Every response to a request with a key has the `X-API-Mode` header, with `sandbox` or `production`.
- Simulated writes also have `X-API-Simulated: true`.
- While the API is in preparation, not even `prod_` keys change the account or charge: writes are simulated and the `writes_simulated` field of [`GET /v1/token`](https://docs.mozout.com/en/key-status.md) is `true`.
- Keys created during the preparation, in either mode, are revoked when the API opens, and the account owner gets a notice by email. After that, create new keys.

### Find out the mode of a key

The `mode` field of [`GET /v1/token`](https://docs.mozout.com/en/key-status.md) says `sandbox` or `production`.

To make sure a program never runs with the wrong key, send the `X-API-Mode` header on the request. If it does not match the mode of the key, the API refuses with `invalid_request` and the reason `mode_mismatch`.

### Playground

Each operation, on the page of its area, has the Playground button, to make requests from the browser without leaving the page.

- The key you type stays only in the memory of that page: it is not saved and never goes in the URL.
- Use a `sandbox_` key. `prod_` keys act on your account.

### Going to Production

When the program is ready, create a `prod_` key with the minimum permissions, on the [API](https://www.my.mozout.com/api-center.php?language=english&currency=1) page. The prefix is the only difference in the request.
