---
name: lua-painel-api
description: Uses the lua.email admin panel API (customer profile) to look up and manage domains, mailboxes, email lists (aliases), DNS, allowed and blocked senders and email logs. Use when the person asks to list mailboxes or domains, create, activate or deactivate a mailbox, change a password through a secure link, check DNS or find out why a message did not arrive, through the API or automation.
---

# lua.email admin panel API (customer profile)

The API does automatically what the panel does on screen, on behalf of the user who owns the token and only on the domains of that user's company. Address: `https://painel.lua.email/api/v1`. Format: JSON in UTF-8, always over HTTPS.

Complete, current documentation (read it when you need fields or examples): https://lua.email/en/docs-api.md (guide) and https://lua.email/en/docs-api-operacoes.md (operations with curl and Python examples).

## Security rules (always apply)

1. The token comes from the `LUA_TOKEN` environment variable. **Never ask for the token, the password, the two-step verification code or a password link in the conversation**, and never show, save or repeat them. If the variable does not exist, explain the steps: in the panel, open My profile (user menu, upper right corner) and the API token tab; under Create a new token, choose only the permissions needed and the validity, and click Create token; copy the token, which is shown only once, and keep it in the `LUA_TOKEN` variable on the computer, outside the conversation.
2. If the person pastes a token or a password into the conversation, do not use the value: warn that it has been exposed and advise revoking the token (My profile, API token) or changing the password. To create a mailbox, do not take the password through the conversation: suggest creating the mailbox on the panel screen or, through the API, using the secure-link password change right after creating it, so that the person receives the final password through the link.
3. Queries (GET) may run directly. **Before creating, changing or removing anything**, describe what will be done (domain, mailbox and values) and wait for the person's confirmation. Removals and deactivations need explicit confirmation.
4. Calls are real and cannot be undone through the API. When in doubt, query first.
5. Passwords never come back in the response: a password change returns only a secure link that expires. Hand the link to the person; never invent or ask for a password.
6. Anything blocked because of a billing issue (409 `bloqueado_pelo_billing`) is not reactivated by the API. Do not retry or work around it: explain that unblocking comes from bringing the subscription up to date and advise the person to contact the finance team or support (https://lua.email/en/support). Activating also needs confirmation, like creating, changing, removing and deactivating.
7. Use only the operations listed below. Do not invent addresses.

## How to call

Header on every call, except `/health`: `Authorization: Bearer $LUA_TOKEN`. Requests with a body carry `Content-Type: application/json`. Use the helper program (`scripts/lua_api.py`, inside this skill's folder; use the full path if you are not in it), which reads the token from the variable, repeats the call if the panel asks for a pause (429) and sends changes only with `--confirmo`:

```
python3 scripts/lua_api.py GET /domains
python3 scripts/lua_api.py GET /domains/yourcompany.com/mailboxes --param per_page=100
python3 scripts/lua_api.py POST /domains/yourcompany.com/aliases --confirmo \
  --json '{"address_local": "contact", "goto": ["maria@yourcompany.com"]}'
```

Or with curl:

```
curl -H "Authorization: Bearer $LUA_TOKEN" "https://painel.lua.email/api/v1/domains/yourcompany.com/mailboxes?per_page=100"
```

## Responses, pages and errors

- Success: `{"success": true, "data": ...}`. Lists carry `pagination` (`page`, `per_page`, `total`, `total_pages`): default of 25 items per page, maximum of 100. Keep requesting `page` while there are pages.
- Error: `{"success": false, "error", "message", "erro": {"codigo", "mensagem"}}`. Decide by the HTTP status and by `erro.codigo`; show the person the `mensagem`.
- An item of another customer answers 404, the same as one that does not exist.
- Limit: 600 calls per minute per user, across all of that user's tokens. On 429, wait the seconds given in the `Retry-After` header.
- Logs: window of up to 7 days per call, within the last 180 days. DNS: 30 changes per minute for each domain, 1 to 50 per request.
- Optional headers on changes: `X-Lua-Chamado` (ticket number) and `X-Lua-Motivo` (reason, up to 500 characters), which go to the action log.

## Token permissions (My profile, API token)

- **Read (query everything)** (`leitura`): Looks up domains, mailboxes, aliases, DNS records, logs and the support history, without changing anything.
- **Mailboxes** (`caixas`): Creates and changes mailboxes, changes passwords through a secure link, manages forwarding, mailbox aliases, plan, service groups, access requirements and mobile devices, and activates, deactivates or requests the removal of mailboxes.
- **Lists and aliases** (`listas`): Manages the domain email lists (aliases) and the allow and block lists of senders, checks and unblocks blocked IP addresses and sends requests to the postmaster.
- **DNS and routing** (`dns`): Looks up and changes the domain DNS records, applies the recommended email records and manages alias domains.
- **Email logs** (`logs`): Checks message delivery and the spam filter analysis for your domains.
- **Support (service actions)** (`suporte`): Used by the lua.email support team. Most integrations do not need it: for customers, it is required only to request a new domain, which also depends on the Request a domain through the API option in the user record.

A query (GET) passes with **Read** or with the permission for that area; creating, changing and removing require the permission for that area. The token can never do more than the user can do in the panel.

## Frequent errors

- 400: Wrong or missing field, or a missing confirmation. Fix the request using the message and the `erros` list.
- 401: `token_invalido`: the token does not exist, has expired or was revoked. Create a new token in the panel.
- 403: Missing permission (`escopo_insuficiente`), user with the Read-only or Helpdesk role, who can only query (`papel_so_consulta`), or a domain that is not the company's (`dominio_sem_acesso`).
- 404: Item does not exist or belongs to another customer (`caixa_nao_encontrada`, `dominio_nao_encontrado`).
- 409: `bloqueado_pelo_billing` (do not retry), `caixa_sem_licenca` (assign a license first), `zone_changed` or `plano_mudou` (query DNS again) and `dns_fora_da_edgium` (the domain DNS is not active at Edgium).
- 422: The panel refused the value under the same rules as the screen; read the `erros` list.
- 429: `limite_de_chamadas`: wait the `Retry-After` seconds.
- 503: A supporting service did not respond (`link_indisponivel`, `logs_indisponiveis`). Nothing was changed, unless the response says otherwise (in DNS, check `pode_ter_mudado`). Wait a few minutes and retry.

## Customer profile operations

In the paths, replace what is between braces with the real value (the domain, the full mailbox address and so on). All of them start with `/api/v1`.

### Check, token and support history

| Method and path | Permission | What it does |
|---|---|---|
| `GET /health` | Any token | Checks that the API is working. No token needed. |
| `GET /token` | Any token | Shows the user, permissions and validity of the token that made the call. |
| `DELETE /token` | Any token | Revokes the token that made the call. |
| `GET /tokens` | Any token | Lists your tokens, without the value. |
| `DELETE /tokens/{token_id}` | Any token | Revokes one of your tokens. |
| `GET /support-history` | Read | Looks up the support history: what the support team and the integrations did on your domains. |

### Domains

| Method and path | Permission | What it does |
|---|---|---|
| `GET /domains` | Read | Lists your domains. |
| `GET /domains/{domain}` | Read | Looks up a domain. |
| `POST /domains` | Support | Requests a new domain, which stays pending until the TXT record is checked in DNS. |
| `GET /domain-requests/{request_id}` | Read | Looks up a domain request. |

### Mailboxes

| Method and path | Permission | What it does |
|---|---|---|
| `GET /domains/{domain}/mailboxes` | Mailboxes | Lists the mailboxes of a domain. |
| `POST /domains/{domain}/mailboxes` | Mailboxes | Creates a mailbox. |
| `GET /mailboxes/{mailbox}` | Mailboxes | Looks up a mailbox. |
| `PUT /mailboxes/{mailbox}` | Mailboxes | Changes a mailbox. |
| `DELETE /mailboxes/{mailbox}` | Mailboxes | Removes a mailbox, following the panel removal rules. |
| `PUT /mailboxes/{mailbox}/active` | Mailboxes | Activates or deactivates a mailbox. |
| `POST /mailboxes/{mailbox}/license` | Mailboxes | Assigns a license to a mailbox that has none. |
| `POST /mailboxes/{mailbox}/password` | Mailboxes | Changes the mailbox password and returns a secure link with the new password. |
| `PUT /mailboxes/{mailbox}/2fa` | Mailboxes | Turns two-step verification (2FA) on or off for the mailbox. |
| `GET /mailboxes/{mailbox}/quota` | Read | Shows the mailbox storage use and the current plan. |
| `GET /mailboxes/{mailbox}/removal` | Mailboxes | Shows the status of the mailbox removal request. |
| `POST /mailboxes/{mailbox}/removal` | Mailboxes | Puts the mailbox in the removal queue, like the Remove button on screen. The request can be canceled in the panel while it is pending. |

### Mailbox settings

| Method and path | Permission | What it does |
|---|---|---|
| `GET /mailboxes/{mailbox}/forwarding` | Read | Looks up the addresses that receive a copy of the mailbox messages (forwarding). |
| `PUT /mailboxes/{mailbox}/forwarding` | Mailboxes | Saves the full list of addresses that receive a copy of the mailbox messages (forwarding). |
| `GET /mailboxes/{mailbox}/aliases` | Read | Lists the aliases that point to the mailbox. |
| `POST /mailboxes/{mailbox}/aliases` | Mailboxes | Adds an alias to the mailbox. |
| `DELETE /mailboxes/{mailbox}/aliases/{nickname}` | Mailboxes | Removes an alias from the mailbox. |
| `GET /mailboxes/{mailbox}/license-swap/candidates` | Read | Lists the mailboxes this one can swap plans with. |
| `GET /mailboxes/{mailbox}/license-swap/preview` | Read | Shows the preview of a plan swap between two mailboxes. |
| `POST /mailboxes/{mailbox}/license-swap` | Mailboxes | Swaps the plan between two mailboxes. |
| `GET /mailboxes/{mailbox}/service-groups` | Mailboxes | Lists the mailbox service groups. |
| `PUT /mailboxes/{mailbox}/service-groups/{group_id}` | Mailboxes | Adds the mailbox to a service group. |
| `DELETE /mailboxes/{mailbox}/service-groups/{group_id}` | Mailboxes | Removes the mailbox from a service group. |
| `GET /mailboxes/{mailbox}/access-requirements` | Mailboxes | Looks up the mailbox access requirements. |
| `PUT /mailboxes/{mailbox}/access-requirements` | Mailboxes | Changes the mailbox access requirements. |
| `GET /mailboxes/{mailbox}/deleted-recovery` | Mailboxes | Shows whether the mailbox has the Recover deleted messages feature and where it comes from. |
| `GET /mailboxes/{mailbox}/devices` | Mailboxes | Lists the mobile devices of the mailbox. |
| `POST /mailboxes/{mailbox}/devices/{device_id}/remove` | Mailboxes | Removes a device from synchronization, without erasing anything on it. |
| `POST /mailboxes/{mailbox}/devices/{device_id}/wipe` | Mailboxes | Requests a remote wipe of the device, like the Wipe the device button. |

### Email lists (aliases)

| Method and path | Permission | What it does |
|---|---|---|
| `GET /domains/{domain}/aliases` | Lists and aliases | Lists the email lists of a domain. |
| `POST /domains/{domain}/aliases` | Lists and aliases | Creates an email list. |
| `GET /aliases/{alias}` | Lists and aliases | Looks up an email list. |
| `PUT /aliases/{alias}` | Lists and aliases | Changes an email list. |
| `DELETE /aliases/{alias}` | Lists and aliases | Removes an email list. |

### Allowed and blocked senders, blocked IP and postmaster

| Method and path | Permission | What it does |
|---|---|---|
| `GET /domains/{domain}/listas/{list}` | Lists and aliases | Shows the domain allow list ({list} = branca) or block list ({list} = negra). |
| `POST /domains/{domain}/listas/{list}` | Lists and aliases | Adds a sender to the domain allow list or block list. |
| `DELETE /domains/{domain}/listas/{list}/{entry_id}` | Lists and aliases | Removes a sender from the domain allow list or block list. |
| `GET /tools/ip/{ip}/bloqueio` | Lists and aliases | Checks whether an IP address is blocked. |
| `GET /tools/ip/liberacoes` | Lists and aliases | Lists the IP addresses unblocked for 24 hours. |
| `POST /tools/ip/liberacoes` | Lists and aliases | Lifts the block on an IP address for 24 hours. |
| `DELETE /tools/ip/liberacoes/{ip}` | Lists and aliases | Ends the unblock of an IP address before it expires. |
| `POST /postmaster/pedidos` | Lists and aliases | Opens a request to the postmaster, for example to remove an IP address from a blocklist. |
| `GET /postmaster/pedidos/{protocol}` | Lists and aliases | Looks up a request to the postmaster. |

### DNS, alias domains and routing

| Method and path | Permission | What it does |
|---|---|---|
| `GET /domains/{domain}/dns` | DNS and routing | Looks up the DNS records of the domain. |
| `GET /domains/{domain}/dns/expected` | DNS and routing | Looks up the expected email records and the check against public DNS. |
| `PATCH /domains/{domain}/dns/records` | DNS and routing | Creates, changes and deletes 1 to 50 DNS records in a single request: either everything is saved or nothing is. |
| `POST /domains/{domain}/dns/email/previa` | DNS and routing | Shows the preview of the email records, without changing anything. |
| `POST /domains/{domain}/dns/email/aplicar` | DNS and routing | Applies the email records to DNS. |
| `POST /domains/{domain}/dns/email/trocar-mx` | DNS and routing | Changes the MX so that emails start arriving at lua.email. |
| `POST /domains/{domain}/dns/email/desfazer` | DNS and routing | Undoes the last email action on DNS (applying the records or changing the MX). |
| `GET /domains/{domain}/alias-domains` | DNS and routing | Lists the alias domains of a domain. |
| `POST /alias-domains` | DNS and routing | Creates an alias domain. |
| `GET /alias-domains/{aliasdomain}` | DNS and routing | Looks up an alias domain. |
| `PUT /alias-domains/{aliasdomain}` | DNS and routing | Changes an alias domain. |
| `DELETE /alias-domains/{aliasdomain}` | DNS and routing | Removes an alias domain. |
| `GET /domains/{domain}/email-transports` | DNS and routing | Lists the per-email routings of a domain (addresses delivered to another email system). |
| `GET /email-transports/{transport_id}` | DNS and routing | Looks up a per-email routing. |

### Email logs

| Method and path | Permission | What it does |
|---|---|---|
| `GET /domains/{domain}/logs/mensagens` | Email logs | Looks up message delivery for the domain and the spam filter analysis. |

## Recipes

- **List the mailboxes of a domain:** `GET /domains/{domain}/mailboxes?per_page=100` (only active ones by default; `active_only=false` includes inactive ones; `search` looks for part of the address or name). Show address, name and status in a table.
- **Create a mailbox:** `POST /domains/{domain}/mailboxes` with `{"username", "password", "name", "x_client_license_id"}`. The password must meet the panel password policy. The license must belong to the company and have a free seat: the `x_client_license_id` number appears on existing mailboxes, in `GET /domains/{domain}/mailboxes`; if you do not know which one to use, ask the person. A mailbox without a license cannot be activated.
- **Change the password:** `POST /mailboxes/{mailbox}/password` (optional body). Hand over only `data.link.url`.
- **Deactivate or activate:** `PUT /mailboxes/{mailbox}/active` with `{"enabled": false}` or `true`; send `X-Lua-Motivo`.
- **Create an email list:** `POST /domains/{domain}/aliases` with `{"address_local": "contact", "goto": ["a@...", "b@..."]}`.
- **Allow a sender:** `POST /domains/{domain}/listas/branca` with `{"origem": "supplier@example.com"}` (`negra` to block).
- **Check the email DNS:** `GET /domains/{domain}/dns/expected`; to apply, `POST /domains/{domain}/dns/email/aplicar` with `{"plan_hash": data.esperados.hash, "versao": data.esperados.versao}`. Works only with DNS active at Edgium (otherwise 409 `dns_fora_da_edgium`). Changing the MX requires the email records to be applied first and `{"confirmo": true}`.
- **Why a message did not arrive:** `GET /domains/{domain}/logs/mensagens?destinatario=...&desde=YYYY-MM-DD&ate=YYYY-MM-DD`; read `status_texto`, `resumo` and `caminho`.

## Usage example

Request: "List the mailboxes of the domain yourcompany.com."

1. Confirm that `LUA_TOKEN` exists (without showing the value). If it does not, explain how to create it, as above.
2. Call `GET /domains/yourcompany.com/mailboxes?per_page=100`.
3. Answer with a table (address, name, active) and the total from `pagination.total`. If `total_pages` is greater than 1, request the following pages.
4. On 403 `escopo_insuficiente`, explain that the token needs the Read or Mailboxes permission; on 403 `dominio_sem_acesso`, ask to check the domain name.
