Skip to main content

Connecting Agents via API

This guide shows how to connect different AI agent frameworks to Conto, enabling them to request and execute payments.

SDK Authentication

All SDK endpoints require the agent’s SDK key in the Authorization header:
Authorization: Bearer conto_agent_xxxxx...

Framework Integrations

OpenAI Assistants

import OpenAI from 'openai';

const openai = new OpenAI();
const CONTO_SDK_KEY = process.env.CONTO_SDK_KEY;

// Define the payment tool for your assistant
const tools = [{
  type: "function",
  function: {
    name: "make_payment",
    description: "Make a payment to a recipient",
    parameters: {
      type: "object",
      properties: {
        amount: { type: "number", description: "Payment amount in USD" },
        recipientAddress: { type: "string", description: "Recipient wallet address" },
        recipientName: { type: "string", description: "Recipient name" },
        purpose: { type: "string", description: "Payment purpose" }
      },
      required: ["amount", "recipientAddress", "purpose"]
    }
  }
}];

// Handle the payment tool call
async function handlePayment(args: {
  amount: number;
  recipientAddress: string;
  recipientName?: string;
  purpose: string;
}) {
  // Step 1: Request payment authorization
  const requestResponse = await fetch('https://conto.finance/api/sdk/payments/request', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${CONTO_SDK_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      amount: args.amount,
      recipientAddress: args.recipientAddress,
      recipientName: args.recipientName,
      purpose: args.purpose,
      category: 'OPERATIONS'
    })
  });

  const request = await requestResponse.json();

  if (request.status === 'DENIED') {
    return { success: false, error: request.reasons.join(', ') };
  }

  if (request.status === 'REQUIRES_APPROVAL') {
    return { success: false, pending: true, message: 'Payment requires manual approval' };
  }

  // Step 2: Execute the approved payment
  const executeResponse = await fetch(
    `https://conto.finance/api/sdk/payments/${request.requestId}/execute`,
    {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${CONTO_SDK_KEY}` }
    }
  );

  const result = await executeResponse.json();

  return {
    success: true,
    transactionHash: result.txHash,
    amount: result.amount,
    explorerUrl: result.explorerUrl
  };
}
In your OpenAI chat loop, check for tool_calls in the response. When the model calls make_payment, extract the arguments, call the Conto API, and send the result back as a tool response message.

Anthropic Claude (Tool Use)

import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic();
const CONTO_SDK_KEY = process.env.CONTO_SDK_KEY;

const tools = [{
  name: "make_payment",
  description: "Make a payment to a recipient using Conto",
  input_schema: {
    type: "object",
    properties: {
      amount: { type: "number", description: "Payment amount in USD" },
      recipientAddress: { type: "string", description: "Recipient wallet address" },
      recipientName: { type: "string", description: "Recipient name" },
      purpose: { type: "string", description: "Payment purpose" }
    },
    required: ["amount", "recipientAddress", "purpose"]
  }
}];

async function runAgent(userMessage: string) {
  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 1024,
    tools: tools,
    messages: [{ role: "user", content: userMessage }]
  });

  for (const block of response.content) {
    if (block.type === "tool_use" && block.name === "make_payment") {
      const result = await executeContoPayment(block.input);
      // Continue conversation with tool result...
    }
  }
}

async function executeContoPayment(input: any) {
  const request = await fetch('https://conto.finance/api/sdk/payments/request', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${CONTO_SDK_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(input)
  }).then(r => r.json());

  if (request.status !== 'APPROVED') {
    return { error: request.reasons?.join(', ') || 'Payment not approved' };
  }

  const result = await fetch(
    `https://conto.finance/api/sdk/payments/${request.requestId}/execute`,
    {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${CONTO_SDK_KEY}` }
    }
  ).then(r => r.json());

  return result;
}

LangChain

import { Tool } from "@langchain/core/tools";

const CONTO_SDK_KEY = process.env.CONTO_SDK_KEY;

class ContoPaymentTool extends Tool {
  name = "conto_payment";
  description = "Make a payment using Conto. Input should be JSON with amount, recipientAddress, and purpose.";

  async _call(input: string): Promise<string> {
    const params = JSON.parse(input);

    const request = await fetch('https://conto.finance/api/sdk/payments/request', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${CONTO_SDK_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        amount: params.amount,
        recipientAddress: params.recipientAddress,
        purpose: params.purpose,
        category: params.category || 'OPERATIONS'
      })
    }).then(r => r.json());

    if (request.status === 'DENIED') {
      return JSON.stringify({ error: `Payment denied: ${request.reasons.join(', ')}` });
    }

    if (request.status === 'REQUIRES_APPROVAL') {
      return JSON.stringify({ pending: true, message: 'Payment requires manual approval', requestId: request.requestId });
    }

    const result = await fetch(
      `https://conto.finance/api/sdk/payments/${request.requestId}/execute`,
      {
        method: 'POST',
        headers: { 'Authorization': `Bearer ${CONTO_SDK_KEY}` }
      }
    ).then(r => r.json());

    return JSON.stringify({
      success: true,
      transactionHash: result.txHash,
      amount: result.amount,
      explorerUrl: result.explorerUrl
    });
  }
}

Python (Any Framework)

import os
import requests

CONTO_SDK_KEY = os.environ.get('CONTO_SDK_KEY')
CONTO_API_URL = 'https://conto.finance/api'

def make_payment(amount: float, recipient_address: str, purpose: str, recipient_name: str = None):
    """Make a payment via Conto API"""

    headers = {
        'Authorization': f'Bearer {CONTO_SDK_KEY}',
        'Content-Type': 'application/json'
    }

    # Step 1: Request authorization
    request_payload = {
        'amount': amount,
        'recipientAddress': recipient_address,
        'purpose': purpose,
        'recipientName': recipient_name,
        'category': 'OPERATIONS'
    }

    response = requests.post(
        f'{CONTO_API_URL}/sdk/payments/request',
        headers=headers,
        json=request_payload
    )
    request_data = response.json()

    if request_data.get('status') == 'DENIED':
        return {'success': False, 'error': ', '.join(request_data.get('reasons', []))}

    if request_data.get('status') == 'REQUIRES_APPROVAL':
        return {'success': False, 'pending': True, 'requestId': request_data['requestId']}

    # Step 2: Execute the payment
    execute_response = requests.post(
        f'{CONTO_API_URL}/sdk/payments/{request_data["requestId"]}/execute',
        headers=headers
    )
    result = execute_response.json()

    return {
        'success': True,
        'transactionHash': result.get('txHash'),
        'amount': result.get('amount'),
        'explorerUrl': result.get('explorerUrl')
    }

Payment Endpoints Reference

EndpointMethodDescription
/api/sdk/payments/requestPOSTRequest payment authorization
/api/sdk/payments/approvePOSTApprove payment for external wallet
/api/sdk/payments/{id}/executePOSTExecute approved payment
/api/sdk/payments/{id}/confirmPOSTConfirm external wallet payment
/api/sdk/payments/{id}GETGet payment status

Error Handling

StatusCodeDescription
400INVALID_INPUTInvalid request data
401AUTH_FAILEDInvalid SDK key
403AGENT_SUSPENDEDAgent is suspended
403INSUFFICIENT_BALANCEWallet balance too low
403SPEND_LIMIT_EXCEEDEDSpending limit reached
403TIME_WINDOW_VIOLATIONOutside allowed hours
429RATE_LIMITEDToo many requests
For full error handling patterns, see Error Handling.

Next Steps

Make Your First Payment

Detailed payment flow walkthrough

SDK Reference

Full SDK documentation

Examples

Complete integration examples

Error Handling

Handle errors gracefully