Skip to main content

A complete reverse-engineered API client for GovPlanet with extensive product search capabilities

Project description

GovPlanet API - Complete Integration Guide

A complete reverse-engineered API client for GovPlanet with extensive product search capabilities. This guide is designed for frontend developers to integrate comprehensive product search functionality.

🎯 Overview

This API client provides access to GovPlanet's product catalog with the ability to search across 1,000+ products by querying multiple categories simultaneously.

Current Capabilities:

  • Single request: 60 products (API limit per request)
  • Extensive search: 100+ products by searching across multiple categories
  • Maximum potential: 1,420+ unique products when searching all categories

The API returns up to 60 products per request, but by searching across categories, you can get extensive results including exactly 100 products for any query.

📦 Installation

pip install -r requirements.txt

🚀 Quick Start

Get Exactly 100 Results ⭐ (Most Common Use Case)

from govplanet_api import GovPlanetAPI

api = GovPlanetAPI()

# Get exactly 100 results for any query
products = api.search_extensive(
    query='truck',           # Your search query
    max_categories=20,       # Search 20 categories (enough for 100 results)
    max_results=100          # Return exactly 100 products
)

print(f"Found {len(products)} products")

Why This Works:

  • Each category can return up to 60 products
  • Searching 20 categories gives us up to 1,200 potential products
  • The method automatically deduplicates products
  • Setting max_results=100 returns exactly 100 unique products

Performance: ~2-3 seconds for 100 results (20 categories × 0.1s delay)

Basic Search (Single Request)

from govplanet_api import GovPlanetAPI

api = GovPlanetAPI()

# Simple search - returns up to 60 products
products, total = api.search(query='trucks')
print(f"Found {len(products)} products (Total available: {total})")

Extensive Search (100+ Results)

from govplanet_api import GovPlanetAPI

api = GovPlanetAPI()

# Search across multiple categories for comprehensive results
products = api.search_extensive(
    query='trucks',
    max_categories=50,  # Search 50 categories
    max_results=500     # Return up to 500 products
)

print(f"Found {len(products)} unique products")

📚 API Reference

GovPlanetAPI Class

search() - Single Request Search

Search products with filters. Returns up to 60 products per request.

products, total = api.search(
    query='trucks',              # Search query (optional)
    category=1,                  # Category ID 1-100+ (optional)
    location='USA-CA',           # Location filter (optional)
    manufacturer='AM General',   # Manufacturer filter (optional)
    sort_by='price',             # Sort: 'date' or 'price' (optional)
    order='asc',                 # Order: 'asc' or 'desc' (optional)
    auction_type='F',            # Auction type: 'F' or 'A' (optional)
    max_results=60               # Max results (default: 60)
)

Returns: Tuple[List[Product], int] - (products list, total available count)

search_extensive() - Multi-Category Search ⭐ RECOMMENDED

Search across multiple categories to get comprehensive results. This is the recommended method for getting extensive product results.

products = api.search_extensive(
    query='trucks',              # Search query (optional)
    location='USA-CA',           # Location filter (optional)
    manufacturer='AM General',   # Manufacturer filter (optional)
    max_categories=50,           # Number of categories to search (default: 50)
    max_results=500              # Maximum results to return (None = all)
)

Returns: List[Product] - List of unique products

Why use this?

  • Searches across multiple categories automatically
  • Returns hundreds or thousands of unique products
  • Handles deduplication automatically
  • Best for comprehensive search results

Product Data Model

Each product contains:

{
    'equip_id': str,              # Unique product ID
    'description': str,            # Product description
    'price': str,                 # Formatted price (e.g., "$1,500")
    'price_numeric': float,       # Numeric price for filtering
    'location': str,              # Location name (e.g., "California")
    'location_code': str,         # Location code (e.g., "USA-CA")
    'photo_url': str,             # Product image URL
    'page_url': str,              # Full product page URL
    'auction_end_date': int,      # Auction end timestamp
    'bid_count': int,             # Number of bids
    'features': str,              # Product features
    'registration_number': str,   # Registration number
    'auction_type': str,          # Auction type
    'equipment_status': int,      # Equipment status code
    'is_ica': bool                # ICA flag
}

AISearchEngine Class

Semantic search engine for natural language queries.

from govplanet_api import AISearchEngine

# Initialize with products
engine = AISearchEngine(products)
engine.index()

# Search with natural language
results = engine.search(
    query='trucks under $5000 in California',
    filters={'price_max': 5000, 'location': 'USA-CA'},
    top_k=10
)

