{
  "info": {
    "name": "Turron · API de Integração (v1)",
    "description": "Coleção oficial da API de Integração Turron.\n\n1. Abra a aba Variables desta coleção.\n2. Preencha clientId e clientSecret (coluna Current value) e salve.\n3. Envie qualquer requisição: o token OAuth 2.0 é gerado e renovado automaticamente.\n\nDocumentação: http://127.0.0.1:6334/documentacao",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{accessToken}}",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "const tokenUrl = pm.variables.get(\"baseUrl\") + \"/oauth/token\";",
          "const clientId = pm.variables.get(\"clientId\");",
          "const clientSecret = pm.variables.get(\"clientSecret\");",
          "const expiresAt = Number(pm.collectionVariables.get(\"tokenExpiresAt\") || 0);",
          "const tokenValid = pm.collectionVariables.get(\"accessToken\") && Date.now() < expiresAt - 30000;",
          "const isTokenRequest = pm.request.url.getPath().endsWith(\"/oauth/token\");",
          "const isPublic = pm.request.auth && pm.request.auth.type === \"noauth\";",
          "",
          "if (!tokenValid && !isTokenRequest && !isPublic) {",
          "  if (!clientId || !clientSecret) {",
          "    console.warn(\"Preencha as variáveis clientId e clientSecret da coleção (aba Variables).\");",
          "  } else {",
          "    pm.sendRequest({",
          "      url: tokenUrl,",
          "      method: \"POST\",",
          "      auth: {",
          "        type: \"basic\",",
          "        basic: [",
          "          { key: \"username\", value: clientId },",
          "          { key: \"password\", value: clientSecret }",
          "        ]",
          "      },",
          "      header: { \"Content-Type\": \"application/x-www-form-urlencoded\" },",
          "      body: { mode: \"urlencoded\", urlencoded: [{ key: \"grant_type\", value: \"client_credentials\" }] }",
          "    }, (err, res) => {",
          "      if (err || res.code !== 200) {",
          "        console.error(\"Falha ao gerar o token\", err || res.json());",
          "        return;",
          "      }",
          "      const body = res.json();",
          "      pm.collectionVariables.set(\"accessToken\", body.access_token);",
          "      pm.collectionVariables.set(\"tokenExpiresAt\", String(Date.now() + body.expires_in * 1000));",
          "    });",
          "  }",
          "}"
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "baseUrl",
      "value": "http://127.0.0.1:6334",
      "type": "string"
    },
    {
      "key": "clientId",
      "value": "",
      "type": "string"
    },
    {
      "key": "clientSecret",
      "value": "",
      "type": "secret"
    },
    {
      "key": "accessToken",
      "value": "",
      "type": "secret"
    },
    {
      "key": "tokenExpiresAt",
      "value": "0",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Autenticação",
      "item": [
        {
          "name": "Gerar token",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/oauth/token",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "oauth",
                "token"
              ]
            },
            "description": "Envie client_id e client_secret via HTTP Basic (recomendado) ou no corpo. Aceita application/x-www-form-urlencoded ou application/json. O token expira em `expires_in` segundos.\n\nEnvie as credenciais via HTTP Basic (recomendado) ou no corpo como client_id e client_secret.\n\nAceita application/x-www-form-urlencoded (padrão OAuth) ou application/json.\n\nReutilize o token até expirar (expires_in, em segundos). Não gere um token por requisição.",
            "auth": {
              "type": "basic",
              "basic": [
                {
                  "key": "username",
                  "value": "{{clientId}}",
                  "type": "string"
                },
                {
                  "key": "password",
                  "value": "{{clientSecret}}",
                  "type": "string"
                }
              ]
            },
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "grant_type",
                  "value": "client_credentials"
                }
              ]
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 200) {",
                  "  const body = pm.response.json();",
                  "  pm.collectionVariables.set(\"accessToken\", body.access_token);",
                  "  pm.collectionVariables.set(\"tokenExpiresAt\", String(Date.now() + body.expires_in * 1000));",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "Colaboradores",
      "item": [
        {
          "name": "Listar colaboradores",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/employees?page=1&limit=50&status=active",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "employees"
              ],
              "query": [
                {
                  "key": "page",
                  "value": "1"
                },
                {
                  "key": "limit",
                  "value": "50"
                },
                {
                  "key": "status",
                  "value": "active"
                }
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Consultar colaborador",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/employees/1001",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "employees",
                "1001"
              ]
            },
            "description": ""
          }
        },
        {
          "name": "Cadastrar colaborador",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Opcional. Evita processamento duplicado em reenvios."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/employees",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "employees"
              ]
            },
            "description": "",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"registration\": \"1001\",\n  \"badge\": \"50001\",\n  \"name\": \"Maria da Silva\",\n  \"company\": \"1\",\n  \"profitCenter\": \"11931400\",\n  \"status\": \"active\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Cadastrar em lote",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Opcional. Evita processamento duplicado em reenvios."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/employees/bulk",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "employees",
                "bulk"
              ]
            },
            "description": "Até 1000 colaboradores por requisição.\n\nTudo ou nada: se uma matrícula já existir ou estiver repetida no envio, nenhum registro é gravado e todas as pendências são listadas em errors.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"items\": [\n    {\n      \"registration\": \"1001\",\n      \"badge\": \"50001\",\n      \"name\": \"Maria da Silva\",\n      \"profitCenter\": \"11931400\"\n    },\n    {\n      \"registration\": \"1002\",\n      \"badge\": \"50002\",\n      \"name\": \"João Souza\",\n      \"profitCenter\": \"11931400\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Atualizar colaborador",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Opcional. Evita processamento duplicado em reenvios."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/employees/1001",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "employees",
                "1001"
              ]
            },
            "description": "Atualização parcial: apenas os campos enviados são alterados.\n\nPara desligar um colaborador envie status: \"inactive\" — a data de desligamento é registrada automaticamente.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"badge\": \"50099\",\n  \"status\": \"inactive\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Atualizar em lote",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Opcional. Evita processamento duplicado em reenvios."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/employees/bulk",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "employees",
                "bulk"
              ]
            },
            "description": "Até 1000 colaboradores por requisição, identificados pela matrícula.\n\nTudo ou nada: se alguma matrícula não existir, nada é alterado.\n\nRegistros sem alteração real são contados em unchanged e não geram nova sincronização.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"items\": [\n    {\n      \"registration\": \"1001\",\n      \"status\": \"inactive\"\n    },\n    {\n      \"registration\": \"1002\",\n      \"name\": \"João Souza Lima\",\n      \"badge\": \"50010\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "Pedidos",
      "item": [
        {
          "name": "Listar itens de pedidos",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/order-items?startDate=2026-09-01&endDate=2026-09-30&page=1&limit=100",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "order-items"
              ],
              "query": [
                {
                  "key": "startDate",
                  "value": "2026-09-01"
                },
                {
                  "key": "endDate",
                  "value": "2026-09-30"
                },
                {
                  "key": "page",
                  "value": "1"
                },
                {
                  "key": "limit",
                  "value": "100"
                }
              ]
            },
            "description": "Período obrigatório de no máximo 31 dias. Datas YYYY-MM-DD usam o fuso de Brasília e incluem o dia inteiro.\n\nstartDate e endDate são obrigatórios, com período máximo de 31 dias.\n\nDatas no formato YYYY-MM-DD usam o fuso de Brasília (UTC-3) e incluem o dia inteiro. Também é aceito date-time ISO 8601.\n\nOs itens são ordenados por data de emissão; percorra as páginas por links.next até ele ser null."
          }
        }
      ]
    },
    {
      "name": "Sistema",
      "item": [
        {
          "name": "Status da API",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/health",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "health"
              ]
            },
            "description": "",
            "auth": {
              "type": "noauth"
            }
          }
        }
      ]
    }
  ]
}