# Pedidos (Atividades)

# Api de Movimentação de Pedidos

A API de Movimentação de Pedidos permite consultar o histórico de movimentações dos pedidos de uma estrutura autorizada.

Use a API para:

- buscar movimentações de pedidos em um período;
- filtrar por tipo de pedido: `COMERCIAL` ou `POS_VENDA`;
- consultar todos os pedidos da estrutura ou somente uma lista de pedidos;
- receber os dados em JSON ou CSV.

## Endereço

```
POST https://api.xeotech.com.br/api/v1/pedidos/movimentacao/{token}
```

O token é informado na URL. Não envie o token dentro do payload.

Para localizar seu token no Xeotech, acesse a página [Meu token](https://ajuda.xeotech.com.br/books/apis-de-integracao/page/meu-token-para-proprietarios).

## Autorização

O token precisa pertencer a um usuário ativo. O usuário também precisa possuir um vínculo ativo com uma estrutura ativa.

A estrutura usada na consulta é obtida pelo vínculo do usuário autenticado. O cliente não informa `estruturaId` no payload.

A consulta sempre aplica a estrutura do usuário:

```
eu.estrutura_id = estruturaIdDoUsuario
```

Mesmo que sejam enviados IDs de pedidos de outra estrutura, eles não serão retornados.

## Payload

```
{
  "dataHoraInicio": "2026-09-30 09:00:00",
  "dataHoraFim": "2026-09-30 10:00:00",
  "pedidoTipo": "COMERCIAL",
  "pedidoIds": [1001, 1002],
  "formato": "json"
}
```

<table id="bkmrk-campos-payload-movimentacao"><thead><tr class="header"><th>Campo</th><th style="text-align: right;">Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr class="odd"><td>`dataHoraInicio`</td><td style="text-align: right;">Sim</td><td>Início do período no formato `yyyy-MM-dd HH:mm:ss`.</td></tr><tr class="even"><td>`dataHoraFim`</td><td style="text-align: right;">Sim</td><td>Fim do período no formato `yyyy-MM-dd HH:mm:ss`. Deve ser posterior ao início.</td></tr><tr class="odd"><td>`pedidoTipo`</td><td style="text-align: right;">Sim</td><td>Aceita `COMERCIAL` ou `POS_VENDA`.</td></tr><tr class="even"><td>`pedidoIds`</td><td style="text-align: right;">Não</td><td>Lista de IDs de pedidos. Quando omitida ou vazia, consulta todos os pedidos da estrutura. Limite de 10.000 IDs.</td></tr><tr class="odd"><td>`formato`</td><td style="text-align: right;">Não</td><td>Aceita `json` ou `csv`. O padrão é `json`.</td></tr></tbody></table>

### Regras dos filtros

<table id="bkmrk-combinacoes-filtros-pedidos"><thead><tr class="header"><th>Payload</th><th>Resultado</th></tr></thead><tbody><tr class="odd"><td>Período + `pedidoTipo`</td><td>Todas as movimentações do período para o tipo informado, dentro da estrutura do usuário.</td></tr><tr class="even"><td>Período + `pedidoTipo` + `pedidoIds`</td><td>Somente as movimentações do período dos pedidos informados e pertencentes à estrutura do usuário.</td></tr></tbody></table>

O início do período é inclusivo e o fim é exclusivo:

```
pedido.data_hora_atualizacao >= dataHoraInicio
pedido.data_hora_atualizacao < dataHoraFim
```

As datas usam o fuso `America/Sao_Paulo`.

## Exemplos cURL

### JSON — todos os pedidos do período

```
curl --fail-with-body --location \
  --request POST \
  'https://api.xeotech.com.br/api/v1/pedidos/movimentacao/SEU_TOKEN' \
  --header 'Content-Type: application/json' \
  --output movimentacoes-pedidos.json \
  --data '{
    "dataHoraInicio": "2026-09-30 09:00:00",
    "dataHoraFim": "2026-09-30 10:00:00",
    "pedidoTipo": "COMERCIAL",
    "formato": "json"
  }'
```

### JSON — somente pedidos selecionados

```
curl --fail-with-body --location \
  --request POST \
  'https://api.xeotech.com.br/api/v1/pedidos/movimentacao/SEU_TOKEN' \
  --header 'Content-Type: application/json' \
  --output movimentacoes-pedidos.json \
  --data '{
    "dataHoraInicio": "2026-09-30 09:00:00",
    "dataHoraFim": "2026-09-30 10:00:00",
    "pedidoTipo": "POS_VENDA",
    "pedidoIds": [1001, 1002, 1003],
    "formato": "json"
  }'
```

### CSV

```
curl --fail-with-body --location \
  --request POST \
  'https://api.xeotech.com.br/api/v1/pedidos/movimentacao/SEU_TOKEN' \
  --header 'Content-Type: application/json' \
  --output movimentacoes-pedidos.csv \
  --data '{
    "dataHoraInicio": "2026-09-30 09:00:00",
    "dataHoraFim": "2026-09-30 10:00:00",
    "pedidoTipo": "COMERCIAL",
    "pedidoIds": [1001, 1002],
    "formato": "csv"
  }'
```

## Retorno JSON

```
{
  "meta": {
    "versao": "v1",
    "operacao": "movimentacao",
    "fusoHorario": "America/Sao_Paulo",
    "recebidoEm": "2026-09-30T10:00:00",
    "dataHoraInicio": "2026-09-30T09:00:00",
    "dataHoraFim": "2026-09-30T10:00:00",
    "pedidoTipo": "COMERCIAL",
    "pedidoIdsInformados": [1001, 1002]
  },
  "dados": [
    {
      "id": "123456789",
      "pedidoId": 1001,
      "euEntrouId": 20,
      "euSaiuId": 21,
      "etapaId": 8,
      "cpfCnpjCliente": "12345678000199",
      "nomeCliente": "Empresa Exemplo Ltda.",
      "numeroAtividade": "PED-1001",
      "nomeEtapa": "Em análise",
      "usuarioEntrou": "Usuário Entrada",
      "usuarioSaiu": "Usuário Saída",
      "dataHoraEntrou": "2026-09-30T09:10:00",
      "dataHoraSaiu": "2026-09-30T09:45:00",
      "tempo": "00:35:00",
      "slaHoras": 24,
      "tagsAtividade": "#PRIORIDADE,#CLIENTE",
      "movimentacao": "Avanço de etapa",
      "nomeConsultor": "Consultor Exemplo",
      "total": 149.90,
      "compromissoMensal": 99.90,
      "pedidoTipo": "COMERCIAL",
      "controlaBko": true
    }
  ],
  "totalRegistros": 1
}
```

O objeto `dados` utiliza os 22 campos do `PedidoStatusDTO`. Campos sem valor podem retornar `null`.

<table id="bkmrk-campos-retorno-movimentacao"><thead><tr class="header"><th>Campo</th><th>Descrição</th></tr></thead><tbody><tr class="odd"><td>`id`</td><td>Identificador gerado para a linha retornada.</td></tr><tr class="even"><td>`pedidoId`</td><td>ID do pedido.</td></tr><tr class="odd"><td>`euEntrouId` / `euSaiuId`</td><td>IDs dos vínculos de estrutura dos usuários que entraram e saíram.</td></tr><tr class="even"><td>`etapaId` / `nomeEtapa`</td><td>Etapa relacionada à movimentação.</td></tr><tr class="odd"><td>`cpfCnpjCliente` / `nomeCliente`</td><td>Identificação do cliente.</td></tr><tr class="even"><td>`numeroAtividade`</td><td>Número da atividade/pedido.</td></tr><tr class="odd"><td>`usuarioEntrou` / `usuarioSaiu`</td><td>Usuários associados à entrada e à saída.</td></tr><tr class="even"><td>`dataHoraEntrou` / `dataHoraSaiu`</td><td>Datas e horas da movimentação.</td></tr><tr class="odd"><td>`tempo` / `slaHoras`</td><td>Tempo calculado e SLA da etapa.</td></tr><tr class="even"><td>`tagsAtividade` / `movimentacao`</td><td>Tags e descrição da movimentação.</td></tr><tr class="odd"><td>`nomeConsultor`</td><td>Consultor associado ao pedido.</td></tr><tr class="even"><td>`total` / `compromissoMensal`</td><td>Valores financeiros do pedido.</td></tr><tr class="odd"><td>`pedidoTipo` / `controlaBko`</td><td>Tipo de pedido e indicador de controle BKO.</td></tr></tbody></table>

O campo `id` retornado pela consulta não deve ser usado como chave permanente de `upsert`. Para uma cópia local, use uma chave composta com os campos de negócio necessários, como `pedidoId`, `etapaId`, `dataHoraEntrou`, `dataHoraSaiu` e `movimentacao`.

## Retorno CSV

O CSV usa UTF-8 com BOM, separador `;`, cabeçalho e quebra de linha CRLF.

```
id;pedidoId;euEntrouId;euSaiuId;etapaId;cpfCnpjCliente;nomeCliente;numeroAtividade;nomeEtapa;usuarioEntrou;usuarioSaiu;dataHoraEntrou;dataHoraSaiu;tempo;slaHoras;tagsAtividade;movimentacao;nomeConsultor;total;compromissoMensal;pedidoTipo;controlaBko
```

Datas e horas seguem o formato ISO no JSON e são gravadas como texto no CSV. Valores nulos geram células vazias.

## Limites e guard

A API de movimentação utiliza os mesmos limites da API de produção, com guard próprio para os pedidos:

<table id="bkmrk-limites-movimentacao-pedidos"><thead><tr class="header"><th>Regra</th><th style="text-align: right;">Limite padrão</th></tr></thead><tbody><tr class="odd"><td>Execuções simultâneas globais</td><td style="text-align: right;">2</td></tr><tr class="even"><td>Execuções simultâneas por estrutura</td><td style="text-align: right;">1</td></tr><tr class="odd"><td>Intervalo mínimo após uma execução</td><td style="text-align: right;">120 segundos</td></tr><tr class="even"><td>Execuções por estrutura</td><td style="text-align: right;">3 a cada 10 minutos</td></tr><tr class="odd"><td>Tentativas por token</td><td style="text-align: right;">20 a cada 60 segundos</td></tr><tr class="even"><td>Tentativas globais</td><td style="text-align: right;">600 a cada 60 segundos</td></tr><tr class="odd"><td>Autenticações simultâneas</td><td style="text-align: right;">8</td></tr><tr class="even"><td>Registros por resposta</td><td style="text-align: right;">1.000.000</td></tr><tr class="odd"><td>Tamanho máximo do payload</td><td style="text-align: right;">16 KiB</td></tr><tr class="even"><td>IDs no campo `pedidoIds`</td><td style="text-align: right;">10.000</td></tr></tbody></table>

As tentativas recusadas também entram no controle. Quando um limite for atingido, a resposta será `429` com o header `Retry-After`.

## Respostas de erro

<table id="bkmrk-erros-movimentacao-pedidos"><thead><tr class="header"><th style="text-align: right;">HTTP</th><th>Código</th><th>Situação</th></tr></thead><tbody><tr class="odd"><td style="text-align: right;">`400`</td><td>`PAYLOAD_INVALIDO`</td><td>Campo ausente, data inválida, lista inválida ou tipo de pedido incorreto.</td></tr><tr class="even"><td style="text-align: right;">`401`</td><td>`TOKEN_INVALIDO`</td><td>Token inexistente ou inválido.</td></tr><tr class="odd"><td style="text-align: right;">`403`</td><td>`ACESSO_NEGADO`</td><td>Usuário ou estrutura inativos.</td></tr><tr class="even"><td style="text-align: right;">`413`</td><td>`PAYLOAD_GRANDE`</td><td>Payload acima de 16 KiB.</td></tr><tr class="odd"><td style="text-align: right;">`422`</td><td>`LIMITE_REGISTROS`</td><td>Resultado acima de 1.000.000 de movimentações.</td></tr><tr class="even"><td style="text-align: right;">`429`</td><td>`LIMITE_API`</td><td>Guard ocupado, cooldown ou excesso de tentativas.</td></tr></tbody></table>

Exemplo:

```
{
  "codigo": "LIMITE_API",
  "mensagem": "Aguarde entre exportações da API.",
  "requestId": "d8e4c3c2-0000-0000-0000-000000000000"
}
```

## Boas práticas

- Use intervalos consecutivos sem sobreposição quando a consulta for controlada pelo período.
- Use JSON quando a integração precisar preservar tipos e datas.
- Use CSV para planilhas e ferramentas de análise.
- Respeite o header `Retry-After` em respostas `429`.
- Não registre o token completo em logs.
- Não use o campo `id` da resposta como identificador permanente.

# Api Consulta Pedido

A API de Consulta de Pedido permite buscar os dados completos de um pedido pertencente à estrutura autorizada pelo token.

Use esta API para consultar:

- dados comerciais e financeiros do pedido;
- cliente associado, sem credenciais sensíveis;
- etapa atual, origem e consultor;
- itens do pedido e dados públicos do produto.

## Endereço

```
GET https://api.xeotech.com.br/api/v1/pedidos/{pedidoId}/{token}
```

O `pedidoId` é o identificador interno do pedido. O token é informado na URL e não deve ser enviado em cabeçalho ou payload.

Para localizar seu token no Xeotech, acesse a página [Meu token](https://ajuda.xeotech.com.br/books/apis-de-integracao/page/meu-token-para-proprietarios).

## Autorização e segurança

O token precisa pertencer a um usuário ativo. O usuário também precisa possuir um vínculo ativo com uma estrutura ativa.

A API obtém a estrutura diretamente do usuário autenticado. O cliente não envia `estruturaId`.

```
pedido.id = pedidoId
AND estrutura_usuario.estrutura_id = estruturaIdDoUsuario
```

Se o pedido não existir ou pertencer a outra estrutura, a API retorna `404`. Essa resposta evita revelar a existência de pedidos de outras estruturas.

## Payload

O GET não possui payload. Todos os dados necessários estão na URL:

<table id="bkmrk-parametros-consulta-pedido"><thead><tr class="header"><th>Parâmetro</th><th>Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr class="odd"><td>`pedidoId`</td><td>Sim</td><td>ID interno numérico do pedido.</td></tr><tr class="even"><td>`token`</td><td>Sim</td><td>Novo token de integração do usuário, informado na URL.</td></tr></tbody></table>

## Exemplo cURL

```
curl --fail-with-body --location \
  --request GET \
  'https://api.xeotech.com.br/api/v1/pedidos/123456/SEU_TOKEN' \
  --header 'Accept: application/json' \
  --output pedido-123456.json
```

## Retorno JSON

O retorno utiliza o formato `PedidoApiDTO`. A entidade JPA não é serializada diretamente.

```
{
  "id": 123456,
  "numero": "49565585",
  "pedidoTipo": "COMERCIAL",
  "tipoNegociacao": "NOVO",
  "dataCadastro": "2026-09-30",
  "dataHoraAtualizacao": "2026-09-30T14:32:10",
  "dataHoraUltimaMov": "2026-09-30T14:31:55",
  "total": 149.90,
  "compromissoMensal": 99.90,
  "nomeConsultorOperadora": "Consultor Exemplo",
  "numeroPedidoOrigem": null,
  "numeroPedidoVinculado": null,
  "numeroSimulacao": "SIM-10001",
  "complementos": null,
  "notasFiscais": null,
  "loginOperadora": null,
  "percentualTroca": null,
  "tags": "#PRIORIDADE",
  "clusterOrigem": null,
  "cotacao": null,
  "codigoPortabilidade": null,
  "observacaoProposta": null,
  "dataRetornoFuturo": null,
  "percentualDesconto": null,
  "observacao": null,
  "aparelhoCartaoCredito": false,
  "cliente": {
    "id": 9876,
    "cpfCnpj": "12345678000199",
    "nome": "Empresa Exemplo Ltda.",
    "cep": "89800000",
    "logradouro": "Rua Principal",
    "numero": "100",
    "complemento": null,
    "bairro": "Centro",
    "cidade": "Balneário Camboriú",
    "estado": "SC",
    "tags": null
  },
  "etapa": {
    "id": 44501,
    "nome": "ENVIADO BKO",
    "ativo": true,
    "sincronizavel": true,
    "editavel": false,
    "pedidoTipo": "COMERCIAL",
    "slaHoras": 0
  },
  "usuarioProprietario": {
    "id": 321,
    "nome": "Consultor Exemplo",
    "login": "consultor",
    "tags": "#PRIORIDADE,#VIP",
    "equipe": {
      "id": 12,
      "nome": "Equipe Comercial"
    },
    "ativo": true
  },
  "itens": [
    {  
      "id": 629534248,
      "numero": "47991370111",
      "quantidade": 1,
      "valorUnitario": 99.99,
      "dataReferencia": "2026-09-30",
      "dataPortabilidade": "2026-09-30",
      "dataInstalacao": "2026-09-30",
      "cepInstalacao": "88330484",
      "logradouroInstalacao": "R 1822",
      "numeroInstalacao": "400",
      "bairroInstalacao": "Centro",
      "complInstalacao": "sl 1901",
      "cidadeInstalacao": "Balneario Camboriu",
      "estadoInstalacao": "SC",
      "operadoraCedente": "TIM",
      "nomeCedente": "Sebastião Barbosa",
      "cpfCnpjCedente": "45935282917",
      "telefoneCedente": "47991917979",
      "emailCedente": "xeotechoficial@gmail.com",
      "produto": {
        "id": 18272,
        "nome": "iPHONE 18",
        "descricao": "iPHONE 18",
        "valor": 12319.00,
        "categoria": "APARELHO"
      }
    }      
  ]
}
```

## Campos do pedido

<table id="bkmrk-campos-pedido-consulta-tabela"><thead><tr class="header"><th>Grupo</th><th>Campos</th></tr></thead><tbody><tr class="odd"><td>Identificação</td><td>`id`, `numero`, `pedidoTipo`, `tipoNegociacao`, `numeroPedidoOrigem`, `numeroPedidoVinculado`, `numeroSimulacao`</td></tr><tr class="even"><td>Datas</td><td>`dataCadastro`, `dataHoraAtualizacao`, `dataHoraOperadora`, `dataHoraUltimaMov`, `dataRetornoFuturo`</td></tr><tr class="odd"><td>Valores</td><td>`total`, `compromissoMensal`, `valorFaturaOrigem`, `percentualTroca`, `percentualDesconto`</td></tr><tr class="even"><td>Operação</td><td>`nomeConsultorOperadora`, `loginOperadora`, `atividades`, `clusterOrigem`, `cotacao`, `codigoPortabilidade`, `leadSistema`</td></tr><tr class="odd"><td>Observações</td><td>`complementos`, `notasFiscais`, `observacao`, `observacaoProposta`, `tags`, `aparelhoCartaoCredito`, `revisao`</td></tr></tbody></table>

## Cliente, etapa e consultor

O objeto `cliente` retorna identificação e endereço comercial. Campos de senha, login de conta online e demais credenciais não fazem parte do retorno.

O objeto `etapa` informa somente `id`, `nome`, `ativo`, `sincronizavel`, `editavel`, `pedidoTipo` e `slaHoras`. O objeto `origem` informa a origem do pedido. O objeto `usuarioProprietario` informa o usuário proprietário, suas tags, equipe e o indicador `ativo` do vínculo com a estrutura.

## Itens e produtos

O campo `itens` retorna uma lista dos itens associados ao pedido. Os campos podem variar conforme o tipo de item, mas somente campos públicos e controlados são exportados, como:

- `id`, `numero`, `descricao`, `quantidade`;
- `valor`, `valorUnitario`, `codigo`, `nome`;
- `modelo`, `plano`, `tipo`;
- `dataReferencia`, `dataInstalacao` e dados do endereço de instalação;
- `dataPortabilidade`, `operadoraCedente`, `nomeCedente`, `cpfCnpjCedente`, `telefoneCedente` e `emailCedente`;
- objeto `produto` com `id`, `codigo`, `nome`, `descricao`, `modelo`, `tipo`, `valor`, `somaCompromissoMensal` e `categoria`.

## Limites e guard

O GET utiliza o mesmo guard da API de pedidos. Embora a consulta retorne somente um pedido, a autenticação e o controle de concorrência continuam protegidos.

<table id="bkmrk-limites-consulta-pedido"><thead><tr class="header"><th>Regra</th><th style="text-align: right;">Limite padrão</th></tr></thead><tbody><tr class="odd"><td>Execuções simultâneas globais</td><td style="text-align: right;">2</td></tr><tr class="even"><td>Execuções simultâneas por estrutura</td><td style="text-align: right;">1</td></tr><tr class="odd"><td>Intervalo mínimo após uma execução</td><td style="text-align: right;">120 segundos</td></tr><tr class="even"><td>Execuções por estrutura</td><td style="text-align: right;">3 a cada 10 minutos</td></tr><tr class="odd"><td>Tentativas por token</td><td style="text-align: right;">20 a cada 60 segundos</td></tr><tr class="even"><td>Tentativas globais</td><td style="text-align: right;">600 a cada 60 segundos</td></tr><tr class="odd"><td>Autenticações simultâneas</td><td style="text-align: right;">8</td></tr></tbody></table>

As tentativas recusadas também entram no controle. Quando um limite for atingido, a resposta será `429` com o header `Retry-After`.

## Respostas de erro

<table id="bkmrk-erros-consulta-pedido"><thead><tr class="header"><th style="text-align: right;">HTTP</th><th>Código</th><th>Situação</th></tr></thead><tbody><tr class="odd"><td style="text-align: right;">`401`</td><td>`TOKEN_INVALIDO`</td><td>Token inexistente, vazio ou inválido.</td></tr><tr class="even"><td style="text-align: right;">`403`</td><td>`ACESSO_NEGADO`</td><td>Usuário ou estrutura inativos.</td></tr><tr class="odd"><td style="text-align: right;">`404`</td><td>`PEDIDO_NAO_ENCONTRADO`</td><td>Pedido inexistente ou que não pertence à estrutura do token.</td></tr><tr class="even"><td style="text-align: right;">`429`</td><td>`LIMITE_API`</td><td>Guard ocupado, cooldown ou excesso de tentativas.</td></tr></tbody></table>

Exemplo de erro:

```
{
  "codigo": "PEDIDO_NAO_ENCONTRADO",
  "mensagem": "Pedido não encontrado para esta estrutura.",
  "requestId": "d8e4c3c2-0000-0000-0000-000000000000"
}
```

## Boas práticas

- Não registre o token completo em logs, código ou repositórios.
- Trate `404` como pedido inexistente ou não autorizado para a estrutura.
- Use o `id` do pedido como identificador da consulta local.
- Respeite o header `Retry-After` nas respostas `429`.
- Considere que campos sem valor podem retornar `null`.

# Api Movimentação de Etapa de Atividade

A API de movimentação de etapa permite mover uma ou várias atividades para outra etapa do funil, respeitando as mesmas regras de segurança, permissões, hierarquia e histórico utilizadas no Xeotech.

Essa operação não altera diretamente o pedido sem controle. Ela executa o processo de movimentação, registra o histórico e valida as regras da atividade.

## Endereço

```
POST https://api.xeotech.com.br/api/v1/pedidos/alterar-etapa/{token}
```

O token é informado na URL. Não envie o token no payload.

## Autorização e estrutura

O token precisa pertencer a um usuário ativo, com vínculo ativo em uma estrutura ativa. A estrutura é obtida automaticamente pelo vínculo do usuário; não é possível informar `estruturaId` no payload.

A etapa de destino é localizada pelo Xeotech usando:

- estrutura do usuário do token;
- tipo do pedido informado;
- nome exato da etapa;
- origem padrão do pedido, atualmente `5`;
- etapa ativa.

## Payload

```
{
  "numerosAtividades": ["49565585", "49565586"],
  "pedidoTipo": "COMERCIAL",
  "nomeEtapa": "ATIVO"
}
```

<table id="bkmrk-campos-payload-alterar-etapa"><thead><tr class="header"><th>Campo</th><th style="text-align: right;">Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr class="odd"><td>`numerosAtividades`</td><td style="text-align: right;">Sim</td><td>Lista com 1 a 50 números de atividades. Envie os números como texto, mesmo quando forem numéricos. Não pode haver repetição.</td></tr><tr class="even"><td>`pedidoTipo`</td><td style="text-align: right;">Sim</td><td>Aceita `COMERCIAL` ou `POS_VENDA`.</td></tr><tr class="odd"><td>`nomeEtapa`</td><td style="text-align: right;">Sim</td><td>Nome exato da etapa ativa cadastrada para o tipo de pedido e estrutura do token.</td></tr></tbody></table>

O payload aceita somente esses três campos. Campos desconhecidos, números vazios, duplicados ou acima de 50 atividades são rejeitados.

## Header obrigatório

```
Idempotency-Key: alteracao-etapa-20261001-0001
```

A chave deve conter de 16 a 64 caracteres usando letras, números, hífen ou sublinhado.

Use a mesma chave somente para repetir exatamente a mesma operação. A chave é controlada por usuário, atividade e payload. Não reutilize uma chave para outra etapa ou outro pedido.

## Regras de processamento

- Cada atividade é processada em uma transação independente.
- Uma falha em uma atividade não impede o processamento das demais.
- A atividade precisa pertencer à estrutura do token e ser acessível pela hierarquia do usuário.
- Se a etapa atual não estiver no Kanban do solicitante, é necessária a permissão `MOVER_SEM_ESTAR_NO_KANBAN`.
- Se a etapa de destino não estiver no Kanban do solicitante, é necessária a permissão `MOVER_ATIVIDADE_FORA_KANBAN`.
- Para sair de uma etapa não editável, é sempre necessária a permissão `ATIVIDADE_MOVER_NAO_EDITAVEIS`, mesmo que a etapa esteja no Kanban.
- Para entrar em uma etapa não editável fora do Kanban, também é necessária a permissão `MOVER_ATIVIDADE_PARA_NAO_EDITAVEIS`. Quando o destino está no Kanban, essa permissão específica é dispensada.
- Se a atividade já estiver na etapa informada, o resultado será `SEM_ALTERACAO`.
- A movimentação registra o status e o histórico da atividade.
- Se a etapa de destino atualizar a data de referência, os itens do pedido terão a data atualizada conforme a regra do sistema.
- Se houver formulário ativo vinculado à etapa atual, a API recusa a operação. Nesse caso, a movimentação deve ser feita pela tela do Xeotech.
- Negociações vinculadas podem ser movimentadas quando atendem às regras de sincronização, hierarquia, permissões e formulário. As mesmas validações de Kanban são aplicadas usando o tipo da negociação vinculada; se ela for recusada, a alteração do pedido principal também é revertida.

## Permissões

<table id="bkmrk-permissoes-alterar-etapa-tabela"><thead><tr class="header"><th>Permissão</th><th>Quando é necessária</th></tr></thead><tbody><tr class="odd"><td>`PAINEL_ATIVIDADE_ETAPA_CHANGE`</td><td>Obrigatória em todas as chamadas, inclusive para uma única atividade. A permissão `KANBAN_ETAPA_CHANGE` sozinha não autoriza esta API.</td></tr><tr class="even"><td>`ATIVIDADE_ALTERACAO_EM_LOTE`</td><td>Obrigatória quando o payload contém mais de uma atividade.</td></tr><tr class="odd"><td>`ATIVIDADE_MOVER_NAO_EDITAVEIS`</td><td>Necessária para sair de uma etapa não editável.</td></tr><tr class="even"><td>`MOVER_ATIVIDADE_PARA_NAO_EDITAVEIS`</td><td>Necessária para entrar em uma etapa não editável que não esteja no Kanban do solicitante.</td></tr><tr class="even"><td>`MOVER_SEM_ESTAR_NO_KANBAN`</td><td>Necessária quando a etapa atual da atividade não está no Kanban do solicitante.</td></tr><tr class="odd"><td>`MOVER_ATIVIDADE_FORA_KANBAN`</td><td>Necessária quando a etapa de destino não está no Kanban do solicitante.</td></tr><tr class="odd"><td>`IGNORAR_HIERARQUIA`</td><td>Permite ignorar a validação de hierarquia, conforme as regras do usuário.</td></tr></tbody></table>

As permissões de Kanban e de etapas não editáveis são cumulativas. Por exemplo, mover uma atividade de uma etapa não editável fora do Kanban para outro destino não editável fora do Kanban exige as quatro permissões específicas, além das permissões gerais da operação.

## Exemplo cURL

```
curl --fail-with-body --location \
  --request POST \
  'https://api.xeotech.com.br/api/v1/pedidos/alterar-etapa/SEU_TOKEN' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: alteracao-etapa-20261001-0001' \
  --data '{
    "numerosAtividades": ["49565585", "49565586"],
    "pedidoTipo": "COMERCIAL",
    "nomeEtapa": "ATIVO"
  }'
```

## Retorno

A resposta informa o resultado individual de cada atividade. O HTTP `200` indica que o lote foi processado; verifique os campos `sucessos`, `falhas` e `resultados`.

```
{
  "requestId": "d8e4c3c2-0000-0000-0000-000000000000",
  "total": 2,
  "sucessos": 1,
  "falhas": 1,
  "resultados": [
    {
      "numeroAtividade": "49565585",
      "pedidoId": 49565585,
      "sucesso": true,
      "codigo": "ETAPA_ALTERADA",
      "mensagem": "Etapa alterada com sucesso."
    },
    {
      "numeroAtividade": "49565586",
      "pedidoId": null,
      "sucesso": false,
      "codigo": "FORMULARIO_VINCULADO",
      "mensagem": "Esta atividade possui formulário vinculado à etapa atual. Realize a movimentação pela tela do sistema."
    }
  ]
}
```

<table id="bkmrk-campos-retorno-alterar-etapa"><thead><tr class="header"><th>Campo</th><th>Descrição</th></tr></thead><tbody><tr class="odd"><td>`requestId`</td><td>Identificador da requisição para rastreamento no suporte.</td></tr><tr class="even"><td>`total`</td><td>Total de atividades recebidas.</td></tr><tr class="odd"><td>`sucessos`</td><td>Quantidade de atividades alteradas ou processadas sem erro.</td></tr><tr class="even"><td>`falhas`</td><td>Quantidade de atividades recusadas ou com erro.</td></tr><tr class="odd"><td>`numeroAtividade`</td><td>Número enviado no payload.</td></tr><tr class="even"><td>`pedidoId`</td><td>ID interno do pedido, quando localizado.</td></tr><tr class="odd"><td>`sucesso`</td><td>Indica se a atividade foi processada com sucesso.</td></tr><tr class="even"><td>`codigo`</td><td>Código estável do resultado, como `ETAPA_ALTERADA`, `SEM_ALTERACAO` ou `FORMULARIO_VINCULADO`.</td></tr><tr class="odd"><td>`mensagem`</td><td>Descrição do resultado.</td></tr></tbody></table>

## Limites e guard

A alteração de etapa reutiliza o `pedidoApiGuard` da API de pedidos. Os limites são aplicados antes da autenticação e durante o processamento.

<table id="bkmrk-limites-alterar-etapa"><thead><tr class="header"><th>Regra</th><th style="text-align: right;">Limite padrão</th></tr></thead><tbody><tr class="odd"><td>Execuções simultâneas globais</td><td style="text-align: right;">2</td></tr><tr class="even"><td>Execuções simultâneas por estrutura</td><td style="text-align: right;">1</td></tr><tr class="odd"><td>Intervalo mínimo após execução</td><td style="text-align: right;">120 segundos</td></tr><tr class="even"><td>Execuções por estrutura</td><td style="text-align: right;">3 a cada 10 minutos</td></tr><tr class="odd"><td>Tentativas por token</td><td style="text-align: right;">20 a cada 60 segundos</td></tr><tr class="even"><td>Tentativas globais</td><td style="text-align: right;">600 a cada 60 segundos</td></tr><tr class="odd"><td>Autenticações simultâneas</td><td style="text-align: right;">8</td></tr><tr class="even"><td>Tamanho máximo do payload</td><td style="text-align: right;">16 KiB</td></tr><tr class="odd"><td>Atividades por requisição</td><td style="text-align: right;">50</td></tr></tbody></table>

Quando um limite for atingido, a API retorna `429` e informa o tempo de espera no header `Retry-After`. O guard em memória é controlado por instância da aplicação; a idempotência é garantida pelo banco de dados.

## Principais erros

<table id="bkmrk-erros-alterar-etapa-tabela"><thead><tr class="header"><th style="text-align: right;">HTTP</th><th>Código</th><th>Situação</th></tr></thead><tbody><tr class="odd"><td style="text-align: right;">`400`</td><td>`PAYLOAD_INVALIDO` ou `CHAVE_INVALIDA`</td><td>Payload inválido ou ausência de uma chave de idempotência válida.</td></tr><tr class="even"><td style="text-align: right;">`401`</td><td>`TOKEN_INVALIDO`</td><td>Token inexistente ou inválido.</td></tr><tr class="odd"><td style="text-align: right;">`403`</td><td>`ACESSO_NEGADO` ou `SEM_PERMISSAO`</td><td>Usuário, vínculo, estrutura ou permissão indisponível.</td></tr><tr class="even"><td style="text-align: right;">`404`</td><td>`PEDIDO_NAO_ENCONTRADO`</td><td>Atividade não encontrada na estrutura e no tipo informados.</td></tr><tr class="odd"><td style="text-align: right;">`409`</td><td>`IDEMPOTENCIA_CONFLITO` ou `NUMERO_AMBIGUO`</td><td>Chave reutilizada com outro payload ou número não exclusivo.</td></tr><tr class="even"><td style="text-align: right;">`413`</td><td>`PAYLOAD_GRANDE`</td><td>Payload acima de 16 KiB.</td></tr><tr class="odd"><td style="text-align: right;">`422`</td><td>`ETAPA_INVALIDA` ou `FORMULARIO_VINCULADO`</td><td>Etapa inexistente, ambígua, inativa ou bloqueada por formulário.</td></tr><tr class="even"><td style="text-align: right;">`429`</td><td>`LIMITE_API`</td><td>Guard ocupado, cooldown ou excesso de tentativas.</td></tr></tbody></table>

Falhas específicas de uma atividade são retornadas dentro de `resultados`, com HTTP `200` para o lote. Isso inclui `ETAPA_ATUAL_FORA_KANBAN`, `ETAPA_DESTINO_FORA_KANBAN`, `SEM_PERMISSAO`, `FORMULARIO_VINCULADO` e demais recusas da atividade. Os números HTTP da tabela representam as categorias de erro; não substituem a análise de cada resultado.

## Boas práticas

- Envie números de atividade como texto para preservar compatibilidade com números antigos.
- Use uma chave de idempotência única para cada operação nova.
- Em caso de timeout, repita a requisição com a mesma chave e o mesmo payload.
- Analise o resultado de cada atividade, mesmo quando o HTTP for `200`.
- Respeite o header `Retry-After` nas respostas `429`.
- Não registre o token completo nos logs.