Getting Started with the Extend API | Virtual Card & Expense Management Integration Guide

Getting Started with the Extend API: A Complete Guide

Author

Ashkan Abedian
Guest Author

TL;DR

In today's digital-first business environment, managing corporate expenses efficiently is crucial.

Extend gives businesses access to powerful virtual card issuing and expense management features with their credit card of choice. In this guide, we'll walk through setting up your API access and creating a simple service that demonstrates how to interact with the Extend API.

What is Extend?

Extend allows businesses to connect their credit cards and get instant access to a suite of card controls and bookkeeping features. By integrating with the Extend API, you can embed virtual card issuing, approvals, transaction monitoring, and expense processing capabilities into your own proprietary workflows. This provides a secure and flexible solution for managing business expenses while significantly reducing manual work surrounding AP/AR and bookkeeping processes.

Prerequisites

Before we begin, make sure you have:

Setting up your API access

Step 1: Request API access

  1. Navigate to your organization's settings page
  2. Click on the "API Keys" tab
  3. Click on the "Setup API Keys" button

A member of the Extend team will review your request and approve it. Once approved, you'll be able to generate an API key.

Step 2: Generate your API key

  1. After approval, return to the API Keys tab
  2. Click the "Generate API Key" button
  3. Copy both the API key and secret - you'll need these for authentication

Store these credentials securely. They won't be displayed again, and you'll need to generate a new key when this one expires (after 365 days).

Building your first integration

Let's create a Python service that demonstrates how to interact with the Extend API. We'll build this step by step, explaining each component as we go.

Project setup

First, let's set up our development environment:

mkdir extend-api-demo

cd extend-api-demo

python -m venv venv

source venv/bin/activate  # On Windows, use: venv\Scripts\activate

pip install requests python-dotenv

Setting up authentication

Before we start coding, we need to set up our authentication. Extend uses a combination of an API key and an authentication token for secure API access.

First, create a .env file to store your credentials:

EXTEND_API_KEY=your_api_key_here

EXTEND_API_SECRET=your_api_secret_here

EXTEND_EMAIL=your_extend_email_here

Next, create a script called generate_token.sh to generate your authentication token:

#!/bin/bash

