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.


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:

  1. chat.openai.com → Explorar GPTs → Criar
  2. Configure:
    • Nome: BSPAY Assistant
    • Descrição: Assistente para integrar com a BSPAY API v2
    • Instruções: cole o prompt acima
  3. Conhecimento: faça upload da página /ai/llm-integration (Markdown)
  4. 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 }

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.

Esta página foi útil?