Pular para o conteúdo principal

Exemplos Python

Exemplos completos utilizando a biblioteca requests. Compativel com Python 3.8+.

Instalacao

pip install requests

Cliente API Completo

import os
import time
import requests
from typing import Optional


class TesselysApiClient:
"""Cliente para a API Externa Tesselys."""

def __init__(self, api_key: str, secret: str):
self.base_url = "https://api.tesselys.com.br/external/v1"
self.api_key = api_key
self.secret = secret
self.access_token: Optional[str] = None
self.company_token: Optional[str] = None
self.expires_at: float = 0
self.session = requests.Session()
self.session.headers.update({"Content-Type": "application/json"})

def authenticate(self) -> dict:
"""Autentica com API Key e Secret. Armazena tokens para uso subsequente."""
response = requests.post(
f"{self.base_url}/auth",
json={"secret": self.secret},
headers={
"Content-Type": "application/json",
"x-api-key": self.api_key,
},
)
response.raise_for_status()
data = response.json()

self.access_token = data["accessToken"]
self.company_token = data["companyToken"]
self.expires_at = time.time() + data["expiresIn"]

self.session.headers.update({
"Authorization": f"Bearer {self.access_token}",
"x-company-token": self.company_token,
})

return data

def _ensure_auth(self):
"""Verifica se o token esta valido. Renova se necessario."""
if not self.access_token or time.time() >= self.expires_at - 60:
self.authenticate()

def _request(self, method: str, path: str, **kwargs) -> dict:
"""Executa uma requisicao com retry automatico para 401."""
self._ensure_auth()

url = f"{self.base_url}{path}"
response = self.session.request(method, url, **kwargs)

# Se 401, tenta renovar token e repetir
if response.status_code == 401:
self.authenticate()
response = self.session.request(method, url, **kwargs)

# Se 429, aguarda e tenta novamente
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
response = self.session.request(method, url, **kwargs)

response.raise_for_status()
return response.json()

# ─── Pessoas ──────────────────────────────────────────────

def list_persons(self, **params) -> dict:
"""Lista pessoas com paginacao e filtros."""
return self._request("GET", "/persons", params=params)

def get_person(self, person_id: str) -> dict:
"""Busca uma pessoa por ID."""
return self._request("GET", f"/persons/{person_id}")

def create_person(self, data: dict) -> dict:
"""Cria uma nova pessoa."""
return self._request("POST", "/persons", json=data)

def update_person(self, person_id: str, data: dict) -> dict:
"""Atualiza uma pessoa existente."""
return self._request("PUT", f"/persons/{person_id}", json=data)

# ─── Negocios ─────────────────────────────────────────────

def list_deals(self, **params) -> dict:
"""Lista negocios com paginacao e filtros."""
return self._request("GET", "/deals", params=params)

def get_deal(self, deal_id: str) -> dict:
"""Busca um negocio por ID."""
return self._request("GET", f"/deals/{deal_id}")

def create_deal(self, data: dict) -> dict:
"""Cria um novo negocio."""
return self._request("POST", "/deals", json=data)

def update_deal(self, deal_id: str, data: dict) -> dict:
"""Atualiza um negocio existente."""
return self._request("PUT", f"/deals/{deal_id}", json=data)

# ─── Lancamentos Financeiros ──────────────────────────────

def list_financial_entries(self, **params) -> dict:
"""Lista lancamentos financeiros com paginacao e filtros."""
return self._request("GET", "/financial-entries", params=params)

def get_financial_entry(self, entry_id: str) -> dict:
"""Busca um lancamento financeiro por ID."""
return self._request("GET", f"/financial-entries/{entry_id}")

def create_financial_entry(self, data: dict) -> dict:
"""Cria um novo lancamento financeiro."""
return self._request("POST", "/financial-entries", json=data)

# ─── Produtos ─────────────────────────────────────────────

def list_products(self, **params) -> dict:
"""Lista produtos com paginacao e filtros."""
return self._request("GET", "/products", params=params)

def create_product(self, data: dict) -> dict:
"""Cria um novo produto."""
return self._request("POST", "/products", json=data)

def update_product(self, product_id: str, data: dict) -> dict:
"""Atualiza um produto existente."""
return self._request("PUT", f"/products/{product_id}", json=data)

# ─── Projetos ─────────────────────────────────────────────

def list_projects(self, **params) -> dict:
"""Lista projetos com paginacao e filtros."""
return self._request("GET", "/projects", params=params)

def create_project(self, data: dict) -> dict:
"""Cria um novo projeto."""
return self._request("POST", "/projects", json=data)

Uso Basico

