Layout e modelos
Salva a posição dos cards com controle de versão e usa a biblioteca de modelos de card.
O layout (posição e tamanho dos cards) é salvo em lote, com um número de versão que protege contra duas pessoas editando a mesma aba. A biblioteca de modelos oferece cards prontos e guarda os que o próprio seller salvar.
Salvar layout
Atualiza posição e tamanho de vários cards em uma transação. Se a aba mudou desde a sua última leitura, a operação é recusada com 409 e você recebe o layout atual.
/api/v1/vendor/dashboards/{id}/layoutSellerSalvar layout
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso do usuário seller (veja Tokens).Content-Typestringobrigatórioapplication/json.Parâmetros de caminho
iduuidobrigatórioCorpo da requisição
versionintegerversion da aba na sua última leitura. Se não bater com o atual, a resposta é 409. 0 ou omitido pula a verificação.itemsobject[]obrigatórioUm item por card.
items[].card_iduuidobrigatórioitems[].grid_rowintegeritems[].grid_colintegeritems[].widthintegeritems[].heightintegerExemplo de requisição
curl -X PUT "$BASE_URL/api/v1/vendor/dashboards/931b3fc7-e703-4cac-bcbc-5c79690f02a8/layout" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"version": 1791752657246, "items": [{"card_id": "94c6b3ff-de9c-4552-8a12-e199e8427f57", "grid_row": 0, "grid_col": 0, "width": 2, "height": 1}]}'Resposta
{
"version": 1791752700123,
"message": "layout updated"
}{
"version": 1791752690000,
"items": [
{
"card_id": "94c6b3ff-de9c-4552-8a12-e199e8427f57",
"grid_row": 0,
"grid_col": 0,
"width": 1,
"height": 1,
"order": 0
}
]
}Campos da resposta
versioninteger200, a nova versão; guarde-a para o próximo salvamento. No 409, a versão atual do servidor.itemsobject[]409: o layout atual (card_id, grid_row, grid_col, width, height, order).messagestring200.Erros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 404 | A aba não existe, é de outro seller ou você não pode vê-la. A API responde 404 nos três casos para não revelar que ela existe. | {"error":"dashboard not found"} |
| 400 | Corpo que não é JSON. | {"error":"invalid request body"} |
| 409 | version diferente da atual. Adote o items devolvido ou reenvie com a nova version. | {"version":1791752690000,"items":[...]} |
| 500 | Algum card_id não pertence à aba, ou falha ao gravar. Nenhuma mudança é aplicada. | {"error":"failed to update layout","detail":"..."} |
| 401 | Token ausente, inválido, expirado ou revogado. | invalid or expired token |
| 403 | O token não é de um usuário seller, ou a loja ainda está em análise de cadastro. | {"error":"vendor_pending_review"} |
Listar modelos
Devolve a biblioteca de modelos de card visíveis ao seller: os da plataforma e os que ele mesmo salvou. Os cards de fábrica não entram aqui.
/api/v1/vendor/dashboards/templatesSellerListar modelos
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso do usuário seller (veja Tokens).Parâmetros de consulta
categorystringExemplo de requisição
curl -X GET "$BASE_URL/api/v1/vendor/dashboards/templates?category=sales" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"templates": [
{
"slug": "meu-top-produtos",
"category": "geral",
"name_pt": "Top produtos",
"name_en": "",
"description_pt": "",
"spec": {
"spec_version": 1,
"kind": "query",
"title": "Top produtos",
"viz": {
"type": "bar",
"snippet_id": "top-produtos"
},
"query": {
"entity": "order_items"
}
},
"icon": "",
"panel": "V",
"default_width": 1,
"default_height": 1,
"is_builtin": false,
"has_real_data": true,
"position": 0,
"is_mine": true
}
]
}Campos da resposta
templatesobject[]|nullOs modelos. Pode vir null (e não []) quando não há nenhum.
templates[].slugstringfrom-template.templates[].categorystringtemplates[].name_ptstringtemplates[].name_enstringtemplates[].description_ptstringtemplates[].specobjecttemplates[].iconstringtemplates[].panelstringV seller, A administrador, B ambos.templates[].default_widthintegertemplates[].default_heightintegertemplates[].is_builtinbooleantrue se é da plataforma.templates[].has_real_databooleanfalse quando a loja ainda não tem dados para o modelo mostrar algo útil.templates[].positionintegertemplates[].is_minebooleantrue se foi salvo pelo próprio seller.Erros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 401 | Token ausente, inválido, expirado ou revogado. | invalid or expired token |
| 403 | O token não é de um usuário seller, ou a loja ainda está em análise de cadastro. | {"error":"vendor_pending_review"} |
| 500 | Falha ao listar. | {"error":"failed to list templates"} |
Criar card de um modelo
Instancia um modelo como card da aba, usando o tamanho sugerido pelo modelo. A spec do modelo é validada como qualquer outra.
/api/v1/vendor/dashboards/{id}/cards/from-templateSellerCriar card de um modelo
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso do usuário seller (veja Tokens).Content-Typestringobrigatórioapplication/json.Parâmetros de caminho
iduuidobrigatórioCorpo da requisição
template_slugstringobrigatórioslug do modelo.grid_rowinteger0.grid_colinteger0.orderinteger0.Exemplo de requisição
curl -X POST "$BASE_URL/api/v1/vendor/dashboards/931b3fc7-e703-4cac-bcbc-5c79690f02a8/cards/from-template" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"template_slug": "meu-top-produtos", "grid_row": 1, "grid_col": 0, "order": 10}'Resposta
{
"id": "94c6b3ff-de9c-4552-8a12-e199e8427f57",
"dashboard_id": "931b3fc7-e703-4cac-bcbc-5c79690f02a8",
"spec": {
"spec_version": 1,
"kind": "query",
"title": "Receita do Mês",
"viz": {
"type": "kpi",
"snippet_id": "seller-kpi-revenue-month",
"icon": "cifrao",
"accent": "#0044FF",
"number_format": {
"style": "currency_cents"
}
},
"query": {
"entity": "orders",
"period": {
"mode": "preset",
"preset": "thisMonth"
},
"metrics": [
{
"id": "receita",
"kind": "catalog",
"ref": "orders.revenue"
}
]
}
},
"spec_version": 1,
"kind": "Q",
"title": "Top produtos",
"grid_row": 1,
"grid_col": 0,
"width": 1,
"height": 1,
"order": 10,
"status": "A",
"source": "T",
"template_slug": "meu-top-produtos",
"created_at": "2026-10-11T21:04:20.327443Z",
"updated_at": "2026-10-11T21:04:20.327443Z"
}Erros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 404 | A aba não existe, é de outro seller ou você não pode vê-la. A API responde 404 nos três casos para não revelar que ela existe. | {"error":"dashboard not found"} |
| 400 | Corpo que não é JSON. | {"error":"invalid request body"} |
| 422 | Modelo inexistente ou que não compila. | {"error":"failed to create card from template","detail":"..."} |
| 401 | Token ausente, inválido, expirado ou revogado. | invalid or expired token |
| 403 | O token não é de um usuário seller, ou a loja ainda está em análise de cadastro. | {"error":"vendor_pending_review"} |
Salvar card como modelo
Guarda a spec do card como modelo pessoal do seller, para reaproveitar em outras abas.
/api/v1/vendor/dashboards/{id}/cards/{cardId}/save-as-templateSellerSalvar card como modelo
Cabeçalhos
AuthorizationstringobrigatórioBearer $TOKEN. Token de acesso do usuário seller (veja Tokens).Content-Typestringobrigatórioapplication/json.Parâmetros de caminho
iduuidobrigatóriocardIduuidobrigatórioCorpo da requisição
name_ptstringobrigatóriocategorystringpadrão: geralExemplo de requisição
curl -X POST "$BASE_URL/api/v1/vendor/dashboards/931b3fc7-e703-4cac-bcbc-5c79690f02a8/cards/94c6b3ff-de9c-4552-8a12-e199e8427f57/save-as-template" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name_pt": "Receita do mês", "category": "vendas"}'Resposta
{
"slug": "receita-do-mes-1f3a",
"category": "vendas",
"name_pt": "Receita do mês",
"name_en": "",
"description_pt": "",
"spec": {
"spec_version": 1,
"kind": "query",
"title": "Receita do Mês",
"viz": {
"type": "kpi",
"snippet_id": "seller-kpi-revenue-month",
"icon": "cifrao",
"accent": "#0044FF",
"number_format": {
"style": "currency_cents"
}
},
"query": {
"entity": "orders",
"period": {
"mode": "preset",
"preset": "thisMonth"
},
"metrics": [
{
"id": "receita",
"kind": "catalog",
"ref": "orders.revenue"
}
]
}
},
"icon": "cifrao",
"panel": "V",
"default_width": 1,
"default_height": 1,
"is_builtin": false,
"has_real_data": true,
"position": 0,
"is_mine": true
}Erros
| Status | Quando | Corpo de exemplo |
|---|---|---|
| 404 | A aba ou o card não existe ou não é do seller. Os dois casos dão 404. | {"error":"card not found"} |
| 400 | Corpo que não é JSON. | {"error":"invalid request body"} |
| 422 | name_pt vazio ou falha ao salvar. | {"error":"failed to save card as template","detail":"name_pt is required"} |
| 401 | Token ausente, inválido, expirado ou revogado. | invalid or expired token |
| 403 | O token não é de um usuário seller, ou a loja ainda está em análise de cadastro. | {"error":"vendor_pending_review"} |