{
  "openapi": "3.0.3",
  "info": {
    "title": "PrintBee - Autenticação",
    "description": "Endpoint público para obter ou renovar token Bearer via client_credentials ou refresh_token.\n\n**Autenticação das APIs:** As demais APIs da PrintBee devem ser autenticadas enviando o header `Authorization: Bearer <token>` em cada requisição.\n\n**Códigos de erro do endpoint /Auth/Token:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| ATH0007 | 400 | grant_type inválido. Use client_credentials ou refresh_token. |\n| ATH0008 | 400 | Request inválido. Envie o corpo em JSON ou application/x-www-form-urlencoded. |\n| CRD0003 | 400/401 | Credenciais ausentes (client_credentials) ou inválidas (ClientId/ClientSecret ou refresh_token). |\n\n## Jornada: Autenticação — obtendo o token de acesso\n\nToda chamada à API precisa de um token de acesso. Você troca as credenciais da sua integração por um token e o envia no header `Authorization` das chamadas seguintes.\n\n![Diagrama de sequência da autenticação: seu sistema envia POST /api/Auth/Token com grant_type=client_credentials; a API confere client_id e client_secret e responde 200 com o access_token, válido por 1 hora; as chamadas seguintes levam o header Authorization Bearer; credencial inválida responde 401 CRD0003.](/openapi/diagrams/jornada-autenticacao.svg)\n\nO `access_token` vive o que você pedir em `expires` (padrão: 1 hora). O `refresh_token` vive **dez vezes** esse prazo, limitado a 7 dias — ou seja, com o `expires=1` padrão ele vale **10 horas**, não 7 dias. Os 7 dias são o TETO, alcançado só a partir de `expires=17`.\n\nRenove **antes** de o `refresh_token` expirar: passado o prazo ele é recusado (`401` / `CRD0003`), e a recuperação e refazer o `client_credentials` — que sua integração faz sozinha, pois detém o Client Secret. Uma rotina que renova uma vez por dia contando com “7 dias” falha na 10ª hora.\n\nMais duas regras na renovação: só o `refresh_token` renova (apresentar o `access_token` no lugar dele é recusado), e o `refresh_token` é de **uso único** — cada renovação devolve um par novo e invalida o anterior, então guarde sempre o último recebido. Se a resposta da renovação se perder (timeout, queda de rede), **não reapresente o antigo**: ele já foi consumido e responderá `401`; refaça o `client_credentials`.\n\nO Client ID começa com `pb_` (por exemplo, `pb_xxxxxxxx`) e o Client Secret é exibido uma única vez, no momento em que você o gera no portal. Guarde-o em local seguro: não há como vê-lo de novo.\n\nOs erros que aparecem nesta jornada (`ATH0007`, `ATH0008` e `CRD0003`) estão descritos na tabela de códigos de erro acima.",
    "version": "1.0.0",
    "contact": {
      "name": "Suporte PrintBee",
      "url": "https://api.printbee.com.br"
    }
  },
  "servers": [
    {
      "url": "https://api.printbee.com.br",
      "description": "Produção"
    }
  ],
  "paths": {
    "/api/Auth/Token": {
      "post": {
        "tags": ["Autenticação"],
        "summary": "Obter ou renovar token",
        "description": "Obtém token Bearer via client_credentials (ClientId + ClientSecret) ou renova via refresh_token. Endpoint público.\n\n**Tabela de erros:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| ATH0007 | 400 | grant_type inválido. Use client_credentials ou refresh_token. |\n| ATH0008 | 400 | Request inválido. Envie o corpo em JSON ou application/x-www-form-urlencoded. |\n| CRD0003 | 400/401 | Credenciais ausentes (client_credentials) ou inválidas (ClientId/ClientSecret ou refresh_token). |",
        "operationId": "token",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["grantType"],
                "properties": {
                  "grantType": {
                    "type": "string",
                    "enum": ["client_credentials", "refresh_token"],
                    "description": "Tipo de concessão",
                    "x-enumDescriptions": {
                      "client_credentials": "Concessão via ClientId e ClientSecret. Use para obter o primeiro token ou credenciais de máquina.",
                      "refresh_token": "Concessão via refresh_token. Use para renovar o access_token quando expirar."
                    }
                  },
                  "clientId": {
                    "type": "string",
                    "description": "Client ID (obrigatório para client_credentials)"
                  },
                  "clientSecret": {
                    "type": "string",
                    "description": "Client Secret (obrigatório para client_credentials)"
                  },
                  "refreshToken": {
                    "type": "string",
                    "description": "Token de refresh (obrigatório para refresh_token)"
                  },
                  "expires": {
                    "type": "integer",
                    "default": 1,
                    "description": "Expiração do access token em horas"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["grantType"],
                "properties": {
                  "grantType": {
                    "type": "string",
                    "enum": ["client_credentials", "refresh_token"],
                    "description": "Tipo de concessão",
                    "x-enumDescriptions": {
                      "client_credentials": "Concessão via ClientId e ClientSecret. Use para obter o primeiro token ou credenciais de máquina.",
                      "refresh_token": "Concessão via refresh_token. Use para renovar o access_token quando expirar."
                    }
                  },
                  "clientId": {
                    "type": "string",
                    "description": "Client ID (obrigatório para client_credentials)"
                  },
                  "clientSecret": {
                    "type": "string",
                    "description": "Client Secret (obrigatório para client_credentials)"
                  },
                  "refreshToken": {
                    "type": "string",
                    "description": "Token de refresh (obrigatório para refresh_token)"
                  },
                  "expires": {
                    "type": "integer",
                    "default": 1,
                    "description": "Expiração do access token em horas"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token obtido ou renovado com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer",
                      "description": "Código HTTP da resposta (200)"
                    },
                    "data": {
                      "type": "object",
                      "description": "Objeto contendo os dados do token",
                      "properties": {
                        "token_type": {
                          "type": "string",
                          "example": "Bearer",
                          "description": "Tipo do token (sempre Bearer)"
                        },
                        "access_token": {
                          "type": "string",
                          "description": "Token JWT para autenticar requisições. Envie no header Authorization: Bearer <access_token>"
                        },
                        "refresh_token": {
                          "type": "string",
                          "description": "Token para renovar o access_token quando expirar"
                        },
                        "expires_in": {
                          "type": "integer",
                          "description": "Tempo de vida do access_token em segundos"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "grant_type inválido ou credenciais ausentes",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorPayload" },
                "example": {
                  "code": 400,
                  "errors": [
                    {
                      "errorCode": "ATH0007",
                      "message": "grant_type inválido. Use client_credentials ou refresh_token."
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "ClientId/ClientSecret ou refresh_token inválidos",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorPayload" },
                "example": {
                  "code": 401,
                  "errors": [
                    {
                      "errorCode": "CRD0003",
                      "message": "Credenciais inválidas."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrorPayload": {
        "type": "object",
        "required": ["code", "errors"],
        "properties": {
          "code": {
            "type": "integer",
            "description": "Código HTTP do erro (400, 401, etc.)",
            "example": 400
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["errorCode", "message"],
              "properties": {
                "errorCode": {
                  "type": "string",
                  "description": "Código interno do erro",
                  "example": "CRD0003"
                },
                "message": {
                  "type": "string",
                  "description": "Mensagem descritiva do erro",
                  "example": "Credenciais inválidas."
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Envie o access_token no header: Authorization: Bearer <token>"
      }
    }
  }
}
