{
  "info": {
    "name": "Flux — API Externa v1",
    "description": "API pública read-only do Flux (`/api/v1`): projetos, posts, grupos de conteúdo, contas conectadas e aprovações.\n\nFormato Postman Collection v2.1 — importável no Postman e no Insomnia.\n\n## Como usar\n\n1. A variável `baseUrl` já aponta para produção (`https://flux.reportei.com`).\n2. Coloque seu token em `token` — é o `flux_...` apresentado uma única vez no momento da criação, em **Configurações → Tokens de API**.\n3. As requisições que dependem de um id (`projectId`, `postId`, `assetGroupId`, `reviewGroupId`) são preenchidas a partir das listagens.\n\n## Escopos\n\n- `projects:read` → endpoints de projetos\n- `posts:read` → posts, grupo de conteúdo\n- `integrations:read` → contas conectadas\n- `reviews:read` → decisões e grupos de aprovação\n\nUm token sem o escopo do endpoint responde `403`.\n\nDocumentação completa: https://developers.reportei.com/flux",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{token}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://flux.reportei.com",
      "type": "string",
      "description": "Base do Flux em produção"
    },
    {
      "key": "token",
      "value": "",
      "type": "string",
      "description": "Seu token do Flux (flux_...). Apresentado uma única vez, na criação."
    },
    {
      "key": "tokenProjectsOnly",
      "value": "",
      "type": "string",
      "description": "Opcional: um segundo token emitido SÓ com projects:read, para ver o 403 de escopo insuficiente."
    },
    {
      "key": "projectId",
      "value": "",
      "type": "string"
    },
    {
      "key": "postId",
      "value": "",
      "type": "string"
    },
    {
      "key": "reviewGroupId",
      "value": "",
      "type": "string",
      "description": "Id do grupo de aprovação. Preenchido a partir de \"Listar grupos de aprovação\"."
    },
    {
      "key": "assetGroupId",
      "value": "",
      "type": "string",
      "description": "Id do grupo de conteúdo (asset_group_id de qualquer post)."
    }
  ],
  "item": [
    {
      "name": "Projetos",
      "description": "Escopo exigido: `projects:read`",
      "item": [
        {
          "name": "Listar projetos",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects?per_page=15",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "projects"
              ],
              "query": [
                {
                  "key": "per_page",
                  "value": "15",
                  "description": "1 a 50. Padrão 15. Acima de 50 → 422."
                },
                {
                  "key": "page",
                  "value": "1",
                  "disabled": true,
                  "description": "Página, a partir de 1"
                },
                {
                  "key": "archived",
                  "value": "1",
                  "disabled": true,
                  "description": "1 retorna SOMENTE os arquivados. Por padrão a listagem traz só os ativos."
                },
                {
                  "key": "all",
                  "value": "1",
                  "disabled": true,
                  "description": "1 retorna ativos e arquivados juntos"
                }
              ]
            },
            "description": "Projetos da conta do token, com as contas conectadas de cada um.\n\nO `status` de cada integração indica a saúde da conexão: `active` quando válida, outro valor quando exige reconexão no painel."
          },
          "response": [
            {
              "name": "200 — listagem",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/projects?per_page=2",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "projects"
                  ],
                  "query": [
                    {
                      "key": "per_page",
                      "value": "2"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"data\": [\n    {\n      \"id\": 5,\n      \"name\": \"Novo Projeto Local\",\n      \"timezone\": \"America/Sao_Paulo\",\n      \"locale\": \"pt_br\",\n      \"archived\": false,\n      \"integrations\": [\n        {\n          \"id\": 59,\n          \"network\": \"facebook\",\n          \"network_group\": \"facebook\",\n          \"account\": {\n            \"id\": \"242029482522443\",\n            \"name\": \"BomDemas\"\n          },\n          \"status\": \"active\",\n          \"last_verified_at\": \"2026-08-26T12:20:29-03:00\",\n          \"created_at\": \"2026-01-20T10:58:14-03:00\"\n        },\n        {\n          \"id\": 2119,\n          \"network\": \"instagram\",\n          \"network_group\": \"instagram\",\n          \"account\": {\n            \"id\": \"27662914370036000_user\",\n            \"name\": \"arenaspro\"\n          },\n          \"status\": \"active\",\n          \"last_verified_at\": \"2026-08-26T12:20:29-03:00\",\n          \"created_at\": \"2026-07-30T13:30:25-03:00\"\n        }\n      ],\n      \"created_at\": \"2025-12-10T16:44:05-03:00\",\n      \"updated_at\": \"2025-12-10T16:44:05-03:00\"\n    }\n  ],\n  \"links\": {\n    \"first\": \"https://flux.reportei.com/api/v1/projects?page=1\",\n    \"last\": \"https://flux.reportei.com/api/v1/projects?page=3\",\n    \"prev\": null,\n    \"next\": \"https://flux.reportei.com/api/v1/projects?page=2\"\n  },\n  \"meta\": {\n    \"current_page\": 1,\n    \"from\": 1,\n    \"last_page\": 3,\n    \"path\": \"https://flux.reportei.com/api/v1/projects\",\n    \"per_page\": 2,\n    \"to\": 2,\n    \"total\": 5\n  }\n}"
            }
          ],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Conveniência: guarda dois projetos para as requisições de vínculo.",
                  "// O primeiro entra na allowlist do token restrito; o segundo fica de fora.",
                  "if (pm.response.code === 200) {",
                  "    const rows = pm.response.json().data || [];",
                  "    if (rows[0]) {",
                  "        pm.collectionVariables.set('allowedProjectId', rows[0].id);",
                  "        pm.collectionVariables.set('projectIds', String(rows[0].id));",
                  "    }",
                  "    if (rows[1]) pm.collectionVariables.set('deniedProjectId', rows[1].id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Consultar um projeto",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects/{{projectId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "projects",
                "{{projectId}}"
              ]
            },
            "description": "Projeto inexistente, excluído ou de outra conta responde 404 — nunca 403, para não revelar a existência de dados de terceiros."
          },
          "response": [
            {
              "name": "200 — projeto",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/projects/5",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "projects",
                    "5"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"data\": {\n    \"id\": 5,\n    \"name\": \"Novo Projeto Local\",\n    \"timezone\": \"America/Sao_Paulo\",\n    \"locale\": \"pt_br\",\n    \"archived\": false,\n    \"integrations\": [\n      {\n        \"id\": 59,\n        \"network\": \"facebook\",\n        \"network_group\": \"facebook\",\n        \"account\": {\n          \"id\": \"242029482522443\",\n          \"name\": \"BomDemas\"\n        },\n        \"status\": \"active\",\n        \"last_verified_at\": \"2026-08-26T12:20:29-03:00\",\n        \"created_at\": \"2026-01-20T10:58:14-03:00\"\n      }\n    ],\n    \"created_at\": \"2025-12-10T16:44:05-03:00\",\n    \"updated_at\": \"2025-12-10T16:44:05-03:00\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Posts",
      "description": "Escopo exigido: `posts:read`",
      "item": [
        {
          "name": "Listar posts",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts?per_page=15",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts"
              ],
              "query": [
                {
                  "key": "per_page",
                  "value": "15",
                  "description": "1 a 50. Padrão 15."
                },
                {
                  "key": "page",
                  "value": "1",
                  "disabled": true
                },
                {
                  "key": "project_id",
                  "value": "{{projectId}}",
                  "disabled": true,
                  "description": "Restringe a um projeto. Id de outra conta → 404."
                },
                {
                  "key": "start_date",
                  "value": "2026-09-01",
                  "disabled": true,
                  "description": "YYYY-MM-DD. schedule_at a partir desta data, inclusive, no fuso do projeto."
                },
                {
                  "key": "end_date",
                  "value": "2026-09-30",
                  "disabled": true,
                  "description": "YYYY-MM-DD. Precisa ser >= start_date."
                },
                {
                  "key": "status",
                  "value": "scheduled",
                  "disabled": true,
                  "description": "draft, in_review, scheduled, publishing, published, failed, archived. Aceita status=x e status[]=x."
                },
                {
                  "key": "network",
                  "value": "instagram",
                  "disabled": true,
                  "description": "instagram, instagram_business, facebook, threads, x, youtube, linkedin, linkedin_personal, tiktok, pinterest, google_my_business"
                },
                {
                  "key": "network_group",
                  "value": "instagram",
                  "disabled": true,
                  "description": "instagram, facebook, threads, x, youtube, linkedin, tiktok, pinterest, google_my_business"
                },
                {
                  "key": "type",
                  "value": "feed",
                  "disabled": true,
                  "description": "feed, story, reels, shorts, photo"
                },
                {
                  "key": "review_status",
                  "value": "pending",
                  "disabled": true,
                  "description": "pending, approved, request_changes. Restringe implicitamente a status=in_review."
                },
                {
                  "key": "order",
                  "value": "schedule_at",
                  "disabled": true,
                  "description": "schedule_at (padrão) ou created_at"
                },
                {
                  "key": "direction",
                  "value": "asc",
                  "disabled": true,
                  "description": "asc (padrão) ou desc"
                }
              ]
            },
            "description": "Posts da conta do token.\n\nParâmetros desconhecidos são ignorados. Valor inválido em parâmetro conhecido responde 422 — a API não devolve lista vazia para filtro errado.\n\n⚠️ As URLs em `media[].url` expiram em 48h (ver `url_expires_at`). Baixe o arquivo; não persista a URL."
          },
          "response": [
            {
              "name": "200 — listagem",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts?status=published&per_page=1",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts"
                  ],
                  "query": [
                    {
                      "key": "status",
                      "value": "published"
                    },
                    {
                      "key": "per_page",
                      "value": "1"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"data\": [\n    {\n      \"id\": 94,\n      \"asset_group_id\": 71,\n      \"project\": {\n        \"id\": 1,\n        \"name\": \"Projeto LEONEL\",\n        \"timezone\": \"America/Sao_Paulo\"\n      },\n      \"network\": \"instagram\",\n      \"network_group\": \"instagram\",\n      \"account\": {\n        \"id\": \"9654176157967125_user\",\n        \"name\": \"lucastesteagendamento\"\n      },\n      \"type\": \"feed\",\n      \"status\": \"published\",\n      \"review_status\": null,\n      \"caption\": \"O Kit Válvula Niveladora AirSuper é aquele item indispensável pra quem não abre mão de uma suspensão pneumática eficiente e segura.\",\n      \"first_comment\": null,\n      \"schedule_at\": \"2025-07-10T09:41:58-03:00\",\n      \"published_url\": null,\n      \"media\": [\n        {\n          \"id\": 993,\n          \"type\": \"image\",\n          \"url\": \"https://s3-medias.reportei.com/flux-upload/company/1/posts/148ff070-a766-4ddf-8e08-3dfb117d6fca-img-01.jpg?exp=1790859334&sig=76dba9186b10652ebaa877ef255b3193dd5058aae0e00e299be16f01f8f1a9fc\",\n          \"url_expires_at\": \"2026-09-03T09:55:34-03:00\",\n          \"width\": null,\n          \"height\": null,\n          \"aspect_ratio\": null\n        }\n      ],\n      \"created_at\": \"2025-07-10T09:40:58-03:00\",\n      \"updated_at\": \"2025-07-10T10:15:10-03:00\"\n    }\n  ],\n  \"links\": {\n    \"first\": \"https://flux.reportei.com/api/v1/posts?page=1\",\n    \"last\": \"https://flux.reportei.com/api/v1/posts?page=66\",\n    \"prev\": null,\n    \"next\": \"https://flux.reportei.com/api/v1/posts?page=2\"\n  },\n  \"meta\": {\n    \"current_page\": 1,\n    \"from\": 1,\n    \"last_page\": 66,\n    \"per_page\": 1,\n    \"to\": 1,\n    \"total\": 66\n  }\n}"
            }
          ]
        },
        {
          "name": "Consultar um post",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts/{{postId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts",
                "{{postId}}"
              ]
            },
            "description": "Devolve exatamente o mesmo objeto da listagem, sob a chave `data`.\n\nPost inexistente, excluído ou de outra conta responde 404.\n\nDevolve o mesmo objeto da listagem mais o bloco `review`, preenchido só enquanto status=in_review. decided conta decisões e pending conta revisores atribuídos que não decidiram, então decided + pending pode não fechar com reviewers_total."
          },
          "response": [
            {
              "name": "200 — post em revisão",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts/30",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts",
                    "30"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"data\": {\n    \"id\": 30,\n    \"asset_group_id\": 71,\n    \"project\": {\n      \"id\": 1,\n      \"name\": \"Projeto LEONEL\",\n      \"timezone\": \"America/Sao_Paulo\"\n    },\n    \"network\": \"instagram_business\",\n    \"network_group\": \"instagram\",\n    \"account\": {\n      \"id\": \"17841404295825681\",\n      \"name\": \"reportei\"\n    },\n    \"type\": \"feed\",\n    \"status\": \"in_review\",\n    \"review_status\": \"pending\",\n    \"caption\": \"\",\n    \"first_comment\": null,\n    \"schedule_at\": null,\n    \"published_url\": null,\n    \"media\": [],\n    \"created_at\": \"2025-06-21T20:11:58-03:00\",\n    \"updated_at\": \"2025-12-11T06:42:06-03:00\",\n    \"review\": {\n      \"status\": \"pending\",\n      \"cycle_started_at\": \"2026-09-05T09:00:00-03:00\",\n      \"reviewers_total\": 3,\n      \"decided\": 0,\n      \"approved\": 0,\n      \"request_changes\": 0,\n      \"pending\": 3\n    }\n  }\n}"
            }
          ]
        },
        {
          "name": "Consultar um grupo de conteúdo",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts/group/{{assetGroupId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts",
                "group",
                "{{assetGroupId}}"
              ]
            },
            "description": "A mesma peça publicada em várias redes: cada rede é um post e todos carregam o mesmo asset_group_id.\n\nDevolve o resumo do lote — contagem, redes, contas, divisão por status e datas de agendamento — e os posts resumidos.\n\nVem inteiro, sem paginação. Legenda, mídias e o bloco review continuam em GET /posts/{id}.\n\nGrupo inexistente, sem posts ou de outra conta → 404."
          },
          "response": [
            {
              "name": "200 — grupo de conteúdo",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts/group/{{assetGroupId}}",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts",
                    "group",
                    "{{assetGroupId}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": {\n    \"id\": 71,\n    \"project\": {\n      \"id\": 1,\n      \"name\": \"Projeto LEONEL\",\n      \"timezone\": \"America/Sao_Paulo\"\n    },\n    \"review_group_id\": 419,\n    \"posts_count\": 3,\n    \"networks\": [\n      \"instagram\",\n      \"facebook\"\n    ],\n    \"accounts\": [\n      {\n        \"id\": \"17841404295825681\",\n        \"name\": \"reportei\"\n      },\n      {\n        \"id\": \"9654176157967125\",\n        \"name\": \"Reportei\"\n      }\n    ],\n    \"status_summary\": {\n      \"scheduled\": 1,\n      \"published\": 2\n    },\n    \"schedule_dates\": [\n      \"2025-07-10T09:41:58-03:00\",\n      \"2025-07-11T18:00:00-03:00\"\n    ],\n    \"posts\": [\n      {\n        \"id\": 94,\n        \"asset_group_id\": 71,\n        \"network\": \"instagram\",\n        \"type\": \"feed\",\n        \"status\": \"published\",\n        \"review_status\": null,\n        \"schedule_at\": \"2025-07-10T09:41:58-03:00\",\n        \"thumbnail\": \"https://s3-medias.reportei.com/flux-upload/...\"\n      },\n      {\n        \"id\": 95,\n        \"asset_group_id\": 71,\n        \"network\": \"facebook\",\n        \"type\": \"feed\",\n        \"status\": \"scheduled\",\n        \"review_status\": null,\n        \"schedule_at\": \"2025-07-11T18:00:00-03:00\",\n        \"thumbnail\": \"https://s3-medias.reportei.com/flux-upload/...\"\n      }\n    ]\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Contas conectadas",
      "description": "Escopo exigido: `integrations:read`\n\nÉ o endpoint que permite detectar conta expirada antes de a publicação falhar.",
      "item": [
        {
          "name": "Listar contas conectadas",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/integrations?per_page=15",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "integrations"
              ],
              "query": [
                {
                  "key": "per_page",
                  "value": "15",
                  "description": "1 a 50. Padrão 15."
                },
                {
                  "key": "page",
                  "value": "1",
                  "disabled": true
                },
                {
                  "key": "project_id",
                  "value": "{{projectId}}",
                  "disabled": true,
                  "description": "Restringe a um projeto. Id de outra conta → 404."
                },
                {
                  "key": "network",
                  "value": "facebook",
                  "disabled": true,
                  "description": "instagram, instagram_business, facebook, threads, x, youtube, linkedin, linkedin_personal, tiktok, pinterest, google_my_business. Aceita network=x e network[]=x."
                },
                {
                  "key": "status",
                  "value": "expired",
                  "disabled": true,
                  "description": "active, expired ou deleted. O filtro sempre concorda com o status do corpo."
                }
              ]
            },
            "description": "Contas de rede social conectadas aos projetos da conta.\n\nConta desconectada continua aparecendo, com status 'deleted': posts publicados por ela seguem apontando para esse registro.\n\nReconexão da mesma conta no mesmo projeto faz o registro expirado voltar a responder 'active' — e sair de ?status=expired."
          },
          "response": [
            {
              "name": "200 — listagem",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/integrations?per_page=1",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "integrations"
                  ],
                  "query": [
                    {
                      "key": "per_page",
                      "value": "1"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": 4,\n      \"project\": {\n        \"id\": 1,\n        \"name\": \"Projeto LEONEL\"\n      },\n      \"network\": \"facebook\",\n      \"network_group\": \"facebook\",\n      \"account\": {\n        \"id\": \"464923206912427\",\n        \"name\": \"Excursão Floripa Grêmio\"\n      },\n      \"status\": \"active\",\n      \"last_verified_at\": \"2025-06-09T14:08:31-03:00\",\n      \"created_at\": \"2025-06-09T14:08:28-03:00\"\n    }\n  ],\n  \"links\": {\n    \"first\": null,\n    \"last\": null,\n    \"prev\": null,\n    \"next\": null\n  },\n  \"meta\": {\n    \"current_page\": 1,\n    \"from\": 1,\n    \"last_page\": 1,\n    \"per_page\": 1,\n    \"to\": 1,\n    \"total\": 1\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Aprovações",
      "description": "Escopo exigido: `reviews:read`\n\nPendente é ausência de decisão: reviews.status só assume approved ou request_changes. Pedido de mudança tem precedência. Reenvio abre um ciclo novo (cycle_started_at) e decisões anteriores saem do agregado, mas ficam no histórico.",
      "item": [
        {
          "name": "Decisões de aprovação de um post",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts/{{postId}}/reviews?per_page=15",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts",
                "{{postId}}",
                "reviews"
              ],
              "query": [
                {
                  "key": "per_page",
                  "value": "15",
                  "description": "1 a 50. Padrão 15."
                },
                {
                  "key": "page",
                  "value": "1",
                  "disabled": true
                }
              ]
            },
            "description": "Histórico das decisões do post, em ordem cronológica. É auditoria: decisão anulada aparece com is_invalidated=true, não desaparece.\n\nDo revisor saem apenas nome e e-mail.\n\nPost inexistente, excluído ou de outra conta → 404."
          },
          "response": [
            {
              "name": "200 — histórico",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts/84/reviews?per_page=1",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts",
                    "84",
                    "reviews"
                  ],
                  "query": [
                    {
                      "key": "per_page",
                      "value": "1"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": 55021,\n      \"reviewer\": {\n        \"name\": \"Marina Alencar\",\n        \"email\": \"marina@cliente.com\"\n      },\n      \"status\": \"request_changes\",\n      \"reasons\": [\n        \"texto\",\n        \"imagem\"\n      ],\n      \"comments\": \"Trocar a foto: a vitrine está vazia.\",\n      \"is_invalidated\": false,\n      \"decided_at\": \"2026-09-09T15:03:22-03:00\",\n      \"created_at\": \"2026-09-09T15:03:22-03:00\"\n    }\n  ],\n  \"links\": {\n    \"first\": null,\n    \"last\": null,\n    \"prev\": null,\n    \"next\": null\n  },\n  \"meta\": {\n    \"current_page\": 1,\n    \"from\": 1,\n    \"last_page\": 1,\n    \"per_page\": 1,\n    \"to\": 1,\n    \"total\": 1\n  }\n}"
            }
          ]
        },
        {
          "name": "Listar grupos de aprovação",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/review-groups?per_page=15",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "review-groups"
              ],
              "query": [
                {
                  "key": "per_page",
                  "value": "15",
                  "description": "1 a 50. Padrão 15."
                },
                {
                  "key": "page",
                  "value": "1",
                  "disabled": true
                },
                {
                  "key": "project_id",
                  "value": "{{projectId}}",
                  "disabled": true,
                  "description": "Restringe a um projeto. Id de outra conta → 404."
                }
              ]
            },
            "description": "Pacotes de posts enviados de uma vez ao cliente, os mais recentes primeiro.\n\nreview_summary cobre só os posts ainda em revisão, então a soma das três chaves pode ser menor que posts_count: um post aprovado e depois agendado saiu da fila de aprovação."
          },
          "response": [
            {
              "name": "200 — listagem",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/review-groups?per_page=1",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "review-groups"
                  ],
                  "query": [
                    {
                      "key": "per_page",
                      "value": "1"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": 419,\n      \"uuid\": \"8e8513bc-7505-4963-b0af-3651be6a3e07\",\n      \"project\": {\n        \"id\": 1,\n        \"name\": \"Projeto LEONEL\"\n      },\n      \"name\": \"NOVO GRUPO DE TESTE\",\n      \"posts_count\": 4,\n      \"review_summary\": {\n        \"approved\": 3,\n        \"request_changes\": 0,\n        \"pending\": 0\n      },\n      \"reviewers_count\": 2,\n      \"created_at\": \"2026-05-12T11:23:36-03:00\"\n    }\n  ],\n  \"links\": {\n    \"first\": null,\n    \"last\": null,\n    \"prev\": null,\n    \"next\": null\n  },\n  \"meta\": {\n    \"current_page\": 1,\n    \"from\": 1,\n    \"last_page\": 1,\n    \"per_page\": 1,\n    \"to\": 1,\n    \"total\": 1\n  }\n}"
            }
          ]
        },
        {
          "name": "Consultar um grupo de aprovação",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/review-groups/{{reviewGroupId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "review-groups",
                "{{reviewGroupId}}"
              ]
            },
            "description": "O grupo com todos os posts do pacote, na ordem em que o cliente os vê na tela de aprovação.\n\nO grupo vem inteiro, sem paginação: um grupo é fechado quando é enviado ao cliente.\n\nO post vem resumido — legenda, mídias e o bloco review continuam em GET /posts/{id}. O thumbnail é temporário e expira em 48 horas.\n\nGrupo inexistente, excluído ou de outra conta → 404."
          },
          "response": [
            {
              "name": "200 — grupo com os posts",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/review-groups/{{reviewGroupId}}",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "review-groups",
                    "{{reviewGroupId}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": {\n    \"id\": 419,\n    \"uuid\": \"8e8513bc-7505-4963-b0af-3651be6a3e07\",\n    \"project\": {\n      \"id\": 1,\n      \"name\": \"Projeto LEONEL\"\n    },\n    \"name\": \"NOVO GRUPO DE TESTE\",\n    \"posts_count\": 4,\n    \"review_summary\": {\n      \"approved\": 3,\n      \"request_changes\": 0,\n      \"pending\": 0\n    },\n    \"reviewers_count\": 2,\n    \"created_at\": \"2026-05-12T11:23:36-03:00\",\n    \"posts\": [\n      {\n        \"id\": 8811,\n        \"asset_group_id\": 71,\n        \"network\": \"instagram\",\n        \"type\": \"feed\",\n        \"status\": \"in_review\",\n        \"review_status\": \"approved\",\n        \"schedule_at\": \"2026-05-20T09:00:00-03:00\",\n        \"thumbnail\": \"https://midias.reportei.com/...\"\n      },\n      {\n        \"id\": 8812,\n        \"asset_group_id\": 72,\n        \"network\": \"facebook\",\n        \"type\": \"feed\",\n        \"status\": \"scheduled\",\n        \"review_status\": null,\n        \"schedule_at\": \"2026-05-21T09:00:00-03:00\",\n        \"thumbnail\": null\n      }\n    ]\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Casos de erro",
      "description": "Requisições que reproduzem cada código do envelope de erro.\n\nTodo erro sai como `{\"error\": {type, message, details?, request_id}}`. Trate o `type`, que é estável — a `message` é texto para humanos e pode mudar entre versões.\n\nO `request_id` também vem no header `X-Request-Id`: informe-o ao suporte ao relatar um problema.",
      "item": [
        {
          "name": "401 — token inválido",
          "request": {
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "flux_invalido000000000000000000000000000000000000000",
                  "type": "string"
                }
              ]
            },
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts"
              ]
            },
            "description": "Por segurança o 401 é idêntico para token ausente, inexistente, expirado e revogado — a API não confirma se um token existe."
          },
          "response": [
            {
              "name": "401",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts"
                  ]
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"error\": {\n    \"type\": \"unauthorized\",\n    \"message\": \"Token de acesso ausente ou inválido.\",\n    \"request_id\": \"01M1EGMBJ7JED66J067A9CBZF2\"\n  }\n}"
            }
          ]
        },
        {
          "name": "403 — escopo insuficiente",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts"
              ]
            },
            "description": "Usa `{{tokenProjectsOnly}}` — um token emitido apenas com o escopo `projects:read`, que por isso não alcança os endpoints de posts.\n\nPara preencher a variável, emita em **Configurações → Tokens de API** um segundo token marcando apenas o escopo `projects:read`.\n\nO `details.required_scope` da resposta diz qual escopo falta.",
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{tokenProjectsOnly}}",
                  "type": "string"
                }
              ]
            }
          },
          "response": [
            {
              "name": "403",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts"
                  ]
                }
              },
              "status": "Forbidden",
              "code": 403,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"error\": {\n    \"type\": \"insufficient_scope\",\n    \"message\": \"Este token não possui o escopo necessário para esta operação.\",\n    \"details\": {\n      \"required_scope\": \"posts:read\"\n    },\n    \"request_id\": \"01M1EGN1165BP5NP8Z5B2X7M79\"\n  }\n}"
            }
          ]
        },
        {
          "name": "404 — recurso inexistente",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts/99999999",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts",
                "99999999"
              ]
            },
            "description": "Recurso inexistente, excluído, de outra conta ou de projeto fora do alcance do token — o mesmo 404 em todos os casos, para não revelar a existência de dados que o token não pode ler.\n\nO caso de projeto fora do alcance tem requisição própria na pasta \"Vínculo de projeto\"."
          },
          "response": [
            {
              "name": "404",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts/99999999",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts",
                    "99999999"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"error\": {\n    \"type\": \"not_found\",\n    \"message\": \"Recurso não encontrado.\",\n    \"request_id\": \"01M1EGMBPV0Q361CWZKH74W5X9\"\n  }\n}"
            }
          ]
        },
        {
          "name": "422 — parâmetro inválido",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/posts?network=tiktokk&per_page=999",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "posts"
              ],
              "query": [
                {
                  "key": "network",
                  "value": "tiktokk",
                  "description": "Rede inexistente"
                },
                {
                  "key": "per_page",
                  "value": "999",
                  "description": "Acima do máximo de 50"
                }
              ]
            },
            "description": "Filtro com valor inválido responde 422 com os campos rejeitados em `details` — a API não devolve lista vazia silenciosa."
          },
          "response": [
            {
              "name": "422",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/posts?network=tiktokk",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "posts"
                  ],
                  "query": [
                    {
                      "key": "network",
                      "value": "tiktokk"
                    }
                  ]
                }
              },
              "status": "Unprocessable Content",
              "code": 422,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"error\": {\n    \"type\": \"invalid_request\",\n    \"message\": \"Os parâmetros enviados são inválidos.\",\n    \"details\": {\n      \"network.0\": [\n        \"The selected network.0 is invalid.\"\n      ]\n    },\n    \"request_id\": \"01M1EGMC1DFAZ2TXZ1B5707WTA\"\n  }\n}"
            }
          ]
        },
        {
          "name": "429 — rate limit (120/min)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/v1/projects",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "v1",
                "projects"
              ]
            },
            "description": "O limite é de 120 requisições por minuto por token. Para reproduzir, rode esta requisição 121 vezes no mesmo minuto (Postman: Run > Iterations 121).\n\nA resposta traz o header `Retry-After` com quantos segundos aguardar — respeite-o em vez de tentar de novo imediatamente."
          },
          "response": [
            {
              "name": "429",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/api/v1/projects",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "api",
                    "v1",
                    "projects"
                  ]
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Retry-After",
                  "value": "37"
                }
              ],
              "body": "{\n  \"error\": {\n    \"type\": \"rate_limit_exceeded\",\n    \"message\": \"Limite de 120 requisições por minuto excedido.\",\n    \"request_id\": \"01M1EGP4Q2R7T8V9W0X1Y2Z3A4\"\n  }\n}"
            }
          ]
        }
      ]
    }
  ]
}