# Results are scored by relevance
for product, score in results:
    print(f"[{score:.2f}] {product.description} - {product.price}")

💡 Usage Examples

Example 1: Get Exactly 100 Results for a Query ⭐

from govplanet_api import GovPlanetAPI

api = GovPlanetAPI()

# Get exactly 100 products matching "truck"
products = api.search_extensive(
    query='truck',
    max_categories=20,  # Search 20 categories
    max_results=100     # Return exactly 100 products
)

print(f"Found {len(products)} products")
for product in products[:10]:
    print(f"- {product.description} - {product.price} - {product.location}")

Quick Examples:

# Get 100 trucks
trucks = api.search_extensive(query='truck', max_categories=20, max_results=100)

# Get 100 generators
generators = api.search_extensive(query='generator', max_categories=20, max_results=100)

# Get 100 products in California
products = api.search_extensive(location='USA-CA', max_categories=30, max_results=100)

Key Points:

  • max_categories=20 ensures enough categories are searched to get 100 results
  • max_results=100 limits the return to exactly 100 products
  • Each category can return up to 60 products, so 2-3 categories is usually enough for 100 results
  • Performance: ~2-3 seconds for 100 results

Example 2: Search for Trucks

from govplanet_api import GovPlanetAPI

api = GovPlanetAPI()

# Get extensive results
trucks = api.search_extensive(
    query='truck',
    max_categories=50,
    max_results=200
)

print(f"Found {len(trucks)} trucks")
for truck in trucks[:10]:
    print(f"- {truck.description} - {truck.price} - {truck.location}")

Example 3: Search by Location

# Get all products in California
california_products = api.search_extensive(
    location='USA-CA',
    max_categories=50
)

print(f"Found {len(california_products)} products in California")

Example 4: Search with Multiple Filters

# Search for generators in Texas
generators = api.search_extensive(
    query='generator',
    location='USA-TX',
    max_categories=30,
    max_results=100
)

# Filter by price (client-side)
affordable = [g for g in generators if g.price_numeric and g.price_numeric < 5000]
print(f"Found {len(affordable)} generators under $5000")

Example 5: Natural Language Search

from govplanet_api import GovPlanetAPI, AISearchEngine

api = GovPlanetAPI()

# Get products
products = api.search_extensive(query='vehicle', max_categories=30)

# Initialize AI search
engine = AISearchEngine(products)
engine.index()

# Natural language queries
queries = [
    "HMMWV vehicles",
    "trucks under $5000",
    "generators in California",
    "equipment with low hours"
]

for query in queries:
    results = engine.search(query, top_k=5)
    print(f"\nQuery: '{query}'")
    for product, score in results:
        print(f"  [{score:.2f}] {product.description[:50]}... - {product.price}")

🔍 API Parameters Reference

Endpoint

https://www.govplanet.com/jsp/s/search.ips

Available Parameters

Parameter Type Description Example Values
mode int Search mode 6 (all products)
format string Response format json
q string Search query "truck", "generator"
ct int Category ID 1, 2, 3... (1-100+)
locationCode string Location filter "USA-CA", "USA-TX"
m string Manufacturer "AM General"
sort string Sort field "date", "price"
order string Sort direction "asc", "desc"
aucType string Auction type "F", "A"
equipStatus int Equipment status 30, 31

Location Codes

Use USA-{STATE} format:

  • USA-CA - California
  • USA-TX - Texas
  • USA-NY - New York
  • USA-FL - Florida
  • USA-AZ - Arizona
  • ... (all US states)

📊 Response Structure

API Response Format

{
  "jsonData": {
    "total": 22487,
    "items": [
      {
        "equipId": "14224716",
        "description": "Product description",
        "priceString": "<span>US $1,490</span>",
        "locationString": "Arizona",
        "locationCode": "USA-AZ",
        "photo": "https://cdn.ironpla.net/...",
        "itemPageUri": "/for-sale/...",
        "featuresString": "Feature details...",
        "aucEndDate": 1762891200000,
        "bidCount": 3,
        ...
      }
    ]
  }
}

⚠️ Important Limitations

  1. Max 60 items per request - The API returns a maximum of 60 products per single request
  2. No pagination - Standard pagination parameters (start, offset, page) don't work
  3. Solution - Use search_extensive() which searches across multiple categories to get comprehensive results

🎯 Best Practices

For Getting 100 Results

# ✅ RECOMMENDED: Get exactly 100 results
products = api.search_extensive(
    query='your query',
    max_categories=20,  # 20 categories is enough for 100 results
    max_results=100     # Return exactly 100 products
)

