API Admin › Recursos
Propostas (modo de aprovação)
O lojista que quer revisar o que uma integração muda nos textos da loja (um agente de SEO, de conteúdo, de anúncios) põe a integração em modo proposta, no painel: Configurações › Integrações, em "Nome, escopos e aprovação". Nesse modo, as escritas de texto dela não mudam a loja: cada uma vira uma proposta, que alguém da equipe aprova ou recusa no painel, em Sugestões dos agentes. O padrão é o modo direto, em que a escrita grava na hora.
| Escopo | O que abre |
|---|---|
write_content ou write_products | ler as propostas desta integração |
O GET /token diz o modo em integration.approval_mode: direct ou proposal. A troca vale já na próxima chamada. No servidor MCP, o mesmo vale para as ferramentas de escrita, e a ferramenta list_proposals faz o que GET /proposals faz.
O que vira proposta
As escritas de texto, as mesmas que vão para o histórico das mudanças:
PATCH /products/{id}com título, descrição, SEO ou endereço;PATCH /products/{id}/images/{image_id}(o texto da foto);PATCH /collections/{id}ePATCH /brands/{id}com os textos;POST /pagesePATCH /pages/{id}.
Em modo proposta, elas passam pelas mesmas validações (os limites, o endereço em uso) e respondem 202 Accepted com a proposta, e nada muda na loja. Se não houver o que mudar (o valor já é esse), a resposta é a de sempre. A escrita que não mexe em texto (o preço, o estoque, a situação) continua direta. O PATCH que mistura texto com outro campo é recusado com 422 proposal_text_only, e os campos que não são texto vêm em fields: mande os textos numa chamada e o resto em outra.
curl -X PATCH "https://api.denaryx.com/admin/2026-10/products/5f2c…" \
-H "Authorization: Bearer dnxa_..." \
-H "Content-Type: application/json" \
-d '{"seo": {"title": "Camiseta de algodão orgânico | Minha Loja"}}'{
"id": "a41e…",
"resource_type": "product",
"resource_id": "5f2c…",
"product_id": null,
"label": "Camiseta Básica",
"action": "update",
"fields": [
{
"field": "seo.title",
"before": "",
"after": "Camiseta de algodão orgânico | Minha Loja"
}
],
"batch_id": null,
"origin": "api",
"status": "pending",
"created_at": "2026-10-21T13:02:11.482Z",
"expires_at": "2026-10-28T13:02:11.482Z",
"decided_at": null,
"rejection_reason": null,
"conflict": null,
"change_id": null,
"reverts": null
}O before de cada campo é o valor de base, lido na hora da proposta. A página proposta (POST /pages) vem com resource_id null: ela só é criada quando o lojista aprova, ainda fora do ar.
A decisão
Alguém da equipe com a permissão de editar o catálogo (e a de cuidar da loja virtual, nas páginas) aprova ou recusa no painel, uma a uma ou várias de uma vez. A loja recebe por e-mail, todo dia de manhã, um resumo das propostas que chegaram nas últimas 24 horas.
status | O que aconteceu |
|---|---|
pending | Espera a decisão, até expires_at. |
approved | Foi ao ar. change_id é a mudança no histórico, que o lojista desfaz no painel e o agente desfaz pelo servidor MCP. Na página criada, resource_id passa a ser o id dela. |
rejected | Recusada. rejection_reason traz o motivo, quando o lojista escreveu. |
conflict | Nada foi aplicado: o valor de base mudou antes da aprovação (alguém editou o recurso), o recurso foi excluído, o endereço passou a estar em uso, ou a mudança a desfazer já tinha sido desfeita. |
expired | Ninguém decidiu em 7 dias. |
A aprovação aplica só se cada campo ainda tiver o valor de base, como o desfazer, e cada proposta é decidida por si: a que tem conflito não segura as outras. Em conflito, conflict diz o motivo e o valor de agora:
{
"conflict": {
"code": "base_changed",
"message": "Nada foi aplicado: o campo título para os buscadores mudou depois da sugestão.",
"fields": [
{
"field": "seo.title",
"expected": "",
"current": "Camiseta básica | Minha Loja"
}
]
}
}Leia o recurso de novo e, se a mudança ainda fizer sentido, proponha outra vez.
GET /proposals
As propostas desta integração, da mais nova para a mais velha, em páginas (ver Listas).
| Parâmetro | O que é |
|---|---|
status | Só as que estão nesta situação: pending, approved, rejected, conflict ou expired. |
batch_id | Só as da mesma chamada (o lote do servidor MCP). |
limit | De 1 a 100 (50 sem ele). |
cursor | O next_cursor da página anterior. |
curl "https://api.denaryx.com/admin/2026-10/proposals?status=rejected" \
-H "Authorization: Bearer dnxa_..."GET /proposals/{id}
Uma proposta desta integração. A de outra integração da mesma loja é 404 not_found.
Prazos
A proposta pendente expira em 7 dias. As propostas, decididas ou não, ficam 180 dias, como o histórico das mudanças, e somem junto com a integração.