Boas Práticas de Integração Use page_size Adequado HTTP # Para bulk sync — máximo por página
GET /empregados/?page_size=100
# Para UI — menor latência
GET /empregados/?page_size=20
Filtre na API, não no código Python # ❌ Ineficiente: traz tudo e filtra localmente
todos = listar_todos ( "/empregados/" , headers )
ativos = [ e for e in todos if e [ "is_active" ]]
# ✅ Eficiente: filtra na API
ativos = listar_todos ( "/empregados/?is_active=true" , headers )
Cache de Respostas Imutáveis Python from functools import lru_cache
import time
class CachedPontotelClient :
def __init__ ( self , auth , cache_ttl_seconds = 300 ):
self . auth = auth
self . cache = {}
self . cache_ttl = cache_ttl_seconds
def get ( self , url : str ) -> dict :
now = time . time ()
if url in self . cache :
cached_data , cached_at = self . cache [ url ]
if now - cached_at < self . cache_ttl :
return cached_data
headers = self . auth . get_headers ()
response = requests . get ( url , headers = headers )
response . raise_for_status ()
data = response . json ()
self . cache [ url ] = ( data , now )
return data
Segurança Armazenamento de Credenciais Python # ✅ Correto: Usar variáveis de ambiente
import os
from dotenv import load_dotenv
load_dotenv ()
USERNAME = os . getenv ( "PONTOTEL_USERNAME" )
PASSWORD = os . getenv ( "PONTOTEL_PASSWORD" )
# ❌ Nunca hardcode credenciais
USERNAME = "meu_usuario" # NÃO FAÇA ISSO
Nunca faça commit de credenciais
Adicione .env ao .gitignore Use secret managers (AWS Secrets Manager, HashiCorp Vault, etc.) Rotacione credenciais regularmente Use credenciais separadas para Sandbox e Produção HTTPS Obrigatório Python # ✅ Sempre HTTPS
base_url = "https://apis.pontotel.com.br"
# ❌ Nunca HTTP
base_url = "http://apis.pontotel.com.br"
Idempotência Operações idempotentes podem ser seguramente repetidas sem efeitos duplicados.
Buscar antes de criar Python def criar_ou_atualizar_empregado ( dados : dict , headers : dict ) -> dict :
"""Garante idempotência verificando antes de criar"""
# 1. Verificar se já existe
existente = buscar_empregado ( dados [ "cpf" ], dados [ "empregador_id" ], headers )
if existente :
# 2. Atualizar se necessário
if dados_diferentes ( existente , dados ):
return atualizar_empregado ( existente [ "id" ], dados , headers )
return existente
# 3. Criar apenas se não existir
return criar_empregado ( dados , headers )
Exemplos de Código por Linguagem Python JavaScript
Python import requests
import os
from datetime import datetime , timedelta
class PontotelClient :
BASE_URL = "https://apis.pontotel.com.br/pontotel/api/v4"
def __init__ ( self ):
self . session = requests . Session ()
self . token = None
self . token_expires_at = None
def _ensure_authenticated ( self ):
if not self . token or datetime . now () >= self . token_expires_at :
self . _login ()
def _login ( self ):
r = self . session . post ( f " { self . BASE_URL } /login/" , json = {
"username" : os . getenv ( "PONTOTEL_USERNAME" ),
"password" : os . getenv ( "PONTOTEL_PASSWORD" )
})
r . raise_for_status ()
data = r . json ()
self . token = data [ "access_token" ]
self . token_expires_at = datetime . now () + timedelta ( seconds = data [ "expires_in" ] - 60 )
def get ( self , path : str , params : dict = None ) -> dict :
self . _ensure_authenticated ()
r = self . session . get (
f " { self . BASE_URL }{ path } " ,
headers = { "Authorization" : f "Bearer { self . token } " },
params = params
)
r . raise_for_status ()
return r . json ()
def post ( self , path : str , payload : dict ) -> dict :
self . _ensure_authenticated ()
r = self . session . post (
f " { self . BASE_URL }{ path } " ,
headers = { "Authorization" : f "Bearer { self . token } " },
json = payload
)
r . raise_for_status ()
return r . json ()
JavaScript class PontotelClient {
constructor () {
this . baseUrl = 'https://apis.pontotel.com.br/pontotel/api/v4' ;
this . token = null ;
this . tokenExpiresAt = null ;
}
async ensureAuthenticated () {
if ( ! this . token || Date . now () >= this . tokenExpiresAt ) {
await this . login ();
}
}
async login () {
const response = await fetch ( ` ${ this . baseUrl } /login/` , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' },
body : JSON . stringify ({
username : process . env . PONTOTEL_USERNAME ,
password : process . env . PONTOTEL_PASSWORD
})
});
const data = await response . json ();
this . token = data . access_token ;
this . tokenExpiresAt = Date . now () + ( data . expires_in - 60 ) * 1000 ;
}
async get ( path , params = {}) {
await this . ensureAuthenticated ();
const url = new URL ( ` ${ this . baseUrl }${ path } ` );
Object . entries ( params ). forEach (([ k , v ]) => url . searchParams . append ( k , v ));
const response = await fetch ( url , {
headers : { 'Authorization' : `Bearer ${ this . token } ` }
});
if ( ! response . ok ) throw new Error ( `API Error: ${ response . status } ` );
return response . json ();
}
}
Próximos Passos