APIPreçosDocumentaçãoBlogParceirosContato
Voltar ao blog
Tutorial

De Ferramenta Interna a Produto API: A História do PunchConnect

Como transformamos uma integração biométrica interna construída para 24.000 funcionários em um produto API REST cloud — e o que aprendemos no caminho.

PunchConnect Team·Mar 28, 2026·5 min read

Introduction

O PunchConnect não deveria ser um produto. Nasceu da frustração — e de 4 meses de produção intensa.

Estávamos construindo o AgriWise, uma plataforma de gestão de pessoal para empresas agrícolas no Marrocos. 24.000+ funcionários em dezenas de unidades. Cada unidade tinha relógios de ponto biométricos ZKTeco. E precisávamos obter os dados de ponto em tempo real na nossa aplicação cloud.

Nada no mercado funcionava. Então construímos o nosso.

O Problema Que Iniciou Tudo

<svg viewBox="0 0 700 300" xmlns="http://www.w3.org/2000/svg" style="max-width:700px;width:100%;font-family:system-ui,sans-serif">
<rect width="700" height="300" fill="#1a1a2e" rx="12"/>
<text x="350" y="30" fill="#e0e0e0" font-size="17" font-weight="bold" text-anchor="middle">O Que Tentamos (e Por Que Falhou)</text>
<rect x="30" y="55" width="195" height="110" rx="8" fill="#3e1e1e" stroke="#ef5350" stroke-width="1"/>
<text x="127" y="80" fill="#ef5350" font-size="15" font-weight="bold" text-anchor="middle">SDKs Open-Source</text>
<text x="127" y="105" fill="#ccc" font-size="14" text-anchor="middle">pyzk, node-zklib</text>
<text x="127" y="125" fill="#ccc" font-size="14" text-anchor="middle">Apenas LAN, sem cloud</text>
<text x="127" y="145" fill="#ef5350" font-size="14" text-anchor="middle">❌ Falhou com 10 dispositivos</text>
<rect x="252" y="55" width="195" height="110" rx="8" fill="#3e1e1e" stroke="#ef5350" stroke-width="1"/>
<text x="350" y="80" fill="#ef5350" font-size="15" font-weight="bold" text-anchor="middle">Software do Fabricante</text>
<text x="350" y="105" fill="#ccc" font-size="14" text-anchor="middle">ZKBioAccess, ADMS</text>
<text x="350" y="125" fill="#ccc" font-size="14" text-anchor="middle">Apenas Windows, sem API</text>
<text x="350" y="145" fill="#ef5350" font-size="14" text-anchor="middle">❌ Sem integração cloud</text>
<rect x="475" y="55" width="195" height="110" rx="8" fill="#3e1e1e" stroke="#ef5350" stroke-width="1"/>
<text x="572" y="80" fill="#ef5350" font-size="15" font-weight="bold" text-anchor="middle">Concorrentes</text>
<text x="572" y="105" fill="#ccc" font-size="14" text-anchor="middle">CAMS, eSSL, MinopCloud</text>
<text x="572" y="125" fill="#ccc" font-size="14" text-anchor="middle">Preços opacos, docs ruins</text>
<text x="572" y="145" fill="#ef5350" font-size="14" text-anchor="middle">❌ Não é dev-friendly</text>
<rect x="30" y="195" width="640" height="85" rx="8" fill="#1b3a2d" stroke="#81c784" stroke-width="2"/>
<text x="350" y="220" fill="#81c784" font-size="17" font-weight="bold" text-anchor="middle">Então Construímos Nós Mesmos</text>
<text x="350" y="245" fill="#ccc" font-size="14" text-anchor="middle">4 meses de engenharia → motor de protocolo → testado com 24.000+ funcionários</text>
<text x="350" y="267" fill="#ccc" font-size="14" text-anchor="middle">Então percebemos: se nós tínhamos esse problema, todo mundo tem</text>
</svg>

De Um Cliente a uma Plataforma

Após 6 meses em produção com o AgriWise, continuávamos ouvindo a mesma pergunta: "Como vocês conectam os dispositivos ZKTeco ao cloud?"

Não construímos um demo. Abrimos nosso sistema de produção. O mesmo motor que gerencia os 24.000+ funcionários da AgriWise alimenta cada chamada API do PunchConnect.

