Mudar o status da cotação
https://api.precificador3d.com.br/v1/cotacoes/{id}/status Escopo: cotacoes:status (quem criou a chave precisa de cotacoes.enviar, como na tela). Não envia nada ao cliente e não mexe no link.
Transições permitidas pela API: rascunho → em_analise, aprovada, recusada ou arquivado; em_analise e enviada → aprovada, recusada ou arquivado; aprovada e recusada → arquivado. Para enviada, para rascunho e entre aprovada e recusada, só pela tela. Fora disso: 422 transicao_invalida.
de é obrigatório: se o status atual for outro, a resposta é 409 status_mudou e nada muda.
Sair de rascunho ou em_analise congela a cotação (os valores não mudam mais e os itens deixam de ser editáveis), igual à tela. Aprovar não cria pedido de produção. Gera o webhook cotacao.status_mudou (e cotacao.aprovada ou cotacao.recusada) com origem.chave_id desta chave, para o integrador ignorar o eco. Escrita com custo 2.
cURL
curl -X POST "https://api.precificador3d.com.br/v1/cotacoes/9e0f1a2b-3c4d-4e5f-6a7b-8c9d0e1f2a3b/status" \
-H "Authorization: Bearer $PC3D_CHAVE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
--data '{
"de": "enviada",
"para": "aprovada",
"motivo": "Cliente aprovou por e-mail"
}' JavaScript
const resposta = await fetch('https://api.precificador3d.com.br/v1/cotacoes/9e0f1a2b-3c4d-4e5f-6a7b-8c9d0e1f2a3b/status', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PC3D_CHAVE}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"de": "enviada",
"para": "aprovada",
"motivo": "Cliente aprovou por e-mail"
}),
});
if (!resposta.ok) {
const erro = await resposta.json(); // application/problem+json
throw new Error(`${erro.codigo}: ${erro.detail} (${erro.requisicao_id})`);
}
const dados = await resposta.json(); Python
import os
import uuid
import requests
resposta = requests.post(
"https://api.precificador3d.com.br/v1/cotacoes/9e0f1a2b-3c4d-4e5f-6a7b-8c9d0e1f2a3b/status",
headers={
"Authorization": f"Bearer {os.environ['PC3D_CHAVE']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"de": "enviada",
"para": "aprovada",
"motivo": "Cliente aprovou por e-mail",
},
timeout=10,
)
resposta.raise_for_status()
dados = resposta.json() Parâmetros de caminho
idstring (uuid)obrigatório
Cabeçalhos
Idempotency-Keystringobrigatório- Chave única da operação, guardada por 24 h junto com o hash do corpo, o status e o id
criado (sem corpo nem resposta). Repetir com o mesmo corpo devolve o mesmo status e o
recurso relido pelo id. A mesma chave com outro corpo responde
422 idempotencia_conflito. (até 64 caracteres)
Corpo da requisição application/json
destringobrigatório- Valores:
rascunho,enviada,aprovada,recusada,em_analise,arquivado. parastringobrigatório- Valores:
em_analise,aprovada,recusada,arquivado. motivostring- (até 200 caracteres)
Resposta 200
Status mudado. Devolve a cotação com o status novo.
Campos da resposta (36)
idstring (uuid)codigostringtitulostringstatusstring- Valores:
rascunho,enviada,aprovada,recusada,em_analise,arquivado. versaointegerclienteobjectcliente.nomestring | nullcliente.contatostring | nullvalidadestring (date) | nullcondicoesstring | nullobservacaostring | nullitensarray de objectitens[].idstring (uuid)itens[].nomestringitens[].skustring | nullitens[].produto_idstring (uuid) | nullitens[].variacao_idstring (uuid) | nullitens[].quantidadeintegeritens[].preco_unitario_centavosinteger- (de 0 a 100000000000)
itens[].total_centavosinteger- (de 0 a 100000000000)
itens[].corCorCliente | nullitens[].cor.idstring (uuid)itens[].cor.codigostringitens[].cor.nome_clientestringitens[].cor.acabamentostring- Valores:
nenhum,brilhante,fosco. itens[].cor_a_combinarbooleantotal_centavosinteger- (de 0 a 100000000000)
desconto_centavosinteger- (de 0 a 100000000000)
criado_emstring (date-time)atualizado_emstring (date-time)enviada_emstring (date-time) | nullaprovada_emstring (date-time) | nullcongeladaboolean- true fora de rascunho e em_analise. Congelada, a cotação só se edita voltando para rascunho pela tela.
custo_total_centavosinteger- [custos] (de 0 a 100000000000)
lucro_centavosinteger- [custos]
margem_bpinteger- [custos] Pontos-base.
{
"id": "9e0f1a2b-3c4d-4e5f-6a7b-8c9d0e1f2a3b",
"codigo": "COT-0042",
"titulo": "Chaveiros evento Loja Exemplo",
"status": "aprovada",
"versao": 2,
"cliente": {
"nome": "Ana Lima",
"contato": "ana.lima@example.com"
},
"validade": "2026-10-31",
"condicoes": "Pagamento 50% na aprovação e 50% na entrega.",
"observacao": null,
"itens": [
{
"id": "d3e4f5a6-b7c8-4d9e-0f1a-2b3c4d5e6f7a",
"nome": "Chaveiro Dragão · Azul",
"sku": "CHAV-DRG-AZ",
"produto_id": "5a6b7c8d-9e0f-4a1b-2c3d-4e5f6a7b8c9d",
"variacao_id": "6b7c8d9e-0f1a-4b2c-3d4e-5f6a7b8c9d0e",
"quantidade": 200,
"preco_unitario_centavos": 1290,
"total_centavos": 258000,
"cor": {
"id": "c2d3e4f5-a6b7-4c8d-9e0f-1a2b3c4d5e6f",
"codigo": "#007",
"nome_cliente": "Azul",
"acabamento": "fosco"
},
"cor_a_combinar": false
}
],
"total_centavos": 258000,
"desconto_centavos": 12900,
"criado_em": "2026-10-03T14:00:00-03:00",
"atualizado_em": "2026-10-05T09:30:00-03:00",
"enviada_em": "2026-10-03T16:10:00-03:00",
"aprovada_em": "2026-10-05T09:30:00-03:00"
} Outras respostas
- 400
dados_invalidos: Dados, filtro, cursor ou cabeçalho inválido. - 401
nao_autenticado: Chave ausente, malformada, desconhecida, revogada ou expirada (a resposta é a mesma para todos os casos). - 403
escopo_insuficiente: Escopo insuficiente, conta bloqueada, módulo desligado ou chave suspensa. - 404
nao_encontrado: Não existe nesta conta. - 408
tempo_esgotado: O corpo do POST não chegou inteiro em 5 s. - 409
status_mudou: O status atual da cotação não é o informado em `de`. Nada mudou. Releia a cotação e decida de novo. - 413
corpo_grande_demais: Corpo acima de 64 KB. - 415
tipo_nao_suportado: Só `application/json`. - 422
saldo_insuficiente: Regra de negócio recusou (referência de outra conta ou inexistente, saldo insuficiente, quantidade fora do mínimo ou múltiplo) ou a Idempotency-Key já foi usada com outro corpo (`idempotencia_conflito`). - 429
limite_excedido: Limite de uso excedido (rajada, minuto, mês ou requisições simultâneas). - 500
erro_interno: Erro interno. O detalhe fica no log, ligado ao requisicao_id. - 503
indisponivel: API desligada, sob pressão (disjuntor aberto) ou no limite global da plataforma.