Criar, alterar e excluir promoção
Cadastra uma promoção do seller com cupom, ajusta seus campos e a exclui de forma lógica.
Crie uma promoção quando o seller quer dar desconto aos clientes que digitarem um código: 10% acima de R$ 200, frete grátis, compre 3 leve 4. A promoção nasce ativa e começa a valer na hora, se valid_from for omitido. O dono (vendor_id) é sempre o seller do token. O desconto incide só sobre os itens dele e só funciona por código: sem code a promoção fica cadastrada e nunca é aplicada.
A plataforma recusa de antemão promoções que nasceriam "mortas" (tipo desconhecido, desconto negativo, condição inexistente na zona escolhida). Leia a mensagem do 400: ela diz o que corrigir.
Criar uma promoção
/api/v1/vendor/promotionsSellerCria uma promoção do seller
Corpo da requisição
namestringobrigatóriotypestringobrigatóriopercentagefixedfree_shippingbuy_x_get_yto_percentageto_fixedorder_discountproduct_discountcategory_discountfree_productsgive_usergroupgive_couponfree_productassign_usergroupdiscountintegerpercentage (1000 = 10%, máximo 10000) e centavos em fixed. Nunca negativo. Pode ser 0 em free_shipping e buy_x_get_y.codestringdescriptionstringmax_discountintegerpriorityintegerpadrão: 0stop_other_rulesbooleanpadrão: falsestackablebooleanpadrão: falseconditionsobjectmin_cart_total (centavos, medido sobre os itens do seller), product_ids, category_ids, exclude_product_ids, user_group_ids, vendor_ids (listas de UUID) e buy_x_get_y (buy_product_ids, buy_quantity, get_product_ids, get_quantity, discount_percent).condition_groupsobject{"set":"all","set_value":true,"conditions":[{"type":"subtotal","operator":"gte","value":20000}]}.bonusesarray[{"bonus_type":"order_discount","config":{"discount_type":"by_percentage","discount_value":1000}}].bonus_typestringbonus_configobjectfree_shipping_method_iduuidfree_shipping).usage_limitintegerpadrão: 00 = sem limite.per_user_limitintegervalid_fromstring (RFC 3339)valid_untilstring (RFC 3339)statusstringactiveinactivedisabledexpireddraftADEdraft vira inativa. Vazio vira ativa.zonestringcartcatalogcart ou catalog. Sem valor, promoção com código vira cart.descriptionsobjectpt-BR, en) para um objeto com nome e descrição traduzidos.Exemplo de requisição: criar
curl -X POST "$BASE_URL/api/v1/vendor/promotions" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Inverno 10% nas camisas",
"type": "percentage",
"discount": 1000,
"code": "INVERNO10",
"zone": "cart",
"conditions": { "min_cart_total": 20000 },
"usage_limit": 500,
"per_user_limit": 1,
"valid_until": "2026-11-30T23:59:59-03:00"
}'Resposta: criar
{
"id": "7c1f0a52-3b8e-4d11-9a47-5e2b6d8c1f30",
"vendor_id": "94bd7e9a-fdad-4d01-8fc2-ba9d677d8b36",
"name": "Inverno 10% nas camisas",
"description": "",
"type": "percentage",
"code": "INVERNO10",
"discount": 1000,
"conditions": { "min_cart_total": 20000 },
"usage_limit": 500,
"usage_count": 0,
"valid_from": "2026-10-11T14:02:10Z",
"valid_until": "2026-11-30T02:59:59Z",
"status": "A",
"priority": 0,
"stop_other_rules": false,
"stackable": false,
"zone": "cart",
"bonuses": [],
"per_user_limit": 1,
"created_at": "2026-10-11T14:02:10.482113Z",
"updated_at": "2026-10-11T14:02:10.482113Z"
}{
"id": "7c1f0a52-3b8e-4d11-9a47-5e2b6d8c1f30",
"name": "Inverno 10% nas camisas",
"...": "demais campos como acima",
"ignored_fields": ["end_at", "title"],
"warning": "a promoção foi criada, mas estes campos do corpo não entraram nela: end_at, title. Campos aceitos: vendor_id, name, ..."
}Campos da resposta
iduuidvendor_iduuid(demais campos)mixedignored_fieldsarray of string | omittedwarningstring | omittedAlterar uma promoção
/api/v1/vendor/promotions/{id}SellerAltera campos de uma promoção do seller
O PUT é parcial: envie só o que muda. Para pausar, envie {"status":"inactive"}; para reativar, {"status":"active"}. O corpo aceita os mesmos campos da criação, todos opcionais, e ignora vendor_id.
Parâmetros de caminho
iduuidobrigatórioCorpo da requisição
namestringtypestringdiscountintegercodestringnull não remove o código nesta rota.statusstringactiveinactivedisabledexpireddraftADEvalid_fromstring (RFC 3339)valid_untilstring (RFC 3339)(demais campos)mixeddescription, max_discount, priority, stop_other_rules, stackable, conditions, condition_groups, bonuses, bonus_type, bonus_config, free_shipping_method_id, usage_limit, per_user_limit, zone, descriptions, como na criação.Exemplo de requisição: alterar
curl -X PUT "$BASE_URL/api/v1/vendor/promotions/7c1f0a52-3b8e-4d11-9a47-5e2b6d8c1f30" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "discount": 1500, "valid_until": "2026-12-01T23:59:59-03:00" }'Resposta: alterar
{
"id": "7c1f0a52-3b8e-4d11-9a47-5e2b6d8c1f30",
"vendor_id": "94bd7e9a-fdad-4d01-8fc2-ba9d677d8b36",
"name": "Inverno 10% nas camisas",
"type": "percentage",
"code": "INVERNO10",
"discount": 1500,
"valid_until": "2026-12-02T02:59:59Z",
"status": "A",
"updated_at": "2026-10-11T15:10:00.120000Z"
}A resposta é a promoção inteira, como na criação (trimada aqui).
Excluir uma promoção
/api/v1/vendor/promotions/{id}SellerExclui (logicamente) uma promoção do seller
A exclusão é lógica: a promoção vai para o status D, sai da lista e deixa de descontar. Os pedidos antigos que a usaram continuam intactos.
Parâmetros de caminho
iduuidobrigatórioResposta: excluir
{ "message": "promotion deleted" }Excluir de novo uma promoção que já foi excluída também responde 200: a rota só falha com 404 quando o id não é de uma promoção sua.
Erros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 401 | Token ausente ou inválido. | {"error":"missing authorization header"} |
| 403 | O token não é de um usuário seller, ou o seller não tem privilégio de configurações. | {"error":"insufficient vendor privileges","privilege_required_any":["vendor_settings", "..."]} |
| 400 | name ou type ausente na criação. | {"error":"name is required","detail":"..."} |
| 400 | Corpo que não é JSON, ou valor com formato errado (data sem hora, por exemplo). A mensagem diz o campo e o formato. | {"error":"invalid request body","detail":"..."} |
| 400 | Regra de validação: tipo, desconto, status, condição ou zona inválidos. A mensagem, em português, traz as opções aceitas. | {"error":"invalid promotion type: percent; tipos aceitos: percentage, fixed, ...","detail":""} |
| 404 | Alterar ou excluir uma promoção que não existe ou é de outro seller. | {"error":"promotion not found"} |
| 422 | A oferta fica abaixo do piso de margem da loja. O corpo é o detalhamento da conta. | {"ok":false,"floor_bps":1500,"reason":"below_floor","worst":{},"violations":[]} |
| 500 | Falha inesperada ao gravar. Um código de cupom repetido também chega como 500, não como 409. | {"error":"failed to create promotion","detail":"..."} |