# Check if both arguments are provided
if [ $# -ne 2 ]; then
    echo "Usage: $0  "
    exit 1
fi

# Assign the arguments to variables
API_KEY=$1
SECRET=$2

# Combine the API key and secret with a colon separator
CREDENTIALS="${API_KEY}:${SECRET}"

# Base64 encode the credentials
SECURITY_TOKEN=$(echo -n "${CREDENTIALS}" | base64)

echo "Your security token is: ${SECURITY_TOKEN}"
echo "Add this to your .env file as EXTEND_AUTHENTICATION_TOKEN=${SECURITY_TOKEN}"

Make the script executable and run it:

chmod +x generate_token.sh

./generate_token.sh your_api_key your_api_secret

Update your .env file with the generated token:

EXTEND_API_KEY=your_api_key_here

EXTEND_AUTHENTICATION_TOKEN=your_generated_token_here

EXTEND_EMAIL=your_extend_email_here

Creating the base client

Let's start by creating our extend_client.py file with the basic client structure and authentication:

import os

import requests

from dotenv import load_dotenv

class ExtendClient:
    def __init__(self):
        load_dotenv()
        self.authentication_token = os.getenv('EXTEND_AUTHENTICATION_TOKEN')
        self.api_key = os.getenv('EXTEND_API_KEY')
        self.base_url = 'https://apiv2.paywithextend.com'
        self.proxy_url = 'https://v-apiv2.paywithextend.com'
        self.extend_email = os.getenv('EXTEND_EMAIL')
        if not self.authentication_token or not self.api_key:
            raise ValueError("Authentication token and API key must be set in .env file")

def _get_auth_headers(self):
        """Generate authentication headers for API requests"""
        return {
            "Authorization": f"Basic {self.authentication_token}",
            "x-extend-api-key": self.api_key,
            "Accept": "application/vnd.paywithextend.v2021-03-12+json"
        }

This base client:

Adding credit card management

Now let's add methods to manage credit cards. Add these methods to your ExtendClient class:

def get_credit_cards(self):
        """Retrieve all enrolled credit cards"""
        response = requests.get(
            f"{self.base_url}/creditcards",
            headers=self._get_auth_headers()
        )
        response.raise_for_status()
        return response.json()

This method:

Implementing virtual card operations

Let's add the virtual card management functionality. Add these methods to your ExtendClient class:

    def create_virtual_card(self, credit_card_id, balance_cents, valid_to_date, display_name):
        """Create a new virtual card"""
        payload = {
            "recipient": self.extend_email,
            "displayName": display_name,
            "balanceCents": balance_cents,
            "validTo": valid_to_date,
            "creditCardId": credit_card_id
        }
        response = requests.post(
            f"{self.base_url}/virtualcards",
            headers=self._get_auth_headers(),
            json=payload
        )
        response.raise_for_status()
        return response.json()

def get_virtual_card_spend_info(self, virtual_card_id):
        """Retrieve spending information for a virtual card"""
        response = requests.get(
            f"{self.proxy_url}/virtualcards/{virtual_card_id}",
            headers=self._get_auth_headers()
        )
        response.raise_for_status()
        data = response.json()
        virtual_card = data.get("virtualCard", {})
        return {
            "id": virtual_card.get("id"),
            "vcn": virtual_card.get("vcn"),
            "securityCode": virtual_card.get("securityCode"),
            "address": virtual_card.get("address"),
            "expires": virtual_card.get("expires")
        }

def close_virtual_card(self, virtual_card_id):
        """Close a virtual card"""
        response = requests.put(
            f"{self.base_url}/virtualcards/{virtual_card_id}/close",
            headers=self._get_auth_headers()
        )
        response.raise_for_status()
        return response.json()

These methods provide:

Using the client

Now that we have our client implementation, let's create a main.py file to demonstrate how to use it:

from extend_client import ExtendClient
from datetime import datetime, timedelta

def main():
    # Initialize the client
    client = ExtendClient()
    try:
        # Get available credit cards
        print("Fetching credit cards...")
        credit_cards = client.get_credit_cards()
        if not credit_cards.get('creditCards'):
            print("No credit cards found. Please enroll a card first.")
            return
        card_id = credit_cards['creditCards'][0]["id"]
        print(f"Found credit card with ID: {card_id}")
        # Create a virtual card
        valid_to_date = (datetime.now() + timedelta(days=365)).strftime("%Y-%m-%d")
        print("\nCreating virtual card...")
        virtual_card = client.create_virtual_card(
            credit_card_id=card_id,
            balance_cents=1000,  # $10.00
            valid_to_date=valid_to_date,
            display_name="Marketing Expenses"
        )
        virtual_card_id = virtual_card['virtualCard']['id']
        print(f"Created virtual card with ID: {virtual_card_id}")
        # Get card details
        print("\nRetrieving card details...")
        card_info = client.get_virtual_card_spend_info(virtual_card_id)
        print("Card Details:")
        print(f"Card Number: {card_info['vcn']}")
        print(f"Security Code: {card_info['securityCode']}")
        print(f"Expires: {card_info['expires']}")
        print(f"Billing Address: {card_info['address']}")
        # Close the card
        print("\nClosing virtual card...")
        client.close_virtual_card(virtual_card_id)
        print("Card closed successfully")
    except Exception as e:
        print(f"An error occurred: {str(e)}")

if __name__ == "__main__":
    main()

This example demonstrates:

Running the example

  1. Make sure your .env file is properly configured with your API credentials.
  2. Run the example:
python main.py

This will:

  1. Fetch your enrolled credit cards
  2. Create a new virtual card
  3. Retrieve the card details
  4. Close the card

Next steps

This example demonstrates the basic functionality of the Extend API. You can now:

Need more information about our API capabilities? Get our API documentation

Need help?

If you need assistance with your integration, you can contact our support team.

Happy coding!

About the author

Ashkan Abedian
Guest Author
Ashkan is a Product Manager & Engineer, driving intelligent automation and personalized platform experiences. With a background in backend engineering, Ashkan previously worked on Extend’s Core Services team, contributing to critical integrations and embedded payments infrastructure. He holds a degree in Management Engineering from the University of Waterloo.