Cotações
Lista, detalha, responde e recusa as cotações B2B recebidas pelo seller.
Uma cotação (RFQ, request for quotation) é um pedido de preço que um comprador B2B faz a um seller antes de comprar. Estas rotas são o lado do seller: ver o que chegou, responder com preços e recusar. A negociação em várias rodadas está em Negociação.
Listar cotações
Devolve as cotações (pedidos de preço de compradores B2B) dirigidas ao seller do token, da mais nova para a mais antiga. Cada item vem resumido, com item_count no lugar das linhas. Antes de listar, a plataforma marca como expired as cotações respondidas cujo valid_until já passou.
/api/v1/vendor/quotesSellerListar as cotações do seller
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso de um usuário seller (veja Tokens).Parâmetros de consulta
statusstringpendingquotednegotiatingacceptedrejectedexpiredconvertedquoted) ou a letra do banco (Q). Vazio não filtra. Não existe valor all: ele não casa com nada e a lista vem vazia.pageintegerpadrão: 1per_pageintegerpadrão: 20Exemplo de requisição
curl "$BASE_URL/api/v1/vendor/quotes?status=pending&page=1&per_page=20" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"quotes": [
{
"id": 68,
"user_id": "220b672c-90fe-4841-ae86-bd4f1ace982e",
"vendor_id": "94bd7e9a-fdad-4d01-8fc2-ba9d677d8b36",
"status": "pending",
"notes": "",
"total_cents": 0,
"created_at": "2026-10-10T20:16:16Z",
"updated_at": "2026-10-10T20:16:16Z",
"user_email": "maria.souza@example.com",
"user_name": "Maria Souza",
"vendor_name": "Loja Exemplo",
"item_count": 1
}
],
"total": 1,
"page": 1,
"per_page": 20,
"total_pages": 1
}Campos da resposta
quotesobject[]items e com item_count.totalintegerpageintegerper_pageintegertotal_pagesintegerErros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 401 | Token ausente, inválido, expirado ou revogado. | {"error":"missing authorization header"} |
| 403 | O token não é de um usuário seller (por exemplo, é de administrador), ou o usuário não está vinculado a nenhum seller. | {"error":"insufficient permissions"} |
| 403 | O módulo b2b-pricing está desligado nesta loja. | {"error":"module_disabled","module":"b2b-pricing"} |
| 403 | Usuário sem perfil de seller. | {"error":"vendor profile not found"} |
Ver uma cotação
Devolve uma cotação com todas as linhas. Use o id de cada linha como item_id ao responder.
/api/v1/vendor/quotes/{id}SellerDetalhe de uma cotação com as linhas
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso de um usuário seller (veja Tokens).Parâmetros de caminho
idintegerobrigatório400 invalid quote id.Exemplo de requisição
curl "$BASE_URL/api/v1/vendor/quotes/69" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"id": 69,
"user_id": "220b672c-90fe-4841-ae86-bd4f1ace982e",
"vendor_id": "94bd7e9a-fdad-4d01-8fc2-ba9d677d8b36",
"status": "quoted",
"notes": "Preciso de 5 unidades para uma reposição de estoque.",
"vendor_notes": "Preço válido para pagamento à vista.",
"total_cents": 20000,
"valid_until": "2026-10-18T14:00:00Z",
"created_at": "2026-10-11T13:00:00Z",
"updated_at": "2026-10-11T14:00:00Z",
"user_email": "maria.souza@example.com",
"user_name": "Maria Souza",
"vendor_name": "Loja Exemplo",
"items": [
{
"id": 98,
"quote_id": 69,
"product_id": "c7bc3778-2c79-4561-b9d7-979768f364c8",
"quantity": 5,
"offered_price_cents": 4000,
"notes": "",
"product_name": "Notebook Plus Rosa",
"product_sku": "SD-000507",
"product_price": 6990
}
]
}Campos da resposta
idintegeruser_iduuidvendor_iduuidstatusstringpendingquotednegotiatingacceptedrejectedexpiredconvertednotesstringvendor_notesstringrespond. Omitido enquanto vazio.total_centsintegeroffered_price_cents vezes a quantidade). 0 até o seller responder.valid_untilstring|nullexpired.created_atstringupdated_atstringuser_emailstringuser_namestringvendor_namestringitem_countintegeritemsobject[]Linhas da cotação. Vem só no detalhe e depois do respond.
idintegeritem_id que você usa em respond.quote_idintegerproduct_iduuidquantityintegerrequested_price_centsinteger|nulloffered_price_centsinteger|nullnull antes da resposta.notesstringproduct_namestringproduct_skustringproduct_priceintegerErros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 400 | id não é um inteiro. | {"error":"invalid quote id"} |
| 404 | Não existe cotação com esse id. | {"error":"quote not found"} |
| 403 | A cotação existe, mas é de outro seller. | {"error":"quote does not belong to this vendor"} |
| 401 | Token ausente, inválido, expirado ou revogado. | {"error":"missing authorization header"} |
| 403 | O token não é de um usuário seller (por exemplo, é de administrador), ou o usuário não está vinculado a nenhum seller. | {"error":"insufficient permissions"} |
| 403 | O módulo b2b-pricing está desligado nesta loja. | {"error":"module_disabled","module":"b2b-pricing"} |
Responder uma cotação
Responde a uma cotação pending com o preço unitário de cada linha. A plataforma calcula o total, grava a validade (7 dias a partir de agora se você não enviar valid_until) e muda o status para quoted. O comprador passa a poder aceitar a oferta.
/api/v1/vendor/quotes/{id}/respondSellerInformar o preço de cada item
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso de um usuário seller (veja Tokens).Content-Typestringobrigatórioapplication/json.Parâmetros de caminho
idintegerobrigatório400 invalid quote id.Corpo da requisição
itemsobject[]obrigatórioUm objeto por linha da cotação, sem repetir linhas. Precisa cobrir todas as linhas.
item_idintegerobrigatórioitems[].id do detalhe).offered_price_centsintegerobrigatóriovalid_untilstringnotesstringvendor_notes. Vazio mantém o texto anterior.Exemplo de requisição
curl -X POST "$BASE_URL/api/v1/vendor/quotes/69/respond" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"item_id": 98,
"offered_price_cents": 4000
}
],
"valid_until": "2026-10-18T14:00:00Z",
"notes": "Preço válido para pagamento à vista."
}'Resposta
{
"id": 69,
"user_id": "220b672c-90fe-4841-ae86-bd4f1ace982e",
"vendor_id": "94bd7e9a-fdad-4d01-8fc2-ba9d677d8b36",
"status": "quoted",
"notes": "Preciso de 5 unidades para uma reposição de estoque.",
"vendor_notes": "Preço válido para pagamento à vista.",
"total_cents": 20000,
"valid_until": "2026-10-18T14:00:00Z",
"created_at": "2026-10-11T13:00:00Z",
"updated_at": "2026-10-11T14:00:00Z",
"user_email": "maria.souza@example.com",
"user_name": "Maria Souza",
"vendor_name": "Loja Exemplo",
"items": [
{
"id": 98,
"quote_id": 69,
"product_id": "c7bc3778-2c79-4561-b9d7-979768f364c8",
"quantity": 5,
"offered_price_cents": 4000,
"notes": "",
"product_name": "Notebook Plus Rosa",
"product_sku": "SD-000507",
"product_price": 6990
}
]
}Campos da resposta
(corpo)objectstatus: quoted.Erros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 400 | JSON inválido, id não inteiro ou items vazio. | {"error":"at least one item response is required"} |
| 404 | A cotação não existe. | {"error":"quote not found"} |
| 403 | A cotação é de outro seller. | {"error":"quote does not belong to this vendor"} |
| 500 | Regra de negócio violada. Hoje a plataforma responde 500 em vez de 4xx; o motivo vem em detail. Casos: cotação que não está pending, linha sem preço, preço negativo, item_id que não é da cotação. | {"error":"failed to respond to quote","detail":"all quote items must be offered a price (quote has 2 items, response covers 1)"} |
| 401 | Token ausente, inválido, expirado ou revogado. | {"error":"missing authorization header"} |
| 403 | O token não é de um usuário seller (por exemplo, é de administrador), ou o usuário não está vinculado a nenhum seller. | {"error":"insufficient permissions"} |
| 403 | O módulo b2b-pricing está desligado nesta loja. | {"error":"module_disabled","module":"b2b-pricing"} |
Recusar uma cotação
Encerra a cotação como rejected. Só funciona enquanto ela está pending ou quoted. Não há corpo e não há campo para o motivo. Para negociar em vez de recusar, use a contraproposta.
/api/v1/vendor/quotes/{id}/rejectSellerRecusar o pedido de preço
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso de um usuário seller (veja Tokens).Parâmetros de caminho
idintegerobrigatório400 invalid quote id.Exemplo de requisição
curl -X POST "$BASE_URL/api/v1/vendor/quotes/69/reject" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"message": "quote rejected"
}Erros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 400 | id não é um inteiro. | {"error":"invalid quote id"} |
| 404 | A cotação não existe. | {"error":"quote not found"} |
| 403 | A cotação é de outro seller. | {"error":"quote does not belong to this vendor"} |
| 500 | A cotação não está pending nem quoted (por exemplo já foi aceita). O motivo vem em detail. | {"error":"failed to reject quote","detail":"quote not found or not in rejectable status"} |
| 401 | Token ausente, inválido, expirado ou revogado. | {"error":"missing authorization header"} |
| 403 | O token não é de um usuário seller (por exemplo, é de administrador), ou o usuário não está vinculado a nenhum seller. | {"error":"insufficient permissions"} |
| 403 | O módulo b2b-pricing está desligado nesta loja. | {"error":"module_disabled","module":"b2b-pricing"} |
Trilha da proposta
Lista, em modo leitura, os eventos que o comprador gerou ao abrir e decidir a proposta pelo link público (aprovar, recusar ou comentar), com nome, papel, IP e navegador. Serve como prova de quem aceitou o quê. Vem vazio se a proposta nunca foi aberta.
/api/v1/vendor/quotes/{id}/proposal/eventsSellerEventos de decisão da proposta pública
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso de um usuário seller (veja Tokens).Parâmetros de caminho
idintegerobrigatório400 invalid quote id.Exemplo de requisição
curl "$BASE_URL/api/v1/vendor/quotes/69/proposal/events" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"events": [
{
"id": "7b0f5f7e-9c0c-4d2c-8c55-2d0d6f7b1a11",
"event_type": "approve",
"actor_name": "Maria Souza",
"actor_role": "Compradora",
"comment": "De acordo.",
"ip": "203.0.113.10",
"user_agent": "Mozilla/5.0",
"created_at": "2026-10-12T09:30:00Z"
}
]
}Campos da resposta
eventsobject[]Eventos, na ordem em que ocorreram.
iduuidevent_typestringapprove, reject, comment).actor_namestringactor_rolestringcommentstringipstringuser_agentstringcreated_atstringErros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 400 | id não é um inteiro. | {"error":"invalid quote id"} |
| 404 | A cotação não existe. | {"error":"quote not found"} |
| 403 | A cotação é de outro seller. | {"error":"quote does not belong to this vendor"} |
| 401 | Token ausente, inválido, expirado ou revogado. | {"error":"missing authorization header"} |
| 403 | O token não é de um usuário seller (por exemplo, é de administrador), ou o usuário não está vinculado a nenhum seller. | {"error":"insufficient permissions"} |
| 403 | O módulo b2b-pricing está desligado nesta loja. | {"error":"module_disabled","module":"b2b-pricing"} |