import os
from tesselys_client import TesselysApiClient


def main():
client = TesselysApiClient(
api_key=os.environ["TESSELYS_API_KEY"], # tesselys_ak_...
secret=os.environ["TESSELYS_API_SECRET"], # base64url string
)

# 1. Autenticar
client.authenticate()
print("Autenticado com sucesso!")

# 2. Criar uma pessoa
person = client.create_person({
"name": "Empresa Exemplo Ltda",
"documentNumber": "12345678000190",
"personType": "COMPANY",
"email": "contato@exemplo.com.br",
"classifications": ["CUSTOMER"],
"tags": ["novo-cliente"],
})
print(f"Pessoa criada: {person['id']}")

# 3. Criar um negocio vinculado
deal = client.create_deal({
"title": "Proposta Comercial - Empresa Exemplo",
"customerId": person["id"],
"dealType": "COMMERCIAL",
"dealPipelineId": "seu-pipeline-id",
"amount": 25000.00,
"expectedCloseDate": "2026-06-30",
})
print(f"Negocio criado: {deal['id']} ({deal['code']})")

# 4. Listar clientes PJ
customers = client.list_persons(
personType="COMPANY",
classification="CUSTOMER",
page=1,
limit=10,
)
print(f"Total de clientes PJ: {customers['meta']['total']}")

# 5. Criar lancamento financeiro
entry = client.create_financial_entry({
"personId": person["id"],
"title": "Fatura de Servico - Abril/2026",
"typeCategory": "REVENUE",
"originalAmount": 12500.00,
"originalDueDate": "2026-04-15",
"financialCategoryId": "sua-categoria-id",
"bankAccountId": "sua-conta-id",
"paymentMethod": "BANK_SLIP",
})
print(f"Lancamento criado: {entry['id']} ({entry['code']})")

# 6. Listar lancamentos pendentes do mes
entries = client.list_financial_entries(
typeCategory="REVENUE",
status="PENDING",
dueDateFrom="2026-04-01",
dueDateTo="2026-04-30",
)
total_pending = sum(e["originalAmount"] for e in entries["data"])
print(f"Receitas pendentes em abril: R$ {total_pending:,.2f}")


if __name__ == "__main__":
main()

Tratamento de Erros

import os
from requests.exceptions import HTTPError, ConnectionError, Timeout
from tesselys_client import TesselysApiClient


def safe_operation():
client = TesselysApiClient(
api_key=os.environ["TESSELYS_API_KEY"],
secret=os.environ["TESSELYS_API_SECRET"],
)

try:
client.authenticate()

person = client.create_person({
"name": "Teste",
"personType": "INDIVIDUAL",
"documentNumber": "00000000000", # CPF invalido
})

except HTTPError as e:
response = e.response
status = response.status_code

try:
error_data = response.json()
except ValueError:
print(f"Erro {status}: resposta nao e JSON")
return

friendly_message = error_data.get("friendlyMessage", "Erro desconhecido")
error_code = error_data.get("message", "")

if status == 400:
print(f"Dados invalidos: {friendly_message}")
# Verificar erros de campo
field_errors = error_data.get("errors", [])
for err in field_errors:
print(f" Campo '{err['field']}': {err['message']}")

elif status == 401:
print(f"Nao autorizado: {friendly_message}")

elif status == 404:
print(f"Nao encontrado: {friendly_message}")

elif status == 429:
retry_after = response.headers.get("Retry-After", "60")
print(f"Rate limit excedido. Tente novamente em {retry_after}s.")

elif status >= 500:
print(f"Erro interno do servidor: {friendly_message}")
print("Tente novamente em alguns segundos.")

else:
print(f"Erro {status}: {friendly_message}")

except ConnectionError:
print("Erro de conexao. Verifique sua rede e tente novamente.")

except Timeout:
print("Timeout na requisicao. Tente novamente.")


if __name__ == "__main__":
safe_operation()

Paginacao Automatica

def fetch_all_persons(client: TesselysApiClient, **filters) -> list:
"""Busca todas as pessoas iterando por todas as paginas."""
all_persons = []
page = 1
limit = 100

while True:
result = client.list_persons(page=page, limit=limit, **filters)
all_persons.extend(result["data"])

if page >= result["meta"]["totalPages"]:
break

page += 1

return all_persons


# Uso
client = TesselysApiClient(os.environ["TESSELYS_API_KEY"], os.environ["TESSELYS_API_SECRET"])
client.authenticate()

all_customers = fetch_all_persons(client, personType="COMPANY", classification="CUSTOMER")
print(f"Total de clientes PJ: {len(all_customers)}")