Back to Documentation

Sir Chargly - API Integration Guide

Complete guide to integrating Sir Chargly's convenience fee platform into your application.

Table of Contents

  • Quick Start
  • Authentication
  • API Endpoints
  • SDK Usage
  • Webhooks
  • Error Handling
  • Testing
  • Production Deployment

  • Quick Start

    1. Install the SDK

    npm install @sirchargly/sdk
    # or
    yarn add @sirchargly/sdk
    

    2. Set Up Environment Variables

    Create a .env.local file in your project root:

    # Development keys (from onboarding)
    SIRCHARGLEY_PUBLISHABLE_KEY=pk_dev_sirchargly_...
    SIRCHARGLEY_SECRET_KEY=sk_dev_sirchargly_...
    
    # Production keys (when ready to go live)
    # SIRCHARGLEY_PUBLISHABLE_KEY=pk_prod_sirchargly_...
    # SIRCHARGLEY_SECRET_KEY=sk_prod_sirchargly_...
    

    3. Basic Integration

    import { SirChargly } from '@sirchargly/sdk';
    
    // Initialize with publishable key
    const chargly = new SirChargly(
      process.env.NEXT_PUBLIC_SIRCHARGLEY_PUBLISHABLE_KEY!
    );
    
    // Create a payment with automatic fee calculation
    const payment = await chargly.payments.create({
      amount: 10000, // $100.00 in cents
      currency: 'usd',
      customer: 'cus_123',
    });
    
    console.log(payment);
    // {
    //   id: 'pay_...',
    //   amount: 10000,
    //   convenienceFee: 320, // $3.20
    //   totalAmount: 10320, // $103.20
    //   ...
    // }
    

    Authentication

    Sir Chargly uses API keys for authentication. There are two types:

    Publishable Keys

    Format: pk_dev_sirchargly_... or pk_prod_sirchargly_...

  • Used in client-side code
  • Safe to expose in frontend JavaScript
  • Used to initialize the SDK
  • Automatically detects environment (dev/prod) from prefix
  • Usage:

    // Client-side (React, Vue, etc.)
    const chargly = new SirChargly('pk_dev_sirchargly_...');
    

    Secret Keys

    Format: sk_dev_sirchargly_... or sk_prod_sirchargly_...

  • Used in server-side code only
  • NEVER expose in client-side code
  • Used for authenticated API requests
  • Has full access to your account
  • Usage:

    // Server-side (API routes, backend)
    const response = await fetch('https://api.sirchargly.com/v1/charges', {
      headers: {
        'Authorization': `Bearer ${process.env.SIRCHARGLEY_SECRET_KEY}`,
        'Content-Type': 'application/json',
      },
    });
    

    Environment Detection

    Keys automatically determine the environment:

  • pk_dev_* / sk_dev_* → Development mode (test data)
  • pk_prod_* / sk_prod_* → Production mode (live data)

  • API Endpoints

    Base URL: https://api.sirchargly.com/v1

    Calculate Fee

    Estimate convenience fee for a transaction

    POST /v1/estimates
    Authorization: Bearer sk_dev_sirchargly_...
    Content-Type: application/json
    
    {
      "amount": 10000,
      "currency": "usd",
      "region": "US-CA",
      "cardType": "credit"
    }
    

    Response:

    {
      "baseAmount": 10000,
      "convenienceFee": 320,
      "totalAmount": 10320,
      "feeBreakdown": {
        "percentage": 290,
        "flatFee": 30
      },
      "compliant": true,
      "region": "US-CA"
    }
    

    Create Charge

    Process a payment with convenience fee

    POST /v1/charges
    Authorization: Bearer sk_dev_sirchargly_...
    Content-Type: application/json
    
    {
      "amount": 10000,
      "currency": "usd",
      "customer": "cus_123",
      "description": "Order #1234",
      "metadata": {
        "orderId": "1234"
      }
    }
    

    Response:

    {
      "id": "ch_sirchargly_...",
      "object": "charge",
      "amount": 10000,
      "convenienceFee": 320,
      "totalAmount": 10320,
      "currency": "usd",
      "customer": "cus_123",
      "status": "succeeded",
      "created": 1704067200,
      "metadata": {
        "orderId": "1234"
      }
    }
    

    List Charges

    Get all charges for your account

    GET /v1/charges?limit=10&starting_after=ch_...
    Authorization: Bearer sk_dev_sirchargly_...
    

    Response:

    {
      "object": "list",
      "data": [
        { /* charge object */ },
        { /* charge object */ }
      ],
      "has_more": true,
      "url": "/v1/charges"
    }
    

    Get Fee Configuration

    Retrieve your current fee settings

    GET /v1/fee-configs
    Authorization: Bearer sk_dev_sirchargly_...
    

    Response:

    {
      "percentage": 2.9,
      "flatFee": 0.30,
      "billingMode": "direct",
      "regions": {
        "US-CA": {
          "maxPercentage": 4.0,
          "requiresDisclosure": true
        }
      }
    }
    

    Update Fee Configuration

    Change your fee settings

    POST /v1/fee-configs
    Authorization: Bearer sk_dev_sirchargly_...
    Content-Type: application/json
    
    {
      "percentage": 3.0,
      "flatFee": 0.35
    }
    

    Regional Compliance

    Check compliance rules for a region

    GET /v1/regions/US-CA
    Authorization: Bearer sk_dev_sirchargly_...
    

    Response:

    {
      "regionCode": "US-CA",
      "country": "US",
      "state": "California",
      "allowedCardTypes": ["credit", "debit"],
      "maxPercentage": 4.0,
      "maxFlatFee": 2.0,
      "requiresDisclosure": true,
      "disclosureText": "A convenience fee of X% will be added to this transaction."
    }
    

    SDK Usage

    Initialization

    import { SirChargly } from '@sirchargly/sdk';
    
    const chargly = new SirChargly(
      process.env.NEXT_PUBLIC_SIRCHARGLEY_PUBLISHABLE_KEY!,
      {
        apiVersion: '2025-01',
        timeout: 30000, // 30 seconds
      }
    );
    

    Creating Payments

    // Simple payment
    const payment = await chargly.payments.create({
      amount: 10000,
      currency: 'usd',
      customer: 'cus_123',
    });
    
    // With metadata
    const payment = await chargly.payments.create({
      amount: 10000,
      currency: 'usd',
      customer: 'cus_123',
      metadata: {
        orderId: '1234',
        productId: 'prod_456',
      },
    });
    
    // With specific region
    const payment = await chargly.payments.create({
      amount: 10000,
      currency: 'usd',
      customer: 'cus_123',
      region: 'US-TX',
    });
    

    Estimating Fees

    // Get fee estimate before charging
    const estimate = await chargly.estimates.create({
      amount: 10000,
      currency: 'usd',
      region: 'US-CA',
      cardType: 'credit',
    });
    
    console.log(`Base: $${estimate.baseAmount / 100}`);
    console.log(`Fee: $${estimate.convenienceFee / 100}`);
    console.log(`Total: $${estimate.totalAmount / 100}`);
    

    Retrieving Charges

    // Get a specific charge
    const charge = await chargly.charges.retrieve('ch_sirchargly_...');
    
    // List all charges
    const charges = await chargly.charges.list({
      limit: 10,
    });
    
    // List with filters
    const charges = await chargly.charges.list({
      limit: 25,
      created: {
        gte: Math.floor(Date.now() / 1000) - 30 * 24 * 60 * 60, // Last 30 days
      },
    });
    

    Fee Configuration

    // Get current config
    const config = await chargly.feeConfigs.retrieve();
    
    // Update config
    const newConfig = await chargly.feeConfigs.update({
      percentage: 3.0,
      flatFee: 0.35,
    });
    

    Regional Compliance

    // Get region info
    const region = await chargly.regions.retrieve('US-CA');
    
    // Check if a fee structure is compliant
    const isCompliant = await chargly.regions.checkCompliance({
      region: 'US-CA',
      percentage: 3.5,
      flatFee: 0.30,
      cardType: 'credit',
    });
    

    Webhooks

    Sir Chargly sends webhooks for various events to keep your system in sync.

    Setting Up Webhooks

  • Go to Dashboard → Settings → Webhooks
  • Click "Add Endpoint"
  • Enter your webhook URL: https://yourdomain.com/api/webhooks/sirchargly
  • Select events to receive
  • Copy the signing secret
  • Webhook Events

    charge.succeeded

    {
      "id": "evt_...",
      "type": "charge.succeeded",
      "data": {
        "object": {
          "id": "ch_sirchargly_...",
          "amount": 10000,
          "convenienceFee": 320,
          "status": "succeeded"
        }
      },
      "created": 1704067200
    }
    

    charge.failed

    {
      "id": "evt_...",
      "type": "charge.failed",
      "data": {
        "object": {
          "id": "ch_sirchargly_...",
          "amount": 10000,
          "status": "failed",
          "failureCode": "card_declined",
          "failureMessage": "Your card was declined"
        }
      },
      "created": 1704067200
    }
    

    fee_config.updated

    {
      "id": "evt_...",
      "type": "fee_config.updated",
      "data": {
        "object": {
          "percentage": 3.0,
          "flatFee": 0.35,
          "billingMode": "direct"
        }
      },
      "created": 1704067200
    }
    

    Verifying Webhooks (Next.js App Router)

    import { NextRequest, NextResponse } from 'next/server';
    import { headers } from 'next/headers';
    import { SirChargly } from '@sirchargly/sdk';
    
    const webhookSecret = process.env.SIRCHARGLEY_WEBHOOK_SECRET!;
    
    export async function POST(req: NextRequest) {
      const body = await req.text();
      const signature = headers().get('sirchargly-signature');
    
      if (!signature) {
        return NextResponse.json(
          { error: 'Missing signature' },
          { status: 400 }
        );
      }
    
      // Verify the webhook signature
      let event;
      try {
        event = SirChargly.webhooks.constructEvent(
          body,
          signature,
          webhookSecret
        );
      } catch (err) {
        return NextResponse.json(
          { error: 'Invalid signature' },
          { status: 400 }
        );
      }
    
      // Handle the event
      switch (event.type) {
        case 'charge.succeeded':
          const charge = event.data.object;
          console.log('Charge succeeded:', charge.id);
          // Update your database, send confirmation email, etc.
          break;
    
        case 'charge.failed':
          const failedCharge = event.data.object;
          console.log('Charge failed:', failedCharge.id);
          // Notify customer, log for review, etc.
          break;
    
        case 'fee_config.updated':
          const config = event.data.object;
          console.log('Fee config updated:', config);
          // Update cached config, notify admin, etc.
          break;
    
        default:
          console.log('Unhandled event type:', event.type);
      }
    
      return NextResponse.json({ received: true });
    }
    

    Error Handling

    Error Types

    try {
      const payment = await chargly.payments.create({
        amount: 10000,
        currency: 'usd',
      });
    } catch (error) {
      if (error.type === 'AuthenticationError') {
        // Invalid API key
        console.error('Authentication failed');
      } else if (error.type === 'InvalidRequestError') {
        // Invalid parameters
        console.error('Invalid request:', error.message);
      } else if (error.type === 'APIError') {
        // Server error
        console.error('API error:', error.message);
      } else if (error.type === 'NetworkError') {
        // Network connectivity issue
        console.error('Network error');
      }
    }
    

    Error Responses

    {
      "error": {
        "type": "invalid_request_error",
        "message": "Amount must be at least $0.50",
        "param": "amount",
        "code": "amount_too_small"
      }
    }
    

    Retry Logic

    async function createPaymentWithRetry(
      params: PaymentParams,
      maxRetries = 3
    ) {
      for (let i = 0; i < maxRetries; i++) {
        try {
          return await chargly.payments.create(params);
        } catch (error) {
          if (error.type === 'NetworkError' && i < maxRetries - 1) {
            // Wait before retrying (exponential backoff)
            await new Promise(resolve =>
              setTimeout(resolve, Math.pow(2, i) * 1000)
            );
            continue;
          }
          throw error;
        }
      }
    }
    

    Testing

    Test Mode

    All development keys (pk_dev_*, sk_dev_*) operate in test mode:

  • No real charges are processed
  • Use test card numbers
  • Separate from production data
  • Safe to experiment
  • Test Card Numbers

    Successful Payments:

    4242 4242 4242 4242 (Visa)
    5555 5555 5555 4444 (Mastercard)
    3782 822463 10005 (American Express)
    

    Declined Payments:

    4000 0000 0000 0002 (Card declined)
    4000 0000 0000 9995 (Insufficient funds)
    

    Test Scenarios

    // Test successful payment
    const successfulPayment = await chargly.payments.create({
      amount: 10000,
      currency: 'usd',
      paymentMethod: {
        card: {
          number: '4242424242424242',
          exp_month: 12,
          exp_year: 2025,
          cvc: '123',
        },
      },
    });
    
    // Test declined payment
    try {
      const declinedPayment = await chargly.payments.create({
        amount: 10000,
        currency: 'usd',
        paymentMethod: {
          card: {
            number: '4000000000000002',
            exp_month: 12,
            exp_year: 2025,
            cvc: '123',
          },
        },
      });
    } catch (error) {
      console.log('Expected decline:', error.code); // card_declined
    }
    
    // Test regional compliance
    const californiaPayment = await chargly.payments.create({
      amount: 10000,
      currency: 'usd',
      region: 'US-CA',
    });
    

    Production Deployment

    Pre-Deployment Checklist

  • [ ] Thoroughly tested in development mode
  • [ ] Created production API keys in dashboard
  • [ ] Updated environment variables in production
  • [ ] Configured webhooks with production URL
  • [ ] Set up monitoring and alerts
  • [ ] Reviewed regional compliance requirements
  • [ ] Added error logging and tracking
  • [ ] Set up rate limiting
  • [ ] Configured HTTPS for webhooks
  • [ ] Added API key rotation plan
  • Environment Variables

    Development:

    SIRCHARGLEY_PUBLISHABLE_KEY=pk_dev_sirchargly_...
    SIRCHARGLEY_SECRET_KEY=sk_dev_sirchargly_...
    SIRCHARGLEY_WEBHOOK_SECRET=whsec_dev_...
    

    Production:

    SIRCHARGLEY_PUBLISHABLE_KEY=pk_prod_sirchargly_...
    SIRCHARGLEY_SECRET_KEY=sk_prod_sirchargly_...
    SIRCHARGLEY_WEBHOOK_SECRET=whsec_prod_...
    

    Security Best Practices

  • Never commit API keys to version control
  • ```bash

    # .gitignore

    .env.local

    .env.production

    ```

  • Use environment variables
  • ```typescript

    // ✅ Good

    const key = process.env.SIRCHARGLEY_SECRET_KEY;

    // ❌ Bad

    const key = 'sk_prod_sirchargly_...';

    ```

  • Validate webhook signatures
  • ```typescript

    // Always verify webhook authenticity

    const event = SirChargly.webhooks.constructEvent(

    body,

    signature,

    webhookSecret

    );

    ```

  • Use HTTPS for webhooks
  • ```

    ✅ https://yourdomain.com/api/webhooks

    ❌ http://yourdomain.com/api/webhooks

    ```

  • Implement rate limiting
  • ```typescript

    // Prevent abuse of your endpoints

    import rateLimit from 'express-rate-limit';

    const limiter = rateLimit({

    windowMs: 15 * 60 * 1000, // 15 minutes

    max: 100, // limit each IP to 100 requests per windowMs

    });

    ```

    Monitoring

    Track Key Metrics:

  • Payment success rate
  • Average convenience fee
  • Failed payment reasons
  • API response times
  • Error rates by type
  • Set Up Alerts:

  • Failed payment spike (>5% failure rate)
  • API errors (>1% error rate)
  • Webhook delivery failures
  • Unusual fee amounts
  • Key usage from unexpected IPs
  • Rollback Plan

  • Keep old API keys active for 24 hours after deployment
  • Test production thoroughly with small amounts first
  • Monitor error rates closely for first 24 hours
  • Have rollback environment variables ready
  • Document the rollback process

  • Support

    Resources

  • API Reference: https://docs.sirchargly.com/api
  • Dashboard: https://dashboard.sirchargly.com
  • Status Page: https://status.sirchargly.com
  • Changelog: https://docs.sirchargly.com/changelog
  • Getting Help

  • Email: support@sirchargly.com
  • Live Chat: Available in dashboard
  • GitHub: https://github.com/sirchargly/sdk-node
  • Community: https://community.sirchargly.com
  • Reporting Issues

    Include the following when reporting bugs:

  • Request ID (from error response)
  • Timestamp of the error
  • Environment (dev/prod)
  • API endpoint affected
  • Error message and stack trace
  • Steps to reproduce

  • Examples

    Complete Payment Flow

    import { SirChargly } from '@sirchargly/sdk';
    
    const chargly = new SirChargly(process.env.SIRCHARGLEY_PUBLISHABLE_KEY!);
    
    async function processOrder(orderId: string, amount: number) {
      try {
        // 1. Get fee estimate
        const estimate = await chargly.estimates.create({
          amount,
          currency: 'usd',
        });
    
        // 2. Show customer the total including fee
        console.log(`Order: $${amount / 100}`);
        console.log(`Convenience Fee: $${estimate.convenienceFee / 100}`);
        console.log(`Total: $${estimate.totalAmount / 100}`);
    
        // 3. Create the charge
        const charge = await chargly.charges.create({
          amount,
          currency: 'usd',
          metadata: { orderId },
        });
    
        // 4. Save charge ID to your database
        await saveChargeToDatabase(orderId, charge.id);
    
        return {
          success: true,
          chargeId: charge.id,
          totalAmount: charge.totalAmount,
        };
      } catch (error) {
        console.error('Payment failed:', error);
        return {
          success: false,
          error: error.message,
        };
      }
    }
    

    This completes the API Integration Guide! 🚀

    Ready to start charging convenience fees?

    Create your account and complete onboarding in minutes.

    No credit card required • 5-minute setup