ChatGPT / OpenAI
Configure a BSPAY como ferramenta no ChatGPT e OpenAI API com Function Calling
Guia de integração via ChatGPT (prompt direto), GPT Builder (Custom GPTs) e OpenAI API com Function Calling.
O catálogo completo de endpoints, HMAC, webhooks e erros vive em Integração com IA. Este guia é específico do OpenAI.
Prompt direto no ChatGPT
Cole o bloco abaixo no início da conversa para que o ChatGPT entenda a API:
Você é um assistente especializado na BSPAY API v2.
## Identidade da API
- Base URL: https://api.bspay.co
- Auth: OAuth2 Client Credentials → Bearer JWT (1h)
- Resposta sucesso: { "success": true, "data": {...}, "request_id": "...", "timestamp": "..." }
- Resposta erro: { "success": false, "error": { "code": "...", "message": "...", "group": "...", "retryable": bool } }
## HMAC (rotas financeiras)
cashout, internal_transfers/payment, conversions/new exigem 3 headers extras:
X-Signature: hex(hmac_sha256(timestamp + "." + nonce + "." + body, signing_key))
X-Timestamp: <unix_seconds>
X-Nonce: <uuid_v4>
Janela ±5min, nonce único últimos 5min.
## Endpoints (resumo)
GET /v2/account/balance | /info/profile | /limits | /fees
POST /v2/transactions/cashin { amount, currency, chain?, external_id, payer, postback_url }
POST /v2/transactions/cashout { external_id, amount, currency, key, key_type?, network?, name?, bank_code? } [HMAC]
POST /v2/transactions/wallet { currency, chain? }
POST /v2/internal_transfers/payment { username, amount, currency, external_id? } [HMAC]
POST /v2/conversions/rate | /simulate | /new { amount, base_currency, destination_currency, external_id? }
POST /v2/account/transactions/list { page, page_size, status?, type?, source?, currency?, from_date?, to_date? }
GET /v2/account/infractions { page?, page_size?, status?, type? }
GET /v2/account/infractions/detail?id=<uuid>
POST /v2/account/infractions/reply (multipart: id, message, files[])
## Eventos webhook
cashin.{confirmed,refunded,expired} | cashout.{confirmed,failed,refunded} | wallet_deposit
transfer.confirmed | conversion.confirmed | chargeback.opened | chargeback.opened|chargeback.won|chargeback.lost|chargeback.canceled
## Status do ciclo de vida
pending → confirmed | failed | cancelled | refunded
## Moedas
BRL (PIX), MXN (SPEI), USDT, USDC, BTC, ETH, SOL, BNB
## Chains
USDT: tron, ethereum, bsc, polygon, solana
USDC: tron, ethereum, bsc, polygon, solana
BTC: bitcoin · ETH: ethereum · SOL: solana · BNB: bsc
## chain vs network
- `chain` (cashin/wallet): blockchain de origem
- `network` (cashout): rede de transmissão (pode ser L2)
Gere código limpo, com tratamento de erros e comentários em português.
GPT Customizado (GPT Builder)
No ChatGPT Plus/Team/Enterprise você pode criar um GPT dedicado:
- chat.openai.com → Explorar GPTs → Criar
- Configure:
- Nome:
BSPAY Assistant - Descrição:
Assistente para integrar com a BSPAY API v2 - Instruções: cole o prompt acima
- Nome:
- Conhecimento: faça upload da página
/ai/llm-integration(Markdown) - Actions (opcional, pra executar API real):
openapi: 3.1.0
info:
title: BSPAY API
version: "2"
servers:
- url: https://api.bspay.co
components:
securitySchemes:
bearer: { type: http, scheme: bearer }
security:
- bearer: []
paths:
/v2/transactions/cashin:
post:
operationId: createCashin
summary: Criar cobrança PIX/cripto/SPEI
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [amount, currency, external_id]
properties:
amount: { type: number }
currency: { type: string, enum: [BRL, MXN, USDT, USDC, BTC, ETH, SOL, BNB] }
chain: { type: string }
external_id: { type: string }
postback_url: { type: string, format: uri }
payer:
type: object
properties:
name: { type: string }
document: { type: string }
responses:
"200": { description: OK }
/v2/account/balance:
get:
operationId: getBalance
summary: Consultar saldo
responses:
"200": { description: OK }
/v2/account/transactions/list:
post:
operationId: listTransactions
summary: Extrato de transações
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
page: { type: integer }
page_size: { type: integer }
status: { type: string, enum: [pending, confirmed, cancelled, failed] }
type: { type: string, enum: [cashin, cashout] }
from_date: { type: string }
to_date: { type: string }
responses:
"200": { description: OK }
Custom GPTs não conseguem assinar HMAC nativamente — operações que exigem X-Signature (cashout, transfer, conversion) precisam ir através do seu backend. Exponha endpoints próprios que façam a assinatura e o GPT chama esses.
OpenAI API — Function Calling completo
Implementação Python com auth, HMAC e tools mapeadas pra OpenAI.
import os, json, time, uuid, hmac, hashlib, base64
import requests
from openai import OpenAI
BASE = "https://api.bspay.co"
# ============================================================
# Cliente BSPAY com auth + HMAC
# ============================================================
class BSPayClient:
def __init__(self, client_id: str, client_secret: str, signing_key: str):
self.signing_key = signing_key
creds = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()
r = requests.post(
f"{BASE}/v2/oauth/token",
headers={"Authorization": f"Basic {creds}", "Content-Type": "application/json"},
json={"grant_type": "client_credentials"},
)
r.raise_for_status()
self.token = r.json()["access_token"]
def _headers(self, extra: dict | None = None) -> dict:
h = {"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"}
if extra: h.update(extra)
return h
def _signed_headers(self, body: str) -> dict:
ts = str(int(time.time()))
nonce = str(uuid.uuid4())
sig = hmac.new(self.signing_key.encode(), f"{ts}.{nonce}.{body}".encode(), hashlib.sha256).hexdigest()
return self._headers({"X-Signature": sig, "X-Timestamp": ts, "X-Nonce": nonce})
# --- read ---
def balance(self):
return requests.get(f"{BASE}/v2/account/balance", headers=self._headers()).json()
def list_transactions(self, **filters):
return requests.post(
f"{BASE}/v2/account/transactions/list",
headers=self._headers(), json=filters
).json()
# --- cashin (sem HMAC) ---
def cashin_pix(self, amount, payer_name, payer_document, external_id):
body = {
"amount": amount, "currency": "BRL",
"external_id": external_id,
"payer": {"name": payer_name, "document": payer_document},
}
return requests.post(f"{BASE}/v2/transactions/cashin", headers=self._headers(), json=body).json()
def cashin_crypto(self, amount, currency, chain, external_id):
body = {"amount": amount, "currency": currency, "chain": chain, "external_id": external_id}
return requests.post(f"{BASE}/v2/transactions/cashin", headers=self._headers(), json=body).json()
# --- cashout (com HMAC) ---
def cashout_pix(self, amount, key, key_type, external_id, description=""):
body = json.dumps({
"external_id": external_id, "amount": amount, "currency": "BRL",
"key": key, "key_type": key_type, "description": description,
}, separators=(",", ":"))
return requests.post(f"{BASE}/v2/transactions/cashout", headers=self._signed_headers(body), data=body).json()
def cashout_crypto(self, amount, currency, key, network, external_id):
body = json.dumps({
"external_id": external_id, "amount": amount, "currency": currency,
"key": key, "network": network,
}, separators=(",", ":"))
return requests.post(f"{BASE}/v2/transactions/cashout", headers=self._signed_headers(body), data=body).json()
# --- conversion (com HMAC) ---
def convert(self, amount, base_currency, destination_currency, external_id=None):
body = json.dumps({
"amount": amount,
"base_currency": base_currency,
"destination_currency": destination_currency,
"external_id": external_id or str(uuid.uuid4()),
}, separators=(",", ":"))
return requests.post(f"{BASE}/v2/conversions/new", headers=self._signed_headers(body), data=body).json()
# ============================================================
# Tools OpenAI (Function Calling)
# ============================================================
TOOLS = [
{"type": "function", "function": {
"name": "get_balance",
"description": "Consulta o saldo da conta em todas as moedas.",
"parameters": {"type": "object", "properties": {}},
}},
{"type": "function", "function": {
"name": "cashin_pix",
"description": "Gera QR Code PIX para receber pagamento em BRL.",
"parameters": {
"type": "object",
"required": ["amount", "payer_name", "payer_document", "external_id"],
"properties": {
"amount": {"type": "number", "description": "Valor em BRL"},
"payer_name": {"type": "string"},
"payer_document": {"type": "string", "description": "CPF/CNPJ"},
"external_id": {"type": "string", "description": "ID único para idempotência"},
},
},
}},
{"type": "function", "function": {
"name": "cashout_pix",
"description": "Envia PIX (saque). Exige confirmação humana antes de chamar.",
"parameters": {
"type": "object",
"required": ["amount", "key", "key_type", "external_id"],
"properties": {
"amount": {"type": "number"},
"key": {"type": "string", "description": "Chave PIX"},
"key_type": {"type": "string", "enum": ["cpf", "cnpj", "email", "phone", "random"]},
"external_id": {"type": "string"},
"description": {"type": "string"},
},
},
}},
{"type": "function", "function": {
"name": "list_transactions",
"description": "Lista transações com filtros (paginado).",
"parameters": {
"type": "object",
"properties": {
"page": {"type": "integer", "default": 1},
"page_size": {"type": "integer", "default": 20},
"status": {"type": "string", "enum": ["pending", "confirmed", "cancelled", "failed"]},
"type": {"type": "string", "enum": ["cashin", "cashout"]},
"currency": {"type": "string"},
"from_date": {"type": "string", "description": "YYYY-MM-DD"},
"to_date": {"type": "string"},
},
},
}},
{"type": "function", "function": {
"name": "convert",
"description": "Converte uma moeda em outra (movimenta saldo)",
"parameters": {
"type": "object",
"required": ["amount", "base_currency", "destination_currency"],
"properties": {
"amount": {"type": "number"},
"base_currency": {"type": "string"},
"destination_currency": {"type": "string"}, },
},
}},
]
# ============================================================
# Loop de chat
# ============================================================
def run():
bspay = BSPayClient(
os.environ["BSPAY_CLIENT_ID"],
os.environ["BSPAY_CLIENT_SECRET"],
os.environ["BSPAY_SIGNING_KEY"],
)
openai = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
messages = [
{"role": "system", "content": "Você é um assistente financeiro com acesso à BSPAY. SEMPRE confirme com o usuário antes de chamar funções que movem dinheiro (cashout/convert)."},
{"role": "user", "content": "Gere um QR Code PIX de R$ 200 para Maria Silva, CPF 98765432100."},
]
while True:
resp = openai.chat.completions.create(model="gpt-4o", messages=messages, tools=TOOLS)
msg = resp.choices[0].message
messages.append(msg)
if not msg.tool_calls:
print(msg.content)
return
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
method = getattr(bspay, call.function.name)
result = method(**args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
run()
Boas práticas para ChatGPT
Confirmação humana sempre
Cashout, transferência interna e conversão movem dinheiro. Configure o GPT pra confirmar valor + destino antes de executar.
Não exponha credenciais
signing_key e client_secret ficam só no servidor. O GPT chama um endpoint seu que assina e repassa.
Idempotência via external_id
Gere uuid.uuid4() no backend e passe pro tool call. Em retries do GPT, o mesmo external_id retorna a mesma transação.
Rate limit do OAuth
/v2/oauth/token tem 30 reqs/min. Cache o token (1h de validade) — não re-autentique a cada request.
Function Calling vs Actions: Use Function Calling (OpenAI API) para apps próprios; use Actions (GPT Builder) para GPTs públicos sem precisar de backend pra chamadas read-only. Para HMAC, Function Calling é obrigatório (server-side signing).
