Documentação
Gerenciar produtos
Crie, edite e controle a disponibilidade do cardápio por canal.
A Nova API V1.0 permite cadastrar e editar produtos do restaurante sem expor
exclusão. Com OAuth, as operações de escrita exigem products:write;
consultar um produto ou o catálogo exige products:read, e o menu usa menu:read. A sessão do
restaurante também é aceita, sem escopos de integração, e só pode alterar
produtos do restaurant_id assinado no token.
Para entender o efeito de cada alteração, consulte a Referência de campos do produto: preços por canal, promoções, esgotamento, venda por peso e padrões na criação.
Antes de começar
Use o access_token obtido pelo OAuth, não a chave tk_
diretamente. Nos exemplos, TAKEAT_API_URL é https://public-api.takeat.app,
sem /v1 no final. Substitua os IDs pelos registros do seu restaurante.
Se a credencial OAuth permite mais de um restaurante, acrescente
?restaurant_id=85 à URL de cada chamada, usando o ID autorizado desejado.
Com sessão de restaurante, o contexto vem do token; um restaurant_id
conflitante é rejeitado. O restaurante não é escolhido pelo corpo JSON.
| Objetivo | Rota | Escopo OAuth |
|---|---|---|
| Listar categorias de produtos | GET /v1/product-categories | products:read |
| Consultar uma categoria de produtos | GET /v1/product-categories/{categoryId} | products:read |
| Criar uma categoria de produtos | POST /v1/product-categories | products:write |
| Editar uma categoria de produtos | PUT /v1/product-categories/{categoryId} | products:write |
| Consultar categorias e produtos no formato legado | GET /v1/products | products:read |
| Consultar os campos atuais e a versão de um produto | GET /v1/products/{productId} | products:read |
| Enviar uma imagem | POST /v1/files | products:write |
| Criar até 100 produtos atomicamente | POST /v1/products/bulk | products:write |
| Criar um produto | POST /v1/products | products:write |
| Editar campos, inclusive esgotamento | PUT /v1/products/{productId} | products:write |
| Editar de 1 a 100 produtos atomicamente | PUT /v1/products/bulk | products:write |
| Alterar somente os canais de venda | PATCH /v1/products/{productId}/availability | products:write |
| Consultar o menu e o preço efetivo de um canal | GET /v1/menu | menu:read |
Teste também altera dados reais
tk_test_ identifica a credencial, mas não cria um banco sandbox. As chamadas
abaixo modificam o cardápio real do restaurante autorizado.
Gerenciar categorias de produtos
As categorias de produtos têm rotas próprias em /v1/product-categories. Elas
não são o mesmo recurso que as categorias de complementos. A listagem de
categorias retorna somente os cadastros não removidos, ordenados por
custom_order e depois por id, sem os produtos aninhados. Para consultar as
categorias junto com seus produtos no formato legado, use GET /v1/products.
As rotas aceitam o access token OAuth com products:read para consulta e
products:write para criação ou edição. Uma sessão autenticada do restaurante
também é aceita. Se a credencial OAuth puder acessar mais de um restaurante,
envie ?restaurant_id=<id> em cada chamada; a sessão de restaurante permanece
limitada ao restaurante assinado no token.
Consultar categorias
GET /v1/product-categories?restaurant_id=85
Authorization: Bearer <access_token>GET /v1/product-categories retorna um array de snapshots. Para consultar uma
categoria específica, use GET /v1/product-categories/{categoryId}. Registros
removidos, inexistentes ou pertencentes a outro restaurante respondem 404 product_category_not_found, sem revelar dados de outro restaurante.
Cada snapshot contém id, restaurant_id, brand_id, name, as
disponibilidades por canal, is_exclusive, custom_order,
preparation_time, created_at e updated_at:
| Campo | Tipo | Efeito |
|---|---|---|
brand_id | integer positivo | Marca do restaurante à qual a categoria pertence. |
name | string de 1 a 255 caracteres | Nome da categoria. |
available | boolean | Disponibilidade para venda presencial. |
available_in_delivery | boolean | Disponibilidade para delivery e retirada pelo fluxo de delivery. |
available_in_self_service | boolean | Disponibilidade no autosserviço. |
available_in_drive_thru | boolean | Disponibilidade no drive-thru. |
is_exclusive | boolean | Indica que a categoria é exclusiva de um canal. |
custom_order | integer de 0 a 2147483647 | Posição da categoria no cardápio. |
preparation_time | integer de 0 a 2147483647 ou null | Tempo de preparo configurado para a categoria. |
As flags de disponibilidade são independentes. Desabilitar available não
desabilita delivery, e desabilitar available_in_delivery não desabilita a
venda presencial. No menu filtrado por disponibilidade, a categoria e o item
também precisam estar disponíveis no canal consultado.
Criar uma categoria
Crie a categoria com name e brand_id. A marca deve existir, não estar
removida e pertencer ao restaurante autorizado. Use a consulta de
marcas para obter o ID; a categoria não aceita uma marca
de outro restaurante.
POST /v1/product-categories?restaurant_id=85
Authorization: Bearer <access_token>
Content-Type: application/json
{
"name": "Hambúrgueres",
"brand_id": 3,
"available": true,
"available_in_delivery": true,
"available_in_self_service": false,
"available_in_drive_thru": true,
"custom_order": 100,
"preparation_time": 15
}POST retorna 201 com o snapshot da categoria criada. Os padrões quando os
campos opcionais são omitidos são true para available,
available_in_delivery e available_in_self_service, false para
available_in_drive_thru e is_exclusive, 100 para custom_order e null
para preparation_time. A criação sempre gera um cadastro manual, não
gerenciado por integração.
Editar uma categoria
PUT /v1/product-categories/{categoryId} é parcial: campos omitidos permanecem
inalterados. A marca não é editável; não envie brand_id para uma categoria
existente. Para proteger uma edição baseada em uma leitura, copie o
updated_at consultado para expected_updated_at:
PUT /v1/product-categories/10?restaurant_id=85
Authorization: Bearer <access_token>
Content-Type: application/json
{
"available": false,
"available_in_delivery": true,
"preparation_time": 20,
"expected_updated_at": "2026-09-30T12:00:00.000Z"
}O campo expected_updated_at é opcional, não é uma alteração por si só e deve
ser o valor devolvido pela consulta. Se a categoria tiver mudado desde essa
consulta, a API retorna 409 product_category_conflict; consulte novamente,
revise a proposta e só então reenvie. Sem esse campo, a edição não faz a
verificação otimista de versão.
Categorias gerenciadas por integração não podem ser alteradas. Isso inclui
cadastros vinculados a iFood, Neemo, multistore ou com código de integração;
essas tentativas retornam 400 invalid_product_category. A API também não
expõe DELETE /v1/product-categories/{categoryId}. Imagens, horários,
configurações de impressão, KDS e vínculos de produtos não são gerenciados por
estas rotas.
Para criar ou editar categorias de complementos, use a gestão de categorias de complementos.
Enviar a imagem do produto
Faça upload antes de criar ou editar o produto. POST /v1/files exige
products:write ou uma sessão de restaurante e aceita um único campo multipart
file. Não defina Content-Type manualmente: o cliente gera o boundary.
curl -X POST "$TAKEAT_API_URL/v1/files?restaurant_id=85" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-F "file=@/caminho/burger.png"Aceita JPEG, PNG e WebP de até 10 MiB e 25 megapixels. O servidor verifica o conteúdo real, rejeita animações, aplica a orientação da câmera e converte a imagem em WebP sem metadados, com dimensão máxima de 1600 pixels e miniatura com dimensão máxima de 400 pixels. SVG, GIF, PDF e outros arquivos são rejeitados.
A resposta 201 inclui id, name, path, url, thumbnail_url,
content_type e size (bytes da imagem processada). Envie esse id como
image_id em POST /v1/products, POST /v1/products/bulk,
PUT /v1/products/{productId} ou PUT /v1/products/bulk.
{ "image_id": 123 }Na edição, image_id: null remove a imagem; omitir o campo preserva a atual.
A resposta do produto inclui image_id; o menu retorna a imagem e sua miniatura
em presentation.image. Só é permitido associar imagens enviadas por este
endpoint para o mesmo restaurante. IDs ausentes, de outro restaurante ou de
arquivos genéricos retornam 404 product_image_not_found.
O upload sozinho não altera o produto. Se uma criação ou edição falhar, o arquivo
continua disponível para uma nova tentativa. O upload não oferece exclusão de
arquivos nem uma rota genérica de mídia. Storage sem configuração responde
503 image_upload_unavailable; falhas de persistência respondem
503 image_upload_failed. Arquivo grande demais recebe 413.
Criar vários produtos
POST /v1/products/bulk aceita um array de 1 a 100 objetos com os mesmos campos
obrigatórios da criação individual. A resposta 201 é um array na ordem do
pedido. Todas as criações ocorrem em uma transação serializável: uma categoria
inválida, imagem não autorizada ou outro erro impede a criação do lote inteiro.
Lotes separados são transações independentes.
Criar um produto
O produto deve apontar para uma categoria não removida do mesmo restaurante. Uma categoria indisponível não é removida: ela pode receber produtos, mas continuará oculta no menu filtrado por disponibilidade.
O produto não recebe brand_id diretamente: a marca vem da categoria. Ao
alterar product_category_id, o produto passa a usar a marca da categoria de
destino, além de ser reposicionado ao final dela.
curl -X POST "$TAKEAT_API_URL/v1/products" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Takeat Burger",
"product_category_id": 10,
"price": 28.00,
"delivery_price": 31.00,
"available": true,
"available_in_delivery": true
}'Obrigatórios: name, product_category_id e price. Quando não informadas,
as duas disponibilidades começam como true, sold_off, use_weight e
has_starting_price como false, e charge_service_tax como true.
Editar um produto
Consulte GET /v1/products/{productId} para obter os campos editáveis e o
updated_at atual. Produtos removidos ou de outro restaurante retornam 404.
PUT /v1/products/{productId} é parcial: envie somente os campos que devem
mudar. Campos ausentes permanecem intactos; preços promocionais e de delivery
aceitam null para remover o valor.
description também aceita null para limpar. Envie preços como números JSON
(por exemplo, 34.90), embora a consulta os retorne como strings ("34.90").
Não envie campos somente de leitura, como restaurant_id, created_at e
updated_at, no corpo de edição.
Na edição, price: 0 é permitido; valores negativos ou com mais de duas casas
decimais são rejeitados. A criação continua exigindo price positivo. Salão e
delivery são independentes: não altere os dois canais sem intenção explícita.
Opcionalmente envie expected_updated_at com o updated_at consultado. Se o
produto mudou desde a consulta, a API responde 409 product_update_conflict.
Consulte novamente e peça uma nova aprovação; não repita a escrita automaticamente.
curl -X PUT "$TAKEAT_API_URL/v1/products/42" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Takeat Burger Duplo", "price": 34.90 }'Não existe DELETE /v1/products/{productId} nesta API.
Editar vários produtos
PUT /v1/products/bulk recebe um array diretamente no corpo, com 1 a 100
objetos. Cada objeto contém id e os campos parciais que devem mudar:
[
{ "id": 42, "price": 0, "expected_updated_at": "2026-08-26T14:00:00.000Z" },
{ "id": 43, "delivery_price": 0 }
]IDs repetidos são rejeitados com 400 duplicate_product_ids, mesmo quando
os objetos alteram campos diferentes. Um campo inválido, alteração vazia,
produto/categoria inexistente ou versão desatualizada impede todo o lote.
A operação é atômica e retorna um array de produtos na ordem recebida.
Para agentes de IA, mostre todos os valores atuais e propostos e aguarde a aprovação do operador antes da chamada. A API exige credenciais válidas, mas a aplicação integradora é responsável por obter essa aprovação humana.
Campos fiscais são enviados em fiscal_info como alterações parciais; null
limpa um campo. O identificador interno fiscal_group_id não é exposto nem editável.
As respostas incluem fiscal e o alias compatível fiscal_info;
veja a explicação de cada atributo fiscal.
Alterar disponibilidade
Use a rota focada quando a alteração for somente de canal:
curl -X PATCH "$TAKEAT_API_URL/v1/products/42/availability" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"available": false,
"available_in_delivery": true
}'| Campo | Canal |
|---|---|
available | Venda presencial, balcão e consumo no local |
available_in_delivery | Delivery e retirada pelo fluxo de delivery |
Os campos são independentes e ao menos um deles deve ser enviado. Depois da
alteração, GET /v1/menu?only_available=true passa a refletir o novo estado no
canal correspondente.
Para sinalizar falta temporária, envie { "sold_off": true } no PUT
individual ou em lote; sold_off não é aceito no PATCH /availability.
O menu exclui esgotados com only_available=true. Com false, retorna
availability.sold_out e o motivo em availability.resolved.reason.
Horários e escolhas obrigatórias também afetam a elegibilidade. Confira as
regras do menu.
Resposta
Criação, edição e disponibilidade retornam o produto atualizado. Valores monetários são strings com duas casas. Exemplo abreviado:
{
"id": 42,
"restaurant_id": 85,
"product_category_id": 10,
"name": "Takeat Burger Duplo",
"price": "34.90",
"delivery_price": "31.00",
"available": false,
"available_in_delivery": true,
"created_at": "2026-08-26T12:00:00.000Z",
"updated_at": "2026-08-26T14:00:00.000Z"
}O produto e a categoria são sempre verificados contra o restaurante resolvido
pela credencial. IDs de outro restaurante respondem 404, sem revelar que o
registro existe.
Erros comuns
HTTP / key | Como resolver |
|---|---|
400 por corpo inválido | Confira tipos, limite de duas casas decimais, campos aceitos e pelo menos uma alteração efetiva. |
400 product_changes_required | Envie um campo editável; apenas id, expected_updated_at ou um objeto fiscal vazio não bastam. |
400 duplicate_product_ids | Agrupe as mudanças de cada produto em um único objeto do lote. |
404 product_not_found | Confira o ID e o restaurante autorizado; o produto pode ter sido removido. |
404 product_category_not_found | Escolha uma categoria não removida do mesmo restaurante. |
409 product_update_conflict | Consulte os valores atuais e revise a proposta antes de reenviar. No lote, nenhum produto foi alterado. |
Se a escrita foi aceita, mas o produto não aparece ou o preço parece diferente, veja o guia de diagnóstico.
Consulte também Gerenciar complementos para editar opções, preços, fiscal e disponibilidade, individualmente ou em lote.
Criar e editar categorias de produtos
| Ação | Rota | Escopo OAuth |
|---|---|---|
| Listar categorias, inclusive vazias | GET /v1/product-categories | products:read |
| Consultar uma categoria | GET /v1/product-categories/{categoryId} | products:read |
| Criar categoria | POST /v1/product-categories | products:write |
| Editar categoria parcialmente | PUT /v1/product-categories/{categoryId} | products:write |
Uma sessão autenticada de restaurante também é aceita. O isolamento segue o mesmo restaurant_id autorizado das rotas de produtos. Consulte GET /v1/brands para obter uma marca real do restaurante. name e brand_id são obrigatórios na criação; a marca de uma categoria existente não pode ser alterada.
POST /v1/product-categories?restaurant_id=85
Authorization: Bearer <access_token>
Content-Type: application/json
{"name":"Hambúrgueres especiais","brand_id":3,"custom_order":10,"available":true,"available_in_delivery":true}Campos editáveis: name (1–255 caracteres), available, available_in_delivery, available_in_self_service, available_in_drive_thru, is_exclusive (booleanos), custom_order (inteiro não negativo) e preparation_time (inteiro não negativo ou null). Inteiros são limitados a 2147483647. preparation_time: null limpa o tempo de preparo; demais campos não aceitam null. Campos omitidos são preservados. As disponibilidades são independentes entre canais.
As respostas retornam o objeto da categoria com id, restaurant_id, brand_id, campos editáveis, created_at e updated_at. Campos internos de integração, multiloja e dados completos da marca não são expostos. Na edição, envie expected_updated_at devolvido pela consulta para proteger uma revisão. Uma revisão obsoleta recebe 409 product_category_conflict. Um corpo vazio ou apenas com expected_updated_at recebe 400.
Categorias inexistentes, excluídas ou de outro restaurante recebem o mesmo 404 product_category_not_found. Categorias gerenciadas por integração ou multiloja rejeitam edição com 409. Estas rotas não editam imagens, horários, configurações de integração ou vínculos de produtos, e não expõem exclusão. Para mover um produto, use product_category_id na edição do próprio produto; para criar produtos em uma nova categoria, aguarde a resposta da criação e use o id real retornado.
Categorias de complementos são recursos distintos e usam complements:read/write; consulte Gerenciar complementos.
Editar a ordem do cardápio
Use custom_order em PUT /v1/products/:productId ou em
PUT /v1/products/bulk para ordenar produtos dentro de cada categoria.
Para ordenar as categorias, use o campo já disponível em
PUT /v1/product-categories/:categoryId. As escritas exigem products:write
ou uma sessão verificada do restaurante; menu:read sozinho não autoriza edição.
O valor deve ser um inteiro entre 0 e 2147483647. Valores menores aparecem
primeiro; produtos empatados usam o ID crescente. A ordem é compartilhada entre
salão e delivery. Omitir o campo preserva a ordem, exceto ao mover para outra
categoria: sem ordem explícita, o produto vai para o final da categoria de destino.
Enviar product_category_id junto com custom_order define a categoria e a posição.
A API não desloca nem renumera automaticamente os demais produtos.
Consulte o cardápio com only_available=false e sem busca para incluir produtos
indisponíveis antes de calcular a sequência. Para categorias vazias, consulte
GET /v1/product-categories. Leia os snapshots de produtos para obter updated_at
e envie-o como expected_updated_at para detectar alterações concorrentes.
PUT /v1/products/bulk?restaurant_id=85
Authorization: Bearer <access_token>
Content-Type: application/json
[
{ "id": 102, "custom_order": 0, "expected_updated_at": "2026-10-27T12:00:00.000Z" },
{ "id": 101, "custom_order": 1, "expected_updated_at": "2026-10-27T12:00:00.000Z" }
]Os IDs e horários são exemplos: substitua pelos snapshots atuais da loja.
Cada lote aceita de 1 a 100 IDs distintos e é atômico. ID ausente ou de outra loja,
versão desatualizada ou campo inválido impede a aplicação do lote inteiro.
Conflitos de versão retornam 409; consulte novamente antes de reapresentar a edição.
Vários lotes e edições de categorias não formam uma transação única.
As respostas de consulta e escrita de produto incluem custom_order.
Depois da escrita, consulte novamente GET /v1/menu para obter a apresentação
ordenada. Grupos de escolhas e opções de complementos não têm edição de ordem
nessas rotas. As restrições existentes de categorias gerenciadas por integrações
ou multilojas continuam valendo.