{
  "openapi": "3.0.3",
  "info": {
    "title": "FortunCred API — Parceiros",
    "version": "1.0.0",
    "description": "API para parceiros integrarem o cadastro de lead, simulação, aprovação (análise de crédito) e acompanhamento da FortunCred. Autenticação por API Key no header X-API-Key. Importe no Postman/Insomnia para testar."
  },
  "servers": [
    {
      "url": "https://developers.fortuncred.com.br",
      "description": "Produção"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Leads"
    },
    {
      "name": "Simulação"
    },
    {
      "name": "Aprovação"
    },
    {
      "name": "Acompanhamento"
    },
    {
      "name": "Utilitários"
    }
  ],
  "paths": {
    "/v1/leads": {
      "post": {
        "tags": [
          "Leads"
        ],
        "summary": "Criar ou reaproveitar lead",
        "description": "Cadastra o lead na unidade do parceiro. Se o CPF já existir, reaproveita o lead (reaproveitado=true). Envie Idempotency-Key para evitar duplicidade em retries.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadInput"
              },
              "example": {
                "nome": "Lucas Henrique Almeida",
                "cpf": "483.729.156-28",
                "telefone": "34999990000",
                "email": "lucas@exemplo.com",
                "data_nascimento": "1988-04-17",
                "renda": 8500,
                "estado_civil": "casado"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lead reaproveitado (CPF já existia)",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "lead_id": 34077,
                  "reaproveitado": true
                }
              }
            }
          },
          "201": {
            "description": "Lead criado",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "lead_id": 34077,
                  "reaproveitado": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Erro"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/leads/{id}": {
      "get": {
        "tags": [
          "Acompanhamento"
        ],
        "summary": "Consultar lead",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Dados do lead"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "404": {
            "$ref": "#/components/responses/Erro"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "tags": [
          "Leads"
        ],
        "summary": "Editar dados do lead",
        "description": "Atualiza os dados do cliente (nome, contato, renda, estado civil, observação). Não move o lead de unidade/consultor. Envie apenas os campos que quer alterar.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadPatch"
              },
              "example": {
                "renda": 9100,
                "email": "novo@exemplo.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lead atualizado",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "lead_id": 34077,
                  "atualizado": [
                    "email",
                    "renda"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "422": {
            "$ref": "#/components/responses/Erro"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/simulacoes/{id}": {
      "get": {
        "tags": [
          "Simulação"
        ],
        "summary": "Dados da simulação (JSON)",
        "description": "Retorna os números crus da simulação para o parceiro montar o próprio layout (card, PDF, tela). Todos os valores monetários são números (R$) e as taxas são percentuais ao ano/mês.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Dados da simulação",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "simulacao": {
                    "id": 45567,
                    "lead_id": 34195,
                    "banco": "Santander",
                    "banco_id": 3,
                    "produto": "FINANCIAMENTO",
                    "sistema_amortizacao": "SAC",
                    "indexador": "TR",
                    "prazo_meses": 420,
                    "data": "2026-07-08T20:48:33Z",
                    "cliente": {
                      "nome": "JANAINA...",
                      "cpf": "10166714402",
                      "data_nascimento": "1993-03-26"
                    },
                    "valores": {
                      "imovel": 450811.83,
                      "financiado": 305659.39,
                      "despesas": 0
                    },
                    "taxas": {
                      "juros_aa": 12.59,
                      "juros_am": 0.9931,
                      "cet_aa": 13.45
                    },
                    "parcelas": {
                      "primeira": 3874.96,
                      "ultima": 786.05,
                      "total_a_pagar": 1019038.3
                    },
                    "renda_necessaria": 12916.53,
                    "custos": {
                      "taxa_avaliacao": 1950,
                      "dfi": 0.0001,
                      "tarifa_mensal": 25
                    },
                    "composicao_primeira_parcela": {
                      "amortizacao": 727.76,
                      "juros": 3035.47,
                      "seguro_mip": 64.19,
                      "dfi": 22.54,
                      "tarifa": 25,
                      "total": 3874.96
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "404": {
            "$ref": "#/components/responses/Erro"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/simulacoes": {
      "post": {
        "tags": [
          "Simulação"
        ],
        "summary": "Simular financiamento",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulacaoInput"
              },
              "example": {
                "lead_id": 34077,
                "valor_imovel": 500000,
                "valor_financiado": 250000,
                "prazo": 360,
                "renda": 8500,
                "tipo_amortizacao": "SAC",
                "bancos": [
                  "bradesco",
                  "itau",
                  "santander"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado da simulação por banco",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "resultado": {
                    "sucesso": true,
                    "id_oportunidade": 19138,
                    "resultados": [
                      {
                        "banco": "Santander",
                        "taxa_anual": 11.69,
                        "cet_anual": 12.77,
                        "parcela_1": 2058.85,
                        "renda_necessaria": 6862.83,
                        "pdf_url": "/simulacoes/45408/pdf"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Erro"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "422": {
            "$ref": "#/components/responses/Erro"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/analises": {
      "post": {
        "tags": [
          "Aprovação"
        ],
        "summary": "Enviar para análise de crédito",
        "description": "Envia a ficha completa para aprovação no banco (uma análise por banco). O resultado é assíncrono — consulte por polling ou receba via webhook. Exige Idempotency-Key (obrigatório aqui) e consentimento LGPD do titular.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyRequired"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnaliseInput"
              },
              "example": {
                "lead_id": 34077,
                "bancos": [
                  "bradesco",
                  "itau"
                ],
                "consentimento": true,
                "consentimento_timestamp": "2026-07-10T14:32:00-03:00",
                "consentimento_ip": "200.145.32.10",
                "consentimento_canal": "web",
                "nome": "Lucas Henrique Almeida",
                "cpf": "483.729.156-28",
                "telefone": "34999990000",
                "data_nascimento": "1988-04-17",
                "renda": 8500,
                "sexo": "M",
                "estado_civil": "casado",
                "nome_mae": "Marta Almeida",
                "email": "lucas@exemplo.com",
                "profissao": "Engenheiro",
                "empresa": "Construtora XYZ",
                "rg": "MG1234567",
                "rg_orgao": "SSP",
                "rg_uf": "MG",
                "rg_emissao": "2010-02-01",
                "cep": "38400-000",
                "logradouro": "Rua das Flores",
                "numero": "120",
                "bairro": "Centro",
                "municipio": "Uberlândia",
                "uf": "MG",
                "valor_imovel": 500000,
                "valor_financiado": 250000,
                "prazo": 360,
                "conjuge_nome": "Ana Paula Almeida",
                "conjuge_cpf": "305.118.440-34",
                "conjuge_data_nascimento": "1990-09-12"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Análise enviada (em processamento)",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "analises": [
                    {
                      "banco_id": 1,
                      "sucesso": true,
                      "analise_id": 27603,
                      "num_consulta": "5316807",
                      "status": "Análise Crédito"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Erro"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "422": {
            "$ref": "#/components/responses/Erro"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/analises/{id}/status": {
      "get": {
        "tags": [
          "Acompanhamento"
        ],
        "summary": "Status da análise",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Situação atual. `situacao` é um enum estável (em_analise | aprovado | condicionado | recusado | cancelado | erro); `status_original` traz o texto cru do CRM.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "analise": {
                    "analise_id": 27603,
                    "banco": "Bradesco",
                    "num_consulta": "5316807",
                    "status_original": "Crédito Aprovado",
                    "situacao": "aprovado",
                    "pendente": false
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "404": {
            "$ref": "#/components/responses/Erro"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/leads/{id}/analises": {
      "get": {
        "tags": [
          "Acompanhamento"
        ],
        "summary": "Análises do lead (paginado)",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Página de análises do lead",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "limit": 20,
                  "offset": 0,
                  "tem_mais": false,
                  "pendentes": 1,
                  "analises": [
                    {
                      "analise_id": 27603,
                      "banco": "Bradesco",
                      "situacao": "aprovado",
                      "pendente": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/leads/{id}/consentimentos": {
      "get": {
        "tags": [
          "Acompanhamento"
        ],
        "summary": "Consentimentos LGPD do lead (auditoria, paginado)",
        "description": "Lista os consentimentos registrados nas análises do lead (auditoria LGPD). Apenas do parceiro dono do lead.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Página de consentimentos",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "limit": 20,
                  "offset": 0,
                  "tem_mais": false,
                  "consentimentos": [
                    {
                      "id": 12,
                      "consentimento": true,
                      "timestamp": "2026-07-10T14:32:00-03:00",
                      "ip": "200.145.32.10",
                      "canal": "web",
                      "analise_ids": [
                        27603
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Configuração de webhook (somente leitura)",
        "description": "Mostra a URL de webhook e se há secret de assinatura configurado para o parceiro autenticado. O cadastro/alteração da URL e a rotação do secret são feitos pelo suporte. O secret nunca é exposto por esta rota.",
        "responses": {
          "200": {
            "description": "Configuração atual",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "webhook": {
                    "configurado": true,
                    "url": "https://parceiro.exemplo.com/hooks/fortuncred",
                    "secret_configurado": true,
                    "eventos": [
                      "analise.resultado",
                      "analise.erro"
                    ],
                    "gestao": "somente-leitura",
                    "observacao": "Para cadastrar/alterar a URL ou rotacionar o secret de assinatura, fale com o suporte."
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "tags": [
          "Utilitários"
        ],
        "summary": "Identidade do parceiro autenticado",
        "responses": {
          "200": {
            "description": "Dados do parceiro"
          },
          "401": {
            "$ref": "#/components/responses/NaoAutenticado"
          },
          "403": {
            "$ref": "#/components/responses/SemPermissao"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": [
          "Utilitários"
        ],
        "summary": "Healthcheck (público)",
        "security": [],
        "responses": {
          "200": {
            "description": "Serviço no ar"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Chave do parceiro (formato fortuncred_...). Também aceita Authorization: Bearer <chave>."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "Chave única da requisição; reenvios com a mesma chave não duplicam o registro."
      },
      "IdempotencyKeyRequired": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "OBRIGATÓRIA neste endpoint. Reenvios com a mesma chave e mesmo corpo devolvem a resposta original (Idempotent-Replay: true); mesma chave com corpo diferente devolve 422 idempotency_conflito."
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        },
        "description": "Itens por página (1..100, padrão 20)."
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        },
        "description": "Deslocamento para a próxima página. A resposta traz tem_mais=true quando há mais itens."
      }
    },
    "responses": {
      "Erro": {
        "description": "Erro. Corpo padronizado com código estável.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "erro": {
                  "type": "string"
                },
                "codigo": {
                  "type": "string",
                  "description": "slug estável do erro (ex.: campo_obrigatorio, consentimento_ausente, idempotency_conflito, rate_limited)"
                },
                "campos": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "campo": {
                        "type": "string"
                      },
                      "motivo": {
                        "type": "string"
                      }
                    }
                  }
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "NaoAutenticado": {
        "description": "API key ausente/invalida (codigo auth_invalid)"
      },
      "SemPermissao": {
        "description": "Escopo insuficiente para o recurso (codigo sem_permissao)"
      },
      "RateLimited": {
        "description": "Limite por minuto excedido (codigo rate_limited). Ver header Retry-After."
      }
    },
    "schemas": {
      "LeadInput": {
        "type": "object",
        "required": [
          "nome",
          "cpf"
        ],
        "properties": {
          "nome": {
            "type": "string"
          },
          "cpf": {
            "type": "string"
          },
          "telefone": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "data_nascimento": {
            "type": "string",
            "format": "date",
            "example": "1990-05-01"
          },
          "renda": {
            "type": "number"
          },
          "estado_civil": {
            "type": "string",
            "enum": [
              "solteiro",
              "casado",
              "uniao",
              "divorciado",
              "viuvo",
              "separado"
            ]
          },
          "origem": {
            "type": "string"
          },
          "observacao": {
            "type": "string"
          }
        }
      },
      "SimulacaoInput": {
        "type": "object",
        "required": [
          "lead_id"
        ],
        "properties": {
          "lead_id": {
            "type": "integer"
          },
          "valor_imovel": {
            "type": "number"
          },
          "valor_financiado": {
            "type": "number"
          },
          "prazo": {
            "type": "integer",
            "description": "meses"
          },
          "renda": {
            "type": "number"
          },
          "tipo_amortizacao": {
            "type": "string",
            "enum": [
              "SAC",
              "PRICE"
            ]
          },
          "bancos": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "bradesco",
                "itau",
                "santander",
                "inter",
                "brb",
                "cashme"
              ]
            },
            "description": "Obrigatório (ao menos 1). Aceita apelido, nome ou id. Banco fora da lista -> 422 banco_invalido.",
            "example": [
              "bradesco",
              "itau",
              "santander"
            ]
          }
        }
      },
      "AnaliseInput": {
        "type": "object",
        "required": [
          "lead_id",
          "consentimento",
          "consentimento_timestamp",
          "consentimento_ip",
          "consentimento_canal",
          "nome",
          "cpf",
          "data_nascimento",
          "renda",
          "sexo",
          "estado_civil",
          "nome_mae",
          "email",
          "profissao",
          "empresa",
          "rg",
          "rg_orgao",
          "rg_uf",
          "rg_emissao",
          "cep",
          "logradouro",
          "numero",
          "bairro",
          "municipio",
          "uf",
          "valor_imovel",
          "valor_financiado"
        ],
        "properties": {
          "lead_id": {
            "type": "integer"
          },
          "consentimento": {
            "type": "boolean",
            "description": "LGPD: deve ser true. O titular autorizou a consulta de crédito. A coleta/registro do consentimento é responsabilidade do PARCEIRO."
          },
          "consentimento_timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Quando o titular consentiu (ISO 8601)."
          },
          "consentimento_ip": {
            "type": "string",
            "description": "IP de onde o titular consentiu (do cliente final, não do parceiro)."
          },
          "consentimento_canal": {
            "type": "string",
            "description": "Canal do consentimento (ex.: web, app, whatsapp, presencial)."
          },
          "bancos": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "bradesco",
                "itau",
                "santander",
                "inter",
                "brb",
                "cashme"
              ]
            },
            "description": "Obrigatório (ao menos 1). Banco fora da lista -> 422 banco_invalido."
          },
          "nome": {
            "type": "string",
            "description": "Deve bater com o nome do lead (senão 422 divergencia_titular)."
          },
          "cpf": {
            "type": "string",
            "description": "Deve bater com o CPF do lead (senão 422 divergencia_titular)."
          },
          "telefone": {
            "type": "string"
          },
          "data_nascimento": {
            "type": "string",
            "format": "date"
          },
          "renda": {
            "type": "number"
          },
          "sexo": {
            "type": "string",
            "enum": [
              "M",
              "F"
            ]
          },
          "estado_civil": {
            "type": "string"
          },
          "nome_mae": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "profissao": {
            "type": "string"
          },
          "empresa": {
            "type": "string"
          },
          "rg": {
            "type": "string"
          },
          "rg_orgao": {
            "type": "string"
          },
          "rg_uf": {
            "type": "string"
          },
          "rg_emissao": {
            "type": "string",
            "format": "date"
          },
          "cep": {
            "type": "string"
          },
          "logradouro": {
            "type": "string"
          },
          "numero": {
            "type": "string"
          },
          "bairro": {
            "type": "string"
          },
          "municipio": {
            "type": "string"
          },
          "uf": {
            "type": "string"
          },
          "valor_imovel": {
            "type": "number"
          },
          "valor_financiado": {
            "type": "number"
          },
          "prazo": {
            "type": "integer"
          },
          "conjuge_nome": {
            "type": "string",
            "description": "Obrigatório quando estado_civil = casado/união."
          },
          "conjuge_cpf": {
            "type": "string",
            "description": "Obrigatório quando estado_civil = casado/união."
          },
          "conjuge_data_nascimento": {
            "type": "string",
            "description": "Obrigatório quando estado_civil = casado/união."
          },
          "conjuge_renda": {
            "type": "number",
            "description": "Opcional (nem todo casal compõe renda)."
          }
        }
      },
      "LeadPatch": {
        "type": "object",
        "description": "Campos a alterar (todos opcionais).",
        "properties": {
          "nome": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "telefone": {
            "type": "string"
          },
          "renda": {
            "type": "number"
          },
          "estado_civil": {
            "type": "string"
          },
          "observacao": {
            "type": "string"
          }
        }
      }
    }
  }
}