<svg viewBox="0 0 700 250" xmlns="http://www.w3.org/2000/svg" style="max-width:700px;width:100%;font-family:system-ui,sans-serif">
<rect width="700" height="250" fill="#1a1a2e" rx="12"/>
<text x="350" y="30" fill="#e0e0e0" font-size="17" font-weight="bold" text-anchor="middle">Ferramenta Interna → Produto API</text>
<rect x="30" y="55" width="300" height="170" rx="8" fill="#2d2d44" stroke="#444" stroke-width="1"/>
<text x="180" y="80" fill="#4fc3f7" font-size="15" font-weight="bold" text-anchor="middle">Ferramenta Interna</text>
<text x="180" y="105" fill="#ccc" font-size="14" text-anchor="middle">• Inquilino único</text>
<text x="180" y="125" fill="#ccc" font-size="14" text-anchor="middle">• Config hardcoded</text>
<text x="180" y="145" fill="#ccc" font-size="14" text-anchor="middle">• Acesso direto ao banco</text>
<text x="180" y="165" fill="#ccc" font-size="14" text-anchor="middle">• Monitoramento interno</text>
<text x="180" y="185" fill="#ccc" font-size="14" text-anchor="middle">• Sem docs necessários</text>
<text x="180" y="210" fill="#81c784" font-size="14" text-anchor="middle">Funcionava pra gente ✓</text>
<text x="350" y="145" fill="#ff9800" font-size="34" text-anchor="middle">→</text>
<rect x="370" y="55" width="300" height="170" rx="8" fill="#1a3a5c" stroke="#4fc3f7" stroke-width="2"/>
<text x="520" y="80" fill="#4fc3f7" font-size="15" font-weight="bold" text-anchor="middle">Produto API (PunchConnect)</text>
<text x="520" y="105" fill="#ccc" font-size="14" text-anchor="middle">• Isolamento multi-inquilino</text>
<text x="520" y="125" fill="#ccc" font-size="14" text-anchor="middle">• Gestão de API keys</text>
<text x="520" y="145" fill="#ccc" font-size="14" text-anchor="middle">• API REST + Webhooks</text>
<text x="520" y="165" fill="#ccc" font-size="14" text-anchor="middle">• Rate limiting por dispositivo</text>
<text x="520" y="185" fill="#ccc" font-size="14" text-anchor="middle">• Documentação completa</text>
<text x="520" y="210" fill="#81c784" font-size="14" text-anchor="middle">Funciona para todos ✓</text>
</svg>

As Decisões de Engenharia que Importaram

1. Multi-Inquilino com Isolamento por Dispositivo

python
@app.route("/v1/devices", methods=["GET"])
@require_api_key
def listar_dispositivos():
tenant_id = request.auth.tenant_id
dispositivos = db.query(
"SELECT * FROM devices WHERE tenant_id = %s", [tenant_id]
)
return jsonify({"devices": dispositivos})

2. Design de API: Lições do Stripe

- Formato de resposta consistente em cada endpoint
- Códigos de erro claros com identificadores específicos
- Chaves de idempotência em cada operação mutativa

3. Sistema de Entrega Webhook com Retentativas

python
ATRASOS_RETRY = [10, 60, 300, 1800, 7200] # segundos
def entregar_webhook(url: str, payload: dict, segredo: str):
body = json.dumps(payload)
assinatura = hmac.new(
segredo.encode(), body.encode(), hashlib.sha256
).hexdigest()
for tentativa, atraso in enumerate(ATRASOS_RETRY):
try:
resp = requests.post(url, data=body, headers={
"Content-Type": "application/json",
"X-PunchConnect-Signature": assinatura,
}, timeout=10)
if resp.status_code < 300:
return True
except requests.RequestException:
pass
time.sleep(atraso)
return False

4. Documentação Como Produto

Para uma ferramenta interna, documentação é uma wiki que ninguém lê. Para um produto API, a documentação É o produto.

No Brasil, o PunchConnect se enquadra como REP-P conforme a Portaria 671, atendendo à LGPD (Arts. 11-13 para dados biométricos sensíveis) e ao Art. 74 §2º da CLT para empresas com mais de 20 funcionários.

O Que Aprendemos

| Métrica | Interno (AgriWise) | Produto (PunchConnect) |
|---------|-------------------|----------------------|
| Dispositivos | 80+ | Em crescimento |
| Funcionários | 24.000+ | Variável por cliente |
| Disponibilidade | 99,7% | 99,7% (mesmo motor) |
| Latência webhook | 340ms méd. | 340ms méd. |
| Registros perdidos | Zero | Zero |
| Tempo para primeira integração | 4 meses | Menos de 5 minutos |

A última linha é o produto. Nós gastamos 4 meses integrando. Nossos clientes gastam 5 minutos.

FAQ

O PunchConnect ainda é usado internamente pela AgriWise?

Sim. A AgriWise roda exatamente sobre o mesmo motor. Os testes em produção nunca param.

Quanto tempo leva para integrar o PunchConnect?

A maioria dos desenvolvedores recebe seu primeiro webhook em 5 minutos.

Quais dispositivos o PunchConnect suporta?

Dispositivos biométricos ZKTeco — a marca mais implantada globalmente. SpeedFace, ProFace, UA860, K40, MB460 e a maioria dos modelos com conectividade de rede.

Qual a diferença de bibliotecas open-source como pyzk?

Bibliotecas como pyzk se conectam por LAN — um dispositivo por vez. O PunchConnect é um serviço cloud: dispositivos se conectam de saída, funcionam em qualquer rede, fazem buffering offline e entregam dados via webhooks.

Posso testar antes de me comprometer?

Sim. Teste grátis por 7 dias com acesso completo à API, sem cartão de crédito.

---

Teste o PunchConnect grátis por 7 dias — de zero ao primeiro webhook em menos de 5 minutos.

Artigos relacionados

De Ferramenta Interna a Produto API: A História do PunchConnect | PunchConnect