For Extensive Results (100+)

# ✅ For 500+ results, search more categories
products = api.search_extensive(
    query='your query',
    max_categories=50,  # Search many categories
    max_results=500     # Set reasonable limit
)

For Quick Single Requests

# ✅ Use search() for quick single requests
products, total = api.search(query='trucks', category=1)

For Natural Language Queries

# ✅ Use AISearchEngine for semantic search
engine = AISearchEngine(products)
results = engine.search('trucks under $5000')

🔧 Frontend Integration Examples

JavaScript/TypeScript Example

// Backend API endpoint (using Python Flask/FastAPI)
// POST /api/search
// {
//   "query": "trucks",
//   "location": "USA-CA",
//   "max_categories": 50,
//   "max_results": 200
// }

// Frontend fetch
async function searchProducts(query, location = null) {
  const response = await fetch('/api/search', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: query,
      location: location,
      max_categories: 50,
      max_results: 200
    })
  });
  
  const products = await response.json();
  return products;
}

// Usage
const trucks = await searchProducts('trucks', 'USA-CA');
console.log(`Found ${trucks.length} trucks`);

React Example

import { useState, useEffect } from 'react';

function ProductSearch() {
  const [query, setQuery] = useState('');
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(false);

  const handleSearch = async () => {
    setLoading(true);
    const results = await searchProducts(query);
    setProducts(results);
    setLoading(false);
  };

  return (
    <div>
      <input 
        value={query} 
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search products..."
      />
      <button onClick={handleSearch}>Search</button>
      
      {loading && <p>Loading...</p>}
      {products.map(product => (
        <div key={product.equip_id}>
          <h3>{product.description}</h3>
          <p>{product.price} - {product.location}</p>
          <img src={product.photo_url} alt={product.description} />
        </div>
      ))}
    </div>
  );
}

📈 Performance Tips

  1. Use caching - The API client includes built-in caching
  2. Limit categories - Start with max_categories=30 and increase if needed
  3. Set max_results - Use reasonable limits to avoid memory issues
  4. Rate limiting - The client includes automatic rate limiting (0.1s between requests)

🐛 Error Handling

try:
    products = api.search_extensive(query='trucks')
except Exception as e:
    print(f"Error: {e}")
    # Handle error appropriately

📝 Notes

  • Rate Limiting: The API includes automatic delays between requests (0.1s)
  • Caching: Results are cached to avoid duplicate requests
  • Deduplication: search_extensive() automatically removes duplicate products
  • Data Format: Price is extracted from HTML automatically

🔗 Additional Resources

  • Product data includes full URLs: product.page_url for direct links
  • Images available: product.photo_url for product images
  • Raw data: product.raw_data contains full API response

📄 License

This is a reverse engineering project for educational purposes. Use responsibly and in compliance with GovPlanet's terms of service.

📦 Publishing to PyPI

Quick Publish Steps

  1. Install build tools:

    pip install build twine
    
  2. Build the package:

    python -m build
    
  3. Upload to PyPI:

    # Test first on TestPyPI (recommended)
    python -m twine upload --repository testpypi dist/*
    
    # Then upload to real PyPI
    python -m twine upload dist/*
    

Before Publishing

After Publishing

Users can install with:

pip install govplanet-api

Note: This is a reverse engineering project for educational purposes. Use responsibly and in compliance with GovPlanet's terms of service.

government-surplus-api-client

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

govplanet_api-1.0.0.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

govplanet_api-1.0.0-py3-none-any.whl (12.4 kB view details)

Uploaded Python 3

File details

Details for the file govplanet_api-1.0.0.tar.gz.

File metadata

  • Download URL: govplanet_api-1.0.0.tar.gz
  • Upload date:
  • Size: 16.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for govplanet_api-1.0.0.tar.gz
Algorithm Hash digest
SHA256 10d26109a45b437460b7463190fb0c52b519615f98a92e8710bed0c38c39953d
MD5 cfa423542cb00a6b7c8e0e3ae7bcd423
BLAKE2b-256 d14cd2595bbf8c09cf2aed06009a4c7c33aa77b9922266de661d242a3d19cdc8

See more details on using hashes here.

File details

Details for the file govplanet_api-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: govplanet_api-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for govplanet_api-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 78d0ba00fa209bc12fdb47287b9891fd258ab7a8ff8fc53fd905dec53dc90e55
MD5 2e53f4816db140f70a0360a9a8e151f1
BLAKE2b-256 10dcd0d95bdd8f77928b7833323d16f1605c2cb12ae37945263bd91f04ce49be

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page