{
  "info": {
    "_postman_id": "b6f3c2a1-4d5e-4f60-8a7b-9c0d1e2f3a4b",
    "name": "CardSign API v1",
    "description": "Coleção oficial da API v1 do CardSign — gerada de `openapi/cardsign-v1.yaml`.\n\n**Como usar**\n1. Importe esta coleção e um ambiente (`CardSign-Sandbox` ou `CardSign-Producao`).\n2. No ambiente, preencha `api_key` (Configurações › API do CardSign), `email_signatario` (seu e-mail) e, se quiser, `empresa_id` e `webhook_url`.\n3. Rode **00 Autorização › Quem sou eu** e depois as pastas na ordem (ou tudo pelo Runner).\n\nTodo `POST` recebe uma `Idempotency-Key` nova automaticamente (script da coleção), a menos que a requisição já defina uma.\nDocumentação: https://cardsign.gopixeltecnologiaa.com.br/docs/api",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Idempotency-Key em todo POST que ainda não tem uma (a mesma chave + o mesmo corpo em 24 h devolve a mesma resposta).",
          "if (pm.request.method === \"POST\" && !pm.request.headers.has(\"Idempotency-Key\")) {",
          "  pm.request.headers.add({ key: \"Idempotency-Key\", value: pm.variables.replaceIn(\"{{$guid}}\") });",
          "}"
        ]
      }
    },
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Toda resposta de erro segue o formato {\"erro\": {\"codigo\", \"mensagem\", \"detalhes\"?}}.",
          "if (pm.response.code >= 400) {",
          "  pm.test(\"Erro no formato do CardSign\", () => {",
          "    const e = pm.response.json().erro;",
          "    pm.expect(e.codigo).to.be.a(\"string\");",
          "    pm.expect(e.mensagem).to.be.a(\"string\");",
          "  });",
          "}",
          "pm.test(\"Respondeu em menos de 15 s\", () => pm.expect(pm.response.responseTime).to.be.below(15000));"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "envelope_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "arquivo_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "signatario_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "signatario2_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "observador_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "external_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "prazo",
      "value": "",
      "type": "string"
    },
    {
      "key": "grupo_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "link_assinatura",
      "value": "",
      "type": "string"
    },
    {
      "key": "poll_tentativas",
      "value": "0",
      "type": "string"
    },
    {
      "key": "proximo",
      "value": "",
      "type": "string"
    },
    {
      "key": "webhook_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "entrega_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "idem_conflito",
      "value": "",
      "type": "string"
    },
    {
      "key": "pdf_base64",
      "value": "JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFszIDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAyIDAgUiAvTWVkaWFCb3ggWzAgMCA1OTUgODQyXSAvUmVzb3VyY2VzIDw8IC9Gb250IDw8IC9GMSA1IDAgUiA+PiA+PiAvQ29udGVudHMgNCAwIFIgPj4KZW5kb2JqCjQgMCBvYmoKPDwgL0xlbmd0aCAxNTYgPj4Kc3RyZWFtCkJUIC9GMSAxNCBUZiA3MiA3NzAgVGQgKFRlcm1vIGRlIGNpZW5jaWEgLSBQT1AgMDE0IEhpZ2llbml6YWNhbyBkYXMgbWFvcykgVGogMCAtMjQgVGQgL0YxIDEwIFRmIChDbGluaWNhIEV4ZW1wbG8gLSBkb2N1bWVudG8gZGUgdGVzdGUgZGEgQVBJIENhcmRTaWduKSBUaiBFVAplbmRzdHJlYW0KZW5kb2JqCjUgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1R5cGUxIC9CYXNlRm9udCAvSGVsdmV0aWNhID4+CmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1OCAwMDAwMCBuIAowMDAwMDAwMTE1IDAwMDAwIG4gCjAwMDAwMDAyNDEgMDAwMDAgbiAKMDAwMDAwMDQ0OCAwMDAwMCBuIAp0cmFpbGVyCjw8IC9TaXplIDYgL1Jvb3QgMSAwIFIgPj4Kc3RhcnR4cmVmCjUxOAolJUVPRgo=",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "00 Autorização",
      "description": "Confere a chave e descobre as empresas. Rode **Quem sou eu** primeiro: se `empresa_id` do ambiente estiver vazio, ele é preenchido com a primeira empresa da chave.",
      "item": [
        {
          "name": "Índice da API",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Lista as rotas\", () => pm.expect(j.rotas).to.be.an(\"array\").that.is.not.empty);"
                ]
              }
            }
          ],
          "request": {
            "auth": {
              "type": "noauth"
            },
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/",
              "host": [
                "{{base_url}}"
              ],
              "path": []
            },
            "description": "`GET /api/v1` — rotas, paginação e regras de escrita. Não exige chave."
          },
          "response": []
        },
        {
          "name": "Quem sou eu",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Traz chave, grupo e empresas\", () => {",
                  "  pm.expect(j.chave.escopos).to.be.an(\"array\");",
                  "  pm.expect(j.empresas).to.be.an(\"array\");",
                  "  pm.expect(j.limite_por_minuto).to.eql(120);",
                  "});",
                  "if (!pm.variables.get(\"empresa_id\") && j.empresas && j.empresas[0]) {",
                  "  if (pm.environment.name) pm.environment.set(\"empresa_id\", j.empresas[0].id);",
                  "  else pm.collectionVariables.set(\"empresa_id\", j.empresas[0].id);",
                  "}",
                  "if (j.grupo && j.grupo.id) pm.collectionVariables.set(\"grupo_id\", j.grupo && j.grupo.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/eu",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "eu"
              ]
            },
            "description": "`GET /eu` — a chave (escopos, validade), o grupo, as empresas em que ela age e o limite por minuto."
          },
          "response": []
        },
        {
          "name": "Empresas da chave",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Lista de empresas\", () => pm.expect(j.empresas).to.be.an(\"array\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/empresas",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "empresas"
              ]
            },
            "description": "`GET /empresas` — as empresas do grupo em que a chave age."
          },
          "response": []
        }
      ]
    },
    {
      "name": "01 Fluxo completo",
      "description": "Do rascunho ao envio, na ordem. Rode a pasta inteira no **Runner** (o passo 10 repete sozinho até o documento sair de `andamento`, no máximo 12 vezes, a cada 10 s).\n\nAntes: preencha `email_signatario` no ambiente com o **seu** e-mail — os convites de teste vão para ele.\nO PDF vai em base64 a partir da variável de coleção `pdf_base64` (um PDF mínimo válido de 1 página).",
      "item": [
        {
          "name": "1. Criar envelope (JSON + base64)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.collectionVariables.set(\"external_id\", \"postman:pop:\" + Date.now());",
                  "const d = new Date(Date.now() + 7 * 86400000);",
                  "pm.collectionVariables.set(\"prazo\", d.toISOString().slice(0, 10));",
                  "pm.collectionVariables.set(\"poll_tentativas\", \"0\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 201\", () => pm.response.to.have.status(201));",
                  "const j = pm.response.json();",
                  "pm.test(\"Formato Envelope\", () => {",
                  "  pm.expect(j).to.include.keys(\"id\", \"titulo\", \"status\", \"empresa_id\", \"arquivos\", \"signatarios\", \"pdfs_finais\");",
                  "  pm.expect(j.signatarios).to.be.an(\"array\");",
                  "});",
                  "pm.test(\"Nasce como rascunho, vindo da API\", () => {",
                  "  pm.expect(j.status).to.eql(\"rascunho\");",
                  "  pm.expect(j.origem).to.eql(\"api\");",
                  "  pm.expect(j.arquivos).to.have.lengthOf(1);",
                  "  pm.expect(j.arquivos[0].sha256).to.match(/^[0-9a-f]{64}$/);",
                  "});",
                  "if (j.id) pm.collectionVariables.set(\"envelope_id\", j.id);",
                  "if (j.arquivos && j.arquivos[0] && j.arquivos[0].id) pm.collectionVariables.set(\"arquivo_id\", j.arquivos && j.arquivos[0] && j.arquivos[0].id);",
                  "if (j.signatarios && j.signatarios[0] && j.signatarios[0].id) pm.collectionVariables.set(\"signatario_id\", j.signatarios && j.signatarios[0] && j.signatarios[0].id);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"empresa_id\": \"{{empresa_id}}\",\n  \"titulo\": \"POP 014 — Higienização das mãos (teste Postman)\",\n  \"external_id\": \"{{external_id}}\",\n  \"external_ref\": { \"origem\": \"postman\", \"pop\": \"014\" },\n  \"prazo\": \"{{prazo}}\",\n  \"mensagem\": \"Teste da API do CardSign pelo Postman.\",\n  \"arquivos\": [{ \"nome\": \"POP-014-teste.pdf\", \"base64\": \"{{pdf_base64}}\" }],\n  \"signatarios\": [\n    {\n      \"nome\": \"Mariana Costa Ribeiro\",\n      \"email\": \"{{email_signatario}}\",\n      \"canal\": \"email\",\n      \"nivel\": \"avancada\",\n      \"campos\": [{ \"tipo\": \"assinatura\", \"pagina\": 1, \"x\": 10, \"y\": 80, \"largura\": 26, \"altura\": 7 }]\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes"
              ]
            },
            "description": "`POST /envelopes` — cria o rascunho completo: arquivo em base64, uma pessoa com campo de assinatura por posição. `external_id` novo a cada execução."
          },
          "response": []
        },
        {
          "name": "2. Editar rascunho",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Título novo\", () => pm.expect(j.titulo).to.include(\"rev. 2\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"titulo\": \"POP 014 — Higienização das mãos (teste Postman, rev. 2)\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}"
              ]
            },
            "description": "`PATCH /envelopes/{id}` — muda título, prazo ou mensagem (só no rascunho)."
          },
          "response": []
        },
        {
          "name": "3. Adicionar arquivo (base64)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 201\", () => pm.response.to.have.status(201));",
                  "const j = pm.response.json();",
                  "pm.test(\"Arquivo com SHA-256 e páginas\", () => {",
                  "  pm.expect(j.sha256).to.match(/^[0-9a-f]{64}$/);",
                  "  pm.expect(j.paginas).to.eql(1);",
                  "  pm.expect(j.ordem).to.eql(2);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{ \"nome\": \"Anexo-I-checklist.pdf\", \"base64\": \"{{pdf_base64}}\" }",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/arquivos",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "arquivos"
              ]
            },
            "description": "`POST /envelopes/{id}/arquivos` — um PDF por chamada (`{nome, url}`, `{nome, base64}` ou multipart `arquivo`)."
          },
          "response": []
        },
        {
          "name": "4. Adicionar signatário (testemunha)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 201\", () => pm.response.to.have.status(201));",
                  "const j = pm.response.json();",
                  "pm.test(\"Pessoa criada, contato mascarado\", () => {",
                  "  pm.expect(j.id).to.be.a(\"string\");",
                  "  pm.expect(j.funcao).to.eql(\"testemunha\");",
                  "  pm.expect(j.email_mascarado || \"\").to.include(\"***@\");",
                  "});",
                  "if (j.id) pm.collectionVariables.set(\"signatario2_id\", j.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"nome\": \"Rafael Almeida Pinto\",\n  \"funcao\": \"testemunha\",\n  \"email\": \"{{email_signatario}}\",\n  \"canal\": \"email\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/signatarios",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "signatarios"
              ]
            },
            "description": "`POST /envelopes/{id}/signatarios` — sem `campos`: o CardSign põe uma caixa de assinatura automática na última página."
          },
          "response": []
        },
        {
          "name": "5. Adicionar observador",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 201\", () => pm.response.to.have.status(201));",
                  "const j = pm.response.json();",
                  "if (j.id) pm.collectionVariables.set(\"observador_id\", j.id);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"nome\": \"Juliana Ferreira Lopes\",\n  \"funcao\": \"observador\",\n  \"canal\": \"email\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/signatarios",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "signatarios"
              ]
            },
            "description": "Uma pessoa a mais, só para mostrar a remoção no passo seguinte."
          },
          "response": []
        },
        {
          "name": "6. Remover observador",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 204\", () => pm.response.to.have.status(204));"
                ]
              }
            }
          ],
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/signatarios/{{observador_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "signatarios",
                "{{observador_id}}"
              ]
            },
            "description": "`DELETE /envelopes/{id}/signatarios/{sid}` — só no rascunho. 204 sem corpo."
          },
          "response": []
        },
        {
          "name": "7. Enviar (com devolver_links)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Formato Envelope\", () => {",
                  "  pm.expect(j).to.include.keys(\"id\", \"titulo\", \"status\", \"empresa_id\", \"arquivos\", \"signatarios\", \"pdfs_finais\");",
                  "  pm.expect(j.signatarios).to.be.an(\"array\");",
                  "});",
                  "pm.test(\"Em andamento\", () => pm.expect(j.status).to.eql(\"andamento\"));",
                  "if (Array.isArray(j.links) && j.links[0]) {",
                  "  pm.collectionVariables.set(\"link_assinatura\", j.links[0].url);",
                  "  pm.test(\"Links de assinatura\", () => pm.expect(j.links[0]).to.include.keys(\"signatario_id\", \"url\"));",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"devolver_links\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/enviar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "enviar"
              ]
            },
            "description": "`POST /envelopes/{id}/enviar` — as conferências do painel e os convites. Com `devolver_links` e o escopo `envelopes:gerir`, a resposta traz os links de assinatura de quem está na vez."
          },
          "response": []
        },
        {
          "name": "8. Repetir o envio (mesma Idempotency-Key)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200 ou 409\", () => pm.expect(pm.response.code).to.be.oneOf([200, 409]));",
                  "if (pm.response.code === 200) pm.test(\"Primeira resposta ou repetição guardada\", () => pm.expect(pm.response.json().status).to.eql(\"andamento\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "postman-enviar-{{envelope_id}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"devolver_links\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/enviar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "enviar"
              ]
            },
            "description": "A mesma `Idempotency-Key` com o mesmo corpo devolve a resposta guardada (status original e `idempotent-replayed: true`), sem enviar de novo."
          },
          "response": []
        },
        {
          "name": "9. Consultar envelope",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Formato Envelope\", () => {",
                  "  pm.expect(j).to.include.keys(\"id\", \"titulo\", \"status\", \"empresa_id\", \"arquivos\", \"signatarios\", \"pdfs_finais\");",
                  "  pm.expect(j.signatarios).to.be.an(\"array\");",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}"
              ]
            },
            "description": "`GET /envelopes/{id}` — o envelope completo."
          },
          "response": []
        },
        {
          "name": "10. Acompanhar até concluir (poll)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const n = Number(pm.collectionVariables.get(\"poll_tentativas\") || 0);",
                  "if (n > 0) setTimeout(() => {}, 10000);"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "const n = Number(pm.collectionVariables.get(\"poll_tentativas\") || 0) + 1;",
                  "pm.collectionVariables.set(\"poll_tentativas\", String(n));",
                  "pm.test(\"Situação válida\", () =>",
                  "  pm.expect(j.status).to.be.oneOf([\"andamento\", \"pausado\", \"concluido\", \"cancelado\", \"expirado\", \"recusado\"]));",
                  "const proximo = j.status === \"andamento\" && n < 12 ? pm.info.requestName : null;",
                  "if (proximo) (pm.execution && pm.execution.setNextRequest ? pm.execution.setNextRequest(proximo) : postman.setNextRequest(proximo));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}"
              ]
            },
            "description": "No Runner, repete a cada 10 s (até 12 vezes) enquanto o envelope está em `andamento`. Em produção, prefira os **webhooks**: o `envelope.concluido` chega sozinho."
          },
          "response": []
        }
      ]
    },
    {
      "name": "02 Ações",
      "description": "Mudanças de situação do envelope de `envelope_id` (rode depois do **01 Fluxo completo**). Cancelar é definitivo, por isso vem por último.",
      "item": [
        {
          "name": "Pausar",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Pausado\", () => pm.expect(j.status).to.eql(\"pausado\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/pausar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "pausar"
              ]
            },
            "description": "`POST /envelopes/{id}/pausar` — suspende as assinaturas."
          },
          "response": []
        },
        {
          "name": "Retomar",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Em andamento\", () => pm.expect(j.status).to.eql(\"andamento\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/retomar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "retomar"
              ]
            },
            "description": "`POST /envelopes/{id}/retomar` — volta para `andamento`."
          },
          "response": []
        },
        {
          "name": "Lembrete",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Quantos saíram\", () => pm.expect(j.enviados).to.be.a(\"number\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{ \"signatario_id\": \"{{signatario_id}}\" }",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/lembrete",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "lembrete"
              ]
            },
            "description": "`POST /envelopes/{id}/lembrete` — link novo e convite de novo para quem está na vez (ou só `signatario_id`)."
          },
          "response": []
        },
        {
          "name": "Cancelar",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Cancelado com motivo\", () => {",
                  "  pm.expect(j.status).to.eql(\"cancelado\");",
                  "  pm.expect(j.motivo_cancelamento).to.include(\"Postman\");",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"motivo\": \"Teste da API pelo Postman: cancelado de propósito.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/cancelar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "cancelar"
              ]
            },
            "description": "`POST /envelopes/{id}/cancelar` — exige `motivo` (5 a 500 caracteres)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "03 Consultas",
      "description": "Listas paginadas (cursor), busca por `external_id`, trilha, PDF final e provas. PDF e provas respondem `409 nao_concluido` enquanto o documento não foi concluído — os testes aceitam os dois.",
      "item": [
        {
          "name": "Listar envelopes (cursor)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Página com cursor\", () => {",
                  "  pm.expect(j.envelopes).to.be.an(\"array\");",
                  "  pm.expect(j).to.have.property(\"proximo\");",
                  "  pm.expect(j.limite).to.eql(2);",
                  "});",
                  "pm.collectionVariables.set(\"proximo\", j.proximo || \"\");"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes?limite=2",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes"
              ],
              "query": [
                {
                  "key": "limite",
                  "value": "2"
                }
              ]
            },
            "description": "`GET /envelopes` — mais recentes primeiro. Guarda `proximo` para a página seguinte."
          },
          "response": []
        },
        {
          "name": "Listar envelopes (próxima página)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.collectionVariables.get(\"proximo\")) {",
                  "  pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "  pm.test(\"Sem total nas páginas seguintes\", () => pm.expect(pm.response.json().total).to.eql(null));",
                  "} else {",
                  "  pm.test(\"Sem próxima página: cursor vazio é recusado\", () => pm.response.to.have.status(400));",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes?limite=2&depois={{proximo}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes"
              ],
              "query": [
                {
                  "key": "limite",
                  "value": "2"
                },
                {
                  "key": "depois",
                  "value": "{{proximo}}"
                }
              ]
            },
            "description": "Segue o cursor `depois={{proximo}}`. `proximo: null` = acabou (sem `proximo`, o CardSign responde `400 cursor_invalido`)."
          },
          "response": []
        },
        {
          "name": "Buscar por external_id",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Achou o envelope do fluxo\", () => {",
                  "  pm.expect(j.envelopes.map((e) => e.id)).to.include(pm.collectionVariables.get(\"envelope_id\"));",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes?external_id={{external_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes"
              ],
              "query": [
                {
                  "key": "external_id",
                  "value": "{{external_id}}"
                }
              ]
            },
            "description": "`GET /envelopes?external_id=…` — acha o envelope pelo seu identificador."
          },
          "response": []
        },
        {
          "name": "Consultar documento (formato de leitura)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Com empresa e pessoas\", () => pm.expect(j).to.include.keys(\"empresa\", \"signatarios\", \"pdfs_finais\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/documentos/{{envelope_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "documentos",
                "{{envelope_id}}"
              ]
            },
            "description": "`GET /documentos/{id}` — o detalhe da API de leitura."
          },
          "response": []
        },
        {
          "name": "Listar documentos",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Lista\", () => pm.expect(j.documentos).to.be.an(\"array\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/documentos?limite=10",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "documentos"
              ],
              "query": [
                {
                  "key": "limite",
                  "value": "10"
                },
                {
                  "key": "status",
                  "value": "concluido",
                  "disabled": true
                }
              ]
            },
            "description": "`GET /documentos` — a lista da API de leitura (sem rascunhos)."
          },
          "response": []
        },
        {
          "name": "Trilha do envelope",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Trilha íntegra\", () => {",
                  "  pm.expect(j.eventos).to.be.an(\"array\").that.is.not.empty;",
                  "  pm.expect(j.integra).to.not.eql(false);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/trilha",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "trilha"
              ]
            },
            "description": "`GET /envelopes/{id}/trilha` — eventos encadeados por hash e se a cadeia está íntegra."
          },
          "response": []
        },
        {
          "name": "Trilha do documento",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Total\", () => pm.expect(j.total).to.eql(j.eventos.length));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/documentos/{{envelope_id}}/trilha",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "documentos",
                "{{envelope_id}}",
                "trilha"
              ]
            },
            "description": "`GET /documentos/{id}/trilha` — a mesma trilha pela rota de leitura."
          },
          "response": []
        },
        {
          "name": "PDF final do envelope",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200 ou 409\", () => pm.expect(pm.response.code).to.be.oneOf([200, 409]));",
                  "if (pm.response.code === 200) pm.test(\"Links com SHA-256\", () => pm.expect(pm.response.json().arquivos).to.be.an(\"array\"));",
                  "else pm.test(\"Ainda não concluído\", () => pm.expect(pm.response.json().erro.codigo).to.eql(\"nao_concluido\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/pdf",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "pdf"
              ]
            },
            "description": "`GET /envelopes/{id}/pdf` — links de 5 minutos para o PDF final selado."
          },
          "response": []
        },
        {
          "name": "PDF final do documento",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200 ou 409\", () => pm.expect(pm.response.code).to.be.oneOf([200, 409]));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/documentos/{{envelope_id}}/pdf",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "documentos",
                "{{envelope_id}}",
                "pdf"
              ]
            },
            "description": "`GET /documentos/{id}/pdf` — o mesmo pela rota de leitura."
          },
          "response": []
        },
        {
          "name": "Pacote de provas",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200 ou 409\", () => pm.expect(pm.response.code).to.be.oneOf([200, 409]));",
                  "if (pm.response.code === 200) pm.test(\"ZIP com link\", () => pm.expect(pm.response.json().arquivo.nome).to.match(/\\.zip$/));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/provas",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "provas"
              ]
            },
            "description": "`GET /envelopes/{id}/provas` — ZIP com PDF final, originais, carimbo do tempo, assinaturas e trilha."
          },
          "response": []
        },
        {
          "name": "Modelos",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200 ou 403\", () => pm.expect(pm.response.code).to.be.oneOf([200, 403]));",
                  "if (pm.response.code === 200) pm.test(\"Lista\", () => pm.expect(pm.response.json().modelos).to.be.an(\"array\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/modelos",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "modelos"
              ]
            },
            "description": "`GET /modelos` — modelos de documento (escopo `modelos:ler`)."
          },
          "response": []
        },
        {
          "name": "Pastas",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200 ou 403\", () => pm.expect(pm.response.code).to.be.oneOf([200, 403]));",
                  "if (pm.response.code === 200) pm.test(\"Lista\", () => pm.expect(pm.response.json().pastas).to.be.an(\"array\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/pastas",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "pastas"
              ]
            },
            "description": "`GET /pastas` — pastas das empresas liberadas, com o caminho (escopo `documentos:ler`)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "04 Webhooks",
      "description": "Cadastra um destino em `webhook_url`, testa com um `ping`, olha as entregas, reenvia e remove. O segredo (`whsec_…`) volta só na criação e fica em `webhook_segredo` — o **DIAS Simulador Webhook** usa o mesmo nome.",
      "item": [
        {
          "name": "Criar webhook",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 201\", () => pm.response.to.have.status(201));",
                  "const j = pm.response.json();",
                  "pm.test(\"Segredo whsec_ só na criação\", () => pm.expect(j.segredo).to.match(/^whsec_/));",
                  "if (j.id) pm.collectionVariables.set(\"webhook_id\", j.id);",
                  "const salvarVar = (k, v) => (pm.environment.name ? pm.environment.set(k, v) : pm.collectionVariables.set(k, v));",
                  "if (j.segredo) salvarVar(\"webhook_segredo\", j.segredo);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"{{webhook_url}}\",\n  \"eventos\": [\"envelope.enviado\", \"signatario.visualizou\", \"signatario.assinou\", \"signatario.recusou\", \"convite.falhou\", \"envelope.concluido\", \"envelope.cancelado\", \"envelope.expirado\"],\n  \"descricao\": \"Teste Postman\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks"
              ]
            },
            "description": "`POST /webhooks` — 201 com o `segredo` (só nesta resposta)."
          },
          "response": []
        },
        {
          "name": "Listar webhooks",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Sem segredo na lista\", () => j.webhooks.forEach((w) => pm.expect(w).to.not.have.property(\"segredo\")));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks"
              ]
            },
            "description": "`GET /webhooks` — sem o segredo (só os 4 últimos caracteres em `segredo_fim`)."
          },
          "response": []
        },
        {
          "name": "Alterar webhook",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Alterado\", () => pm.expect(j.descricao).to.include(\"alterado\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"descricao\": \"Teste Postman (alterado)\",\n  \"ativo\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/webhooks/{{webhook_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                "{{webhook_id}}"
              ]
            },
            "description": "`PATCH /webhooks/{id}` — `url`, `eventos`, `empresas`, `descricao`, `ativo`."
          },
          "response": []
        },
        {
          "name": "Testar (ping)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 202\", () => pm.response.to.have.status(202));",
                  "const j = pm.response.json();",
                  "if (j.entrega_id) pm.collectionVariables.set(\"entrega_id\", j.entrega_id);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/webhooks/{{webhook_id}}/testar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                "{{webhook_id}}",
                "testar"
              ]
            },
            "description": "`POST /webhooks/{id}/testar` — enfileira um `ping` (sai em até 1 minuto)."
          },
          "response": []
        },
        {
          "name": "Entregas",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Lista de entregas\", () => pm.expect(j.entregas).to.be.an(\"array\"));",
                  "if (j.entregas[0] && j.entregas[0].id) pm.collectionVariables.set(\"entrega_id\", j.entregas[0] && j.entregas[0].id);"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/webhooks/{{webhook_id}}/entregas",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                "{{webhook_id}}",
                "entregas"
              ]
            },
            "description": "`GET /webhooks/{id}/entregas` — as últimas 100."
          },
          "response": []
        },
        {
          "name": "Reenviar entrega",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 202\", () => pm.response.to.have.status(202));",
                  "const j = pm.response.json();",
                  "pm.test(\"Reenviada\", () => pm.expect(j.reenviada).to.eql(true));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/webhooks/{{webhook_id}}/entregas/{{entrega_id}}/reenviar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                "{{webhook_id}}",
                "entregas",
                "{{entrega_id}}",
                "reenviar"
              ]
            },
            "description": "`POST /webhooks/{id}/entregas/{eid}/reenviar` — de novo na fila, mesmo `evento_id`."
          },
          "response": []
        },
        {
          "name": "Trocar segredo",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200\", () => pm.response.to.have.status(200));",
                  "const j = pm.response.json();",
                  "pm.test(\"Segredo novo whsec_\", () => pm.expect(j.segredo).to.match(/^whsec_/));",
                  "const salvarVar = (k, v) => (pm.environment.name ? pm.environment.set(k, v) : pm.collectionVariables.set(k, v));",
                  "if (j.segredo) salvarVar(\"webhook_segredo\", j.segredo);"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/webhooks/{{webhook_id}}/segredo",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                "{{webhook_id}}",
                "segredo"
              ]
            },
            "description": "`POST /webhooks/{id}/segredo` — segredo novo (o antigo para de valer na hora), só nesta resposta; fica em `webhook_segredo`."
          },
          "response": []
        },
        {
          "name": "Remover webhook",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 204\", () => pm.response.to.have.status(204));"
                ]
              }
            }
          ],
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/webhooks/{{webhook_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                "{{webhook_id}}"
              ]
            },
            "description": "`DELETE /webhooks/{id}` — 204 sem corpo."
          },
          "response": []
        }
      ]
    },
    {
      "name": "05 Erros esperados",
      "description": "Cada requisição provoca um erro de propósito e confere o código. `api_key_restrita` (opcional) é uma chave só com `documentos:ler`.",
      "item": [
        {
          "name": "Sem chave (401 sem_chave)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 401\", () => pm.response.to.have.status(401));",
                  "pm.test(\"Erro sem_chave\", () => pm.expect(pm.response.json().erro.codigo).to.eql(\"sem_chave\"));"
                ]
              }
            }
          ],
          "request": {
            "auth": {
              "type": "noauth"
            },
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/eu",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "eu"
              ]
            },
            "description": "Sem `Authorization` → `401 sem_chave`."
          },
          "response": []
        },
        {
          "name": "Chave sem o escopo (403 sem_escopo)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (!pm.variables.get(\"api_key_restrita\")) {",
                  "  pm.test.skip(\"Defina api_key_restrita para testar o escopo\", () => {});",
                  "} else {",
                  "  pm.test(\"Status 403\", () => pm.response.to.have.status(403));",
                  "  pm.test(\"sem_escopo ou sem_permissao\", () => pm.expect(pm.response.json().erro.codigo).to.be.oneOf([\"sem_escopo\", \"sem_permissao\"]));",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{api_key_restrita}}",
                  "type": "string"
                }
              ]
            },
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"empresa_id\": \"{{empresa_id}}\",\n  \"titulo\": \"Não deve ser criado\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes"
              ]
            },
            "description": "Com uma chave só de leitura em `api_key_restrita`, criar envelope dá `403 sem_escopo`. Sem a variável, o teste é pulado."
          },
          "response": []
        },
        {
          "name": "POST sem Idempotency-Key (400)",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.request.headers.remove(\"Idempotency-Key\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 400\", () => pm.response.to.have.status(400));",
                  "pm.test(\"Erro sem_idempotency_key\", () => pm.expect(pm.response.json().erro.codigo).to.eql(\"sem_idempotency_key\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/pausar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "pausar"
              ]
            },
            "description": "O script desta requisição tira o cabeçalho que a coleção põe → `400 sem_idempotency_key`."
          },
          "response": []
        },
        {
          "name": "Idempotência: 1ª chamada",
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.collectionVariables.set(\"idem_conflito\", \"postman-conflito-\" + pm.variables.replaceIn(\"{{$guid}}\"));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 200 ou 409\", () => pm.expect(pm.response.code).to.be.oneOf([200, 409]));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{idem_conflito}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/lembrete",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "lembrete"
              ]
            },
            "description": "Usa uma Idempotency-Key nova (guardada em `idem_conflito`) com corpo `{}`."
          },
          "response": []
        },
        {
          "name": "Idempotência conflitando (422)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 422\", () => pm.response.to.have.status(422));",
                  "pm.test(\"Erro idempotencia_conflito\", () => pm.expect(pm.response.json().erro.codigo).to.eql(\"idempotencia_conflito\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{idem_conflito}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{ \"signatario_id\": \"{{signatario_id}}\" }",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes/{{envelope_id}}/lembrete",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes",
                "{{envelope_id}}",
                "lembrete"
              ]
            },
            "description": "A mesma Idempotency-Key com outro corpo → `422 idempotencia_conflito`."
          },
          "response": []
        },
        {
          "name": "Corpo inválido (422 validacao)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 422\", () => pm.response.to.have.status(422));",
                  "pm.test(\"Erro validacao\", () => pm.expect(pm.response.json().erro.codigo).to.eql(\"validacao\"));",
                  "pm.test(\"Detalhes por campo\", () => {",
                  "  const campos = pm.response.json().erro.detalhes.map((d) => d.campo);",
                  "  pm.expect(campos).to.include.members([\"empresa_id\", \"titulo\"]);",
                  "});"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"empresa_id\": \"nao-e-uuid\",\n  \"titulo\": \"x\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/envelopes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "envelopes"
              ]
            },
            "description": "`empresa_id` que não é UUID e título curto → `422 validacao` com `detalhes` por campo."
          },
          "response": []
        },
        {
          "name": "Rota inexistente (404)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Status 404\", () => pm.response.to.have.status(404));",
                  "pm.test(\"Erro nao_encontrado\", () => pm.expect(pm.response.json().erro.codigo).to.eql(\"nao_encontrado\"));"
                ]
              }
            }
          ],
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/inventada",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "inventada"
              ]
            },
            "description": "Caminho que não existe → `404 nao_encontrado`."
          },
          "response": []
        }
      ]
    }
  ]
}
