Skip to main content

Make Your First Payment

This guide walks you through making your first payment using the Conto SDK.

Prerequisites

Before making a payment, ensure you have:

Payment Flow Overview

Option 1: Simple Payment (Request + Execute)

Use payments.pay() for a simple one-step payment:
import { Conto } from '@conto/sdk';

const conto = new Conto({
  apiKey: process.env.CONTO_API_KEY
});

async function makePayment() {
  const result = await conto.payments.pay({
    amount: 50.00,
    recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...',
    recipientName: 'OpenAI',
    purpose: 'GPT-4 API credits',
    category: 'AI_SERVICES'
  });

  console.log('Payment successful!');
  console.log('Transaction ID:', result.transactionId);
  console.log('TX Hash:', result.txHash);
  console.log('Explorer:', result.explorerUrl);
}
payments.pay() throws an error if the payment is denied or requires approval.

Option 2: Two-Step Payment (More Control)

For more control, use separate request and execute calls:

Step 1: Request Authorization

const request = await conto.payments.request({
  amount: 50.00,
  recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...',
  recipientName: 'OpenAI',
  purpose: 'GPT-4 API credits',
  category: 'AI_SERVICES'
});

console.log('Request ID:', request.requestId);
console.log('Status:', request.status);

Step 2: Handle the Response

switch (request.status) {
  case 'APPROVED':
    console.log('Payment approved!');
    console.log('Wallet:', request.wallet.address);
    console.log('Expires at:', request.expiresAt);
    // Proceed to execute
    break;

  case 'DENIED':
    console.log('Payment denied');
    console.log('Reasons:', request.reasons);
    if (request.violations) {
      request.violations.forEach(v => {
        console.log(`- ${v.type}: ${v.message}`);
      });
    }
    break;

  case 'REQUIRES_APPROVAL':
    console.log('Payment requires manual approval');
    console.log('Request ID:', request.requestId);
    // Notify someone to approve in the dashboard
    break;
}

Step 3: Execute (if Approved)

if (request.status === 'APPROVED') {
  const result = await conto.payments.execute(request.requestId);

  console.log('Payment executed!');
  console.log('TX Hash:', result.txHash);
  console.log('Status:', result.status);
}

Payment Parameters

ParameterRequiredDescription
amountYesPayment amount
recipientAddressYesEthereum address (0x…)
recipientNameNoHuman-readable name
purposeNoWhy this payment is needed
categoryNoSpending category
walletIdNoSpecific wallet to use
urgencyNoLOW, NORMAL, HIGH, CRITICAL
contextNoAdditional metadata (JSON)

Common Categories

const categories = [
  'INFRASTRUCTURE',  // Cloud, hosting, compute
  'AI_SERVICES',     // AI APIs, model training
  'MARKETING',       // Ads, promotions
  'OPERATIONS',      // General operations
  'VENDOR',          // Vendor payments
  'EMPLOYEE',        // Employee reimbursements
];

Checking Payment Status

After executing, you can check the status:
const status = await conto.payments.status(requestId);

console.log('Status:', status.status);
// PENDING → APPROVED → COMPLETED
// or PENDING → DENIED
// or PENDING → EXPIRED

if (status.transaction) {
  console.log('TX Hash:', status.transaction.txHash);
  console.log('TX Status:', status.transaction.status);
  // PENDING → CONFIRMING → CONFIRMED
  console.log('Block:', status.transaction.blockNumber);
}

Complete Example

import { Conto, ContoError } from '@conto/sdk';

const conto = new Conto({
  apiKey: process.env.CONTO_API_KEY
});

async function payVendor(vendor: string, amount: number, purpose: string) {
  try {
    // Request authorization
    const request = await conto.payments.request({
      amount,
      recipientAddress: vendor,
      purpose,
      category: 'VENDOR'
    });

    // Handle different statuses
    if (request.status === 'DENIED') {
      console.error('Payment denied:', request.reasons.join(', '));
      return null;
    }

    if (request.status === 'REQUIRES_APPROVAL') {
      console.log('Payment needs approval. Request ID:', request.requestId);
      return { pending: true, requestId: request.requestId };
    }

    // Execute the payment
    const result = await conto.payments.execute(request.requestId);

    console.log(`Paid $${amount} to ${vendor}`);
    console.log(`TX: ${result.txHash}`);

    return result;

  } catch (error) {
    if (error instanceof ContoError) {
      console.error(`Payment error [${error.code}]:`, error.message);
    } else {
      console.error('Unexpected error:', error);
    }
    return null;
  }
}

// Usage
await payVendor(
  '0x742d35Cc6634C0532925a3b844Bc9e7595f...',
  100.00,
  'Monthly subscription'
);

Verifying in Dashboard

After making a payment:
  1. Go to Transactions in the dashboard
  2. Find your transaction by ID or recipient
  3. Check the status and block explorer link
  4. View the audit trail for full details

Troubleshooting

Your wallet doesn’t have enough funds. Fund your wallet in the dashboard.
You’ve exceeded your daily spending limit. Wait until the limit resets or increase it in agent settings.
The transaction is outside allowed hours. Check your time window settings.
Invalid or expired API key. Generate a new SDK key in the dashboard.
Too many requests. Wait and retry. Check the Retry-After header.

Next Steps