API Usage Guide

Learn how to programmatically access ISBT blood group data

What is an API?

An Application Programming Interface (API) is a set of rules and protocols that allows different software applications to communicate with each other. Think of it as a waiter in a restaurant who takes your order, delivers it to the kitchen, and brings your food back to you.

The ISBT Blood Group Database API allows researchers, developers, and healthcare systems to programmatically access blood group data without manually browsing the website. This enables automation, integration with laboratory systems, and large-scale data analysis.

πŸ’‘ Key Insight: In fact, this website itself uses the ISBT API to fetch what it needs for the data pages!

RESTful API Architecture

The ISBT API follows REST (Representational State Transfer) principles, which means:

  • Resource-based URLs: Each URL represents a specific resource (systems, antigens, alleles)
  • HTTP methods: GET (retrieve), POST (create), PATCH (update), DELETE (remove)
  • Stateless: Each request contains all information needed to process it
  • JSON format: Data is returned in JavaScript Object Notation format

Learn more about RESTful APIs at: https://restfulapi.net/

The API base URL for the ISBT Blood Group Database is: https://api-blooddatabase.isbtweb.org

Try the API in Your Browser

The API is really designed to be used computationally using programming languages like Python, JavaScript, or R - but even your web browser can make GET requests to fetch data from the API (its how the internet works!).

Before diving into code, you can explore the API directly using your web browser. This is great for understanding the data structure and testing endpoints:

🩸 Get All Blood Group Systems

View all ISBT blood group systems with their basic information:

https://api-blooddatabase.isbtweb.org/system

πŸ”¬ Search Kell System Antigens

Browse all antigens in the Kell blood group system:

https://api-blooddatabase.isbtweb.org/antigen/search?system_symbol=KEL

🧬 Search ABO System Alleles

Explore genetic variants in the ABO blood group system:

https://api-blooddatabase.isbtweb.org/allele/search?system_symbol=ABO

πŸ“‹ Interactive API Documentation

Explore all endpoints with interactive documentation:

https://api-blooddatabase.isbtweb.org/api

πŸ’‘ Pro Tip: Most browsers will automatically format JSON responses for easier reading. Try the links above to see the raw data structure and some examples before writing code!

Python Examples

Here are some practical Python examples using the popular requests and pandas libraries.

Copy and paste the code snippets into your Python environment (e.g. Jupyter Notebook, VSCode, PyCharm) to run them. Each example includes comments explaining what the code does.

You will have to install Python and these libraries first if you haven’t already - see the external Python installation guide, requests installation guide, and the pandas installation guide.

1. Get All Blood Group Systems

import requests
import json

# Base URL for the API
BASE_URL = "https://api-blooddatabase.isbtweb.org"

def get_all_systems():
    """Fetch all blood group systems from the ISBT API."""
    try:
        response = requests.get(f"{BASE_URL}/system")
        response.raise_for_status()  # Raises an HTTPError for bad responses
        
        systems = response.json()
        print(f"βœ… Found {len(systems)} blood group systems")
        
        # Display first few systems
        for system in systems[:3]:
            isbt_num = system['isbt_number']
            name = system['name']
            symbol = system['symbol']
            print(f"System {isbt_num:03d}: {name} ({symbol})")
            
        return systems
        
    except requests.exceptions.RequestException as e:
        print(f"❌ Error fetching systems: {e}")
        return None

# Execute the function
systems_data = get_all_systems()

# Print full data as JSON (optional)
print(json.dumps(systems_data, indent=2))

2. Search Antigens by System

import requests
from typing import List, Dict, Optional

BASE_URL = "https://api-blooddatabase.isbtweb.org"

def search_antigens_by_system(system_symbol: str) -> Optional[List[Dict]]:
    """
    Search for all antigens in a specific blood group system.
    
    Args:
        system_symbol (str): System symbol (e.g., 'KEL', 'ABO', 'RH', 'FY')
        
    Returns:
        List of antigen dictionaries or None if error
    """
    try:
        search_params = {"system_symbol": system_symbol}
        response = requests.get(
            f"{BASE_URL}/antigen/search", 
            params=search_params,
            timeout=30
        )
        response.raise_for_status()
        
        antigens = response.json()
        
        if not antigens:
            print(f"⚠️  No antigens found for system '{system_symbol}'")
            return []
            
        print(f"🩸 Found {len(antigens)} antigens in {system_symbol} system")
        print("=" * 50)
        
        # Sort by ISBT number for systematic display
        sorted_antigens = sorted(antigens, key=lambda x: x.get('isbt_number', 0))
        
        for antigen in sorted_antigens:
            name = antigen['name']
            isbt_code = antigen['isbt_code']
            isbt_number = antigen['isbt_number']
            approved = antigen.get('approved', False)
            status = "βœ… Approved" if approved else "⏳ Pending"
            
            print(f"πŸ”¬ {isbt_code}: {name}")
            print(f"   ISBT Number: {isbt_number}")
            print(f"   Status: {status}")
            print("   " + "-" * 40)
            
        return antigens
        
    except requests.exceptions.RequestException as e:
        print(f"❌ Error searching {system_symbol} antigens: {e}")
        return None
    except Exception as e:
        print(f"❌ Unexpected error: {e}")
        return None

# Example usage: Get antigens from different systems
print("=== Kell System Antigens ===")
kell_antigens = search_antigens_by_system("KEL")

print("\n=== Duffy System Antigens ===")
duffy_antigens = search_antigens_by_system("FY")

print("\n=== ABO System Antigens ===")
abo_antigens = search_antigens_by_system("ABO")

3. Get Alleles for a Specific System

import requests
import pandas as pd
from typing import List, Dict, Optional

BASE_URL = "https://api-blooddatabase.isbtweb.org"

def get_system_alleles(system_symbol: str) -> Optional[pd.DataFrame]:
    """
    Fetch alleles for a specific blood group system using search endpoint.
    
    Args:
        system_symbol (str): System symbol (e.g., 'KEL', 'ABO', 'RH', 'FY')
        
    Returns:
        pandas.DataFrame with allele data or None if error
    """
    try:
        # Use the allele search endpoint with system_symbol parameter
        search_params = {"system_symbol": system_symbol}
        response = requests.get(
            f"{BASE_URL}/allele/search", 
            params=search_params,
            timeout=30
        )
        response.raise_for_status()
        
        alleles = response.json()
        
        if not alleles:
            print(f"⚠️  No alleles found for system '{system_symbol}'")
            return None
            
        print(f"🧬 Found {len(alleles)} {system_symbol} alleles")
        print("=" * 50)
        
        # Convert JSON response directly to DataFrame - much cleaner!
        df = pd.read_json(response.text)
        
        # Select only the columns we're interested in
        desired_columns = [
            'id', 'isbt_allele', 'isbt_phenotype', 'reference_allele',
            'sv_allele', 'null_allele', 'mod_allele', 'partial_allele', 
            'weak_allele', 'el_allele', 'allele_order', 'alternate_names',
            'approved'
        ]
        
        # Keep only columns that exist in the response
        available_columns = [col for col in desired_columns if col in df.columns]
        df = df[available_columns]
        
        # Display summary statistics
        print(f"πŸ“Š {system_symbol} Allele Summary:")
        print(f"   Total alleles: {len(df)}")
        
        # Show allele type distribution
        allele_types = []
        type_columns = ['reference_allele', 'sv_allele', 'null_allele', 'mod_allele', 
                       'partial_allele', 'weak_allele', 'el_allele']
        
        for col in type_columns:
            if col in df.columns:
                count = df[col].sum()
                if count > 0:
                    type_name = col.replace('_allele', '').replace('_', ' ').title()
                    allele_types.append(f"{type_name}: {count}")
        
        if allele_types:
            print("   Allele types:")
            for allele_type in allele_types:
                print(f"     {allele_type}")
        
        # Show sample data with key columns
        print(f"\nπŸ” First 5 alleles (key properties):")
        display_cols = ['isbt_allele', 'isbt_phenotype', 'reference_allele', 
                       'null_allele', 'weak_allele', 'approved']
        available_cols = [col for col in display_cols if col in df.columns]
        print(df[available_cols].head().to_string(index=False))
        
        # Show approval statistics
        if 'approved' in df.columns:
            approved_count = df['approved'].sum()
            total_count = len(df)
            print(f"\nβœ… Approved: {approved_count}/{total_count} alleles")
        
        # Show reference allele info
        if 'reference_allele' in df.columns:
            ref_count = df['reference_allele'].sum()
            print(f"πŸ”¬ Reference alleles: {ref_count}")
        
        return df
        
    except requests.exceptions.RequestException as e:
        print(f"❌ Error fetching {system_symbol} alleles: {e}")
        return None
    except Exception as e:
        print(f"❌ Unexpected error: {e}")
        return None

# Example usage: Get alleles from different systems
print("=== Kell System Alleles ===")
kell_df = get_system_alleles("KEL")

print("\n=== ABO System Alleles ===")
abo_df = get_system_alleles("ABO")

4. Load Systems Data into Pandas DataFrame

import requests
import pandas as pd
from pathlib import Path
from typing import List, Dict, Optional

BASE_URL = "https://api-blooddatabase.isbtweb.org"

def load_systems_to_dataframe(save_csv: bool = True) -> Optional[pd.DataFrame]:
    """
    Load all ISBT blood group systems into a pandas DataFrame.
    
    Args:
        save_csv (bool): Whether to save data to CSV file
        
    Returns:
        pandas.DataFrame with systems data or None if error
    """
    try:
        # Fetch systems data
        response = requests.get(f"{BASE_URL}/system", timeout=30)
        response.raise_for_status()
        
        systems_data = response.json()
        
        # Convert to pandas DataFrame
        systems_df = pd.DataFrame(systems_data)
        
        # Data validation
        if systems_df.empty:
            print("⚠️  No systems data received")
            return None
            
        # Display basic information
        print(f"πŸ“Š Loaded {len(systems_df)} blood group systems")
        print(f"πŸ”§ Columns: {list(systems_df.columns)}")
        
        # Show sample data
        key_columns = ['isbt_number', 'name', 'symbol', 'category']
        available_columns = [col for col in key_columns if col in systems_df.columns]
        
        print(f"\nπŸ” First 5 systems:")
        print(systems_df[available_columns].head().to_string(index=False))
        
        # Category analysis
        if 'category' in systems_df.columns:
            print(f"\nπŸ“‚ Systems by category:")
            category_counts = systems_df['category'].value_counts()
            for category, count in category_counts.items():
                print(f"   {category}: {count}")
        
        # Approval status analysis
        if 'approved' in systems_df.columns:
            approved_count = systems_df['approved'].sum()
            total_count = len(systems_df)
            print(f"\nβœ… Approved systems: {approved_count}/{total_count}")
        
        # Sort by ISBT number for systematic view
        if 'isbt_number' in systems_df.columns:
            sorted_systems = systems_df.sort_values('isbt_number')
            print(f"\nπŸ”’ Systems by ISBT number (first 10):")
            display_cols = ['isbt_number', 'name', 'symbol']
            available_display = [col for col in display_cols if col in sorted_systems.columns]
            print(sorted_systems[available_display].head(10).to_string(index=False))
        
        # Save to CSV if requested
        if save_csv:
            output_file = Path('isbt_systems.csv')
            systems_df.to_csv(output_file, index=False)
            print(f"\nπŸ’Ύ Data saved to '{output_file}'")
        
        return systems_df
        
    except requests.exceptions.RequestException as e:
        print(f"❌ Error fetching systems: {e}")
        return None
    except Exception as e:
        print(f"❌ Unexpected error: {e}")
        return None

# Execute the function
systems_df = load_systems_to_dataframe(save_csv=True)

Best Practices

  • Rate Limiting: Be respectful with API calls. Don’t make too many requests in quick succession
  • Error Handling: Always check HTTP status codes and handle errors gracefully
  • Data Validation: Validate the structure and content of API responses before processing
  • Caching: Cache frequently accessed data to reduce API calls and improve performance
  • Version Control: Use release information to track which version of data you’re working with
  • Documentation: Keep your API usage documented for reproducibility

Authentication and Access

The ISBT API provides public read access to most blood group data. For write operations (creating, updating, or suggesting changes), authentication is required. To request API access:

  • Visit the access request page
  • Provide details about your intended use
  • Wait for approval from the ISBT working party
  • Use provided credentials for authenticated requests

Additional Resources

Note: The API structure and endpoints may evolve as the database grows. Always refer to the latest API documentationfor the most current information and consider versioning in your applications.

Tutorial Sections