API para gerenciamento de clientes, simulação de integração com Pipefy via GraphQL e webhooks.
- Python 3.12
- FastAPI
- SQLAlchemy 2.0
- Pydantic v2
- SQLite
- uv
- pytest
- Ruff
app/
├── integrations/
│ └── pipefy_client.py # Mutations GraphQL do Pipefy
├── models/
├── repositories/
├── routes/
├── schemas/
├── services/
├── config.py
├── database.py
├── exceptions.py
└── main.py
tests/
├── conftest.py
├── test_clients.py
└── test_webhooks.py
- Python 3.12+
- uv
# Clonar o repositório
git clone https://github.com/lucasdavidoj/client-workflow-api.git
cd client-workflow-api
# Instalar dependências (cria o .venv automaticamente)
uv synccp .env.example .envO .env.example já contém os valores padrão para execução local com SQLite, não é preciso alterá-lo para rodar.
uv run uvicorn app.main:app --reloadA API estará disponível em http://localhost:8000.
A documentação swagger estará em http://localhost:8000/docs.
uv run pytest -qOs testes usam um banco SQLite em memória isolado por fixture.
As mutations foram estruturadas seguindo o formato esperado da API GraphQL do Pipefy, mas a aplicação não realiza chamadas reais ao Pipefy neste desafio.
Cria um novo cliente com status inicial "Aguardando Análise" e retorna o payload GraphQL que seria enviado ao Pipefy para criar o card correspondente.
curl -s -X POST http://localhost:8000/clientes \
-H "Content-Type: application/json" \
-d '{
"cliente_nome": "Lucas David",
"cliente_email": "lucas.david@tests.com",
"tipo_solicitacao": "Atualização cadastral",
"valor_patrimonio": 250000
}' | python3 -m json.toolResposta (201 Created):
{
"client": {
"id": 1,
"name": "Lucas David",
"email": "lucas.david@tests.com",
"request_type": "Atualização cadastral",
"asset_value": "250000.00",
"status": "Aguardando Análise",
"priority": null
},
"pipefy_payload": {
"query": "mutation CreateCard($input: CreateCardInput!) { ... }",
"variables": {
"input": {
"pipe_id": "pipe_id_placeholder",
"title": "Lucas David",
"fields_attributes": [...]
}
}
}
}Simula o recebimento de um evento do Pipefy quando um card é atualizado. Aplica a regra de prioridade baseada no patrimônio do cliente e retorna o payload GraphQL que seria enviado ao Pipefy para atualizar os campos do card.
curl -s -X POST http://localhost:8000/webhooks/pipefy/card-updated \
-H "Content-Type: application/json" \
-d '{
"event_id": "evt_123",
"card_id": "card_456",
"cliente_email": "lucas.david@tests.com",
"timestamp": "2026-05-18T12:00:00Z"
}' | python3 -m json.toolResposta (200 OK):
{
"event_id": "evt_123",
"client": {
"id": 1,
"name": "Lucas David",
"email": "lucas.david@tests.com",
"request_type": "Atualização cadastral",
"asset_value": "250000.00",
"status": "Processado",
"priority": "prioridade_alta"
},
"pipefy_payload": {
"query": "mutation UpdateCardFields(...) { ... }",
"variables": {
"statusInput": {
"card_id": "card_456",
"field_id": "status",
"new_value": "Processado"
},
"priorityInput": {
"card_id": "card_456",
"field_id": "prioridade",
"new_value": "prioridade_alta"
}
}
}
}Regras de prioridade:
valor_patrimonio |
Prioridade atribuída |
|---|---|
| >= R$ 200.000 | prioridade_alta |
| < R$ 200.000 | prioridade_normal |
Idempotência: reenviar o mesmo event_id retorna 409 Conflict.
Para escalar esse sistema em produção, eu trocaria o SQLite pelo PostgreSQL no AWS RDS em conjunto com AWS RDS Proxy para evitar excesso de conexões abertas no banco.
A API poderia ser exposta por API Gateway e processada por Lambdas separadas para criação de clientes e recebimento de webhooks. Para webhooks com maior volume, eu colocaria uma fila SQS entre o recebimento do evento e o processamento, dessa forma, a API responde rápido e o processamento pode ser refeito em caso de falha.
A idempotência por event_id poderia continuar no banco relacional ou ir para o DynamoDB, já que é uma consulta simples por chave única.
Para infraestrutura, usaria Terraform ou AWS SAM.