Discover/Org API
live

Org APIzppa.org.zm

Access Zambia's public procurement data via ZPPA OCDS. Browse tenders, search by OCID, and retrieve buyer details, contract values, and tenderer info.

Endpoints
3
Updated
2mo ago

What is the Org API?

This API provides structured access to Zambia Public Procurement Authority (ZPPA) procurement records across 3 endpoints. Use get_current_tenders to retrieve a paginated list of live and historical procurement records sorted by most recent process date, each carrying an OCID and status field. From there, pass the returned MongoDB ObjectId into get_tender_details to pull the full OCDS compiled release including procuring entity, procurement method, budget, tenderers, and contract details.

Try it
Page number to fetch. Each page contains 20 records.
api.parse.bot/scraper/9194eb38-d322-4509-9d51-933120aa8121/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/9194eb38-d322-4509-9d51-933120aa8121/get_current_tenders?page=1' \
  -H 'X-API-Key: $PARSE_API_KEY'
Python SDK · recommended

Typed, relational, agent-ready

A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.

  • Fully typed · autocompletes
  • Objects link to objects
  • Typed errors & pagination

Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:

uv add parse-sdk
uv run parse init
uv run parse add --marketplace zppa-org-zm-api

uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.

"""
Zambia Public Procurement Authority (ZPPA) OCDS API Client

Access Zambia's public procurement data through the ZPPA Open Contracting Data Standard (OCDS) system.
Get your API key from: https://parse.bot/settings
"""

import os
import requests
from datetime import datetime
from typing import Optional, Dict, Any, List


class ParseClient:
    """Client for interacting with the ZPPA OCDS API via Parse."""
    
    def __init__(self, api_key: Optional[str] = None):
        """
        Initialize the Parse client.
        
        Args:
            api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
        """
        self.base_url = "https://api.parse.bot"
        self.scraper_id = "9194eb38-d322-4509-9d51-933120aa8121"
        self.api_key = api_key or os.getenv("PARSE_API_KEY")
        
        if not self.api_key:
            raise ValueError("API key must be provided or set in PARSE_API_KEY environment variable")
    
    def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
        """
        Make an API call to the Parse endpoint.
        
        Args:
            endpoint: The endpoint name (e.g., 'get_current_tenders')
            method: HTTP method ('GET' or 'POST')
            **params: Parameters to pass to the endpoint
            
        Returns:
            Dictionary containing the API response data
        """
        url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }
        
        if method.upper() == "GET":
            response = requests.get(url, headers=headers, params=params)
        else:  # POST
            response = requests.post(url, headers=headers, json=params)
        
        response.raise_for_status()
        result = response.json()
        
        if result.get("status") != "success":
            raise Exception(f"API error: {result}")
        
        return result.get("data", {})
    
    def get_current_tenders(self, page: int = 1) -> Dict[str, Any]:
        """
        Fetch a paginated list of procurement records from the ZPPA OCDS system.
        
        Args:
            page: Page number to fetch (default 1). Each page contains 20 records.
            
        Returns:
            Dictionary with 'tenders', 'page', 'total_pages', and 'total_records'
        """
        return self._call("get_current_tenders", method="GET", page=page)
    
    def get_tender_details(self, record_id: str) -> Dict[str, Any]:
        """
        Fetch full OCDS compiled release details for a specific procurement record.
        
        Args:
            record_id: MongoDB ObjectId of the record (e.g., '69f3df4ab4275d46715e26b5')
            
        Returns:
            Dictionary with 'details' containing full OCDS compiled release data
        """
        return self._call("get_tender_details", method="GET", record_id=record_id)
    
    def search_tenders(self, query: str, page: int = 1) -> Dict[str, Any]:
        """
        Search OCDS procurement records by OCID.
        
        Args:
            query: OCID search term (matches numeric portion, e.g., '10000137')
            page: Page number to fetch (default 1). Each page contains 20 records.
            
        Returns:
            Dictionary with 'results', 'query', 'page', 'total_pages', and 'total_results'
        """
        return self._call("search_tenders", method="GET", query=query, page=page)


def format_timestamp(epoch_ms: int) -> str:
    """Convert epoch milliseconds to readable date string."""
    return datetime.fromtimestamp(epoch_ms / 1000).strftime("%Y-%m-%d %H:%M:%S")


def main():
    """
    Practical workflow: Search for a tender, retrieve its details,
    and analyze procurement information.
    """
    # Initialize the client
    client = ParseClient()
    
    print("=" * 70)
    print("ZPPA OCDS Procurement Data Analysis")
    print("=" * 70)
    
    # Step 1: Search for a specific tender by OCID
    print("\n[1] Searching for tender with OCID containing '10000137'...")
    search_results = client.search_tenders(query="10000137")
    
    total_results = search_results.get("total_results", 0)
    print(f"    Found {total_results} matching record(s)")
    
    results = search_results.get("results", [])
    if not results:
        print("    No records found. Fetching recent tenders instead...")
        
        # Step 2: If search yields nothing, get current/recent tenders
        print("\n[2] Fetching most recent procurement records (page 1)...")
        recent = client.get_current_tenders(page=1)
        tenders = recent.get("tenders", [])
        total_records = recent.get("total_records", 0)
        
        print(f"    Total records in system: {total_records}")
        print(f"    Records on this page: {len(tenders)}")
        
        # Use first few records for analysis
        results = tenders[:3]
    
    # Step 3: Retrieve and analyze details for each result
    print(f"\n[3] Retrieving detailed information for {len(results)} tender(s)...")
    
    for idx, tender_summary in enumerate(results, 1):
        tender_id = tender_summary.get("id")
        ocid = tender_summary.get("ocid")
        status = tender_summary.get("status")
        creation_date = format_timestamp(tender_summary.get("creation_date", 0))
        process_date = format_timestamp(tender_summary.get("process_date", 0))
        
        print(f"\n    --- Tender {idx} ---")
        print(f"    OCID: {ocid}")
        print(f"    Status: {status}")
        print(f"    Created: {creation_date}")
        print(f"    Processed: {process_date}")
        
        # Fetch full details
        details_response = client.get_tender_details(record_id=tender_id)
        details = details_response.get("details", {})
        
        # Extract key procurement information
        tender_info = details.get("tender", {})
        title = tender_info.get("title", "N/A")
        description = tender_info.get("description", "N/A")
        procurement_method = tender_info.get("procurement_method", "N/A")
        number_of_tenderers = tender_info.get("number_of_tenderers", 0)
        
        value = tender_info.get("value", {})
        amount = value.get("amount", "N/A")
        currency = value.get("currency", "N/A")
        
        procuring_entity = tender_info.get("procuring_entity", {})
        entity_name = procuring_entity.get("name", "N/A")
        
        buyer = details.get("buyer", {})
        buyer_name = buyer.get("name", "N/A")
        
        # Print procurement details
        print(f"\n    Title: {title}")
        print(f"    Description: {description}")
        print(f"    Procuring Entity: {entity_name}")
        print(f"    Buyer: {buyer_name}")
        print(f"    Procurement Method: {procurement_method}")
        print(f"    Budget: {amount:,} {currency}" if isinstance(amount, (int, float)) else f"    Budget: {amount} {currency}")
        print(f"    Number of Tenderers: {number_of_tenderers}")
        
        # Extract and display items
        items = tender_info.get("items", [])
        if items:
            print(f"    Items ({len(items)}):")
            for item in items[:2]:  # Show first 2 items
                item_desc = item.get("description", "N/A")
                item_id = item.get("id", "N/A")
                print(f"      - {item_desc} (ID: {item_id})")
            if len(items) > 2:
                print(f"      ... and {len(items) - 2} more")
        
        # Display tenderers
        tenderers = tender_info.get("tenderers", [])
        if tenderers:
            print(f"    Tenderers ({len(tenderers)}):")
            for tenderer in tenderers[:3]:  # Show first 3 tenderers
                tenderer_name = tenderer.get("name", "N/A")
                print(f"      - {tenderer_name}")
            if len(tenderers) > 3:
                print(f"      ... and {len(tenderers) - 3} more")
    
    print("\n" + "=" * 70)
    print("Analysis complete!")
    print("=" * 70)


if __name__ == "__main__":
    main()
All endpoints · 3 totalmissing one? ·

Fetch a paginated list of procurement records from the ZPPA OCDS system, sorted by most recent process date. Returns record identifiers that can be used with get_tender_details to retrieve full information.

Input
ParamTypeDescription
pageintegerPage number to fetch. Each page contains 20 records.
Response
{
  "type": "object",
  "fields": {
    "page": "integer, current page number",
    "tenders": "array of record summary objects, each containing id, ocid, status, creation_date (epoch ms), and process_date (epoch ms)",
    "total_pages": "integer, total number of pages available",
    "total_records": "integer, total number of records in the system"
  },
  "sample": {
    "data": {
      "page": 1,
      "tenders": [
        {
          "id": "69f3df4ab4275d46715e26b5",
          "ocid": "ocds-23g63a01-25844731",
          "status": "NEW",
          "process_date": 1777676418609,
          "creation_date": 1777563602000
        }
      ],
      "total_pages": 8533,
      "total_records": 170656
    },
    "status": "success"
  }
}

About the Org API

Browsing and Searching Tenders

The get_current_tenders endpoint returns a paginated list of procurement records from the ZPPA OCDS system. Each page contains 20 records, and each record in the tenders array includes an id (MongoDB ObjectId), ocid, status, creation_date, and process_date (both as epoch milliseconds). The total_records and total_pages fields let you walk the full dataset systematically. For targeted lookups, search_tenders accepts a query string matched against the numeric portion of an OCID — for example, querying 10000001 will match ocds-23g63a01-10000001. Results are paginated identically to the browse endpoint.

Retrieving Full Procurement Details

Once you have a record_id from either listing or search, pass it to get_tender_details to retrieve the full OCDS compiled release. The details object follows the Open Contracting Data Standard and includes the ocid, a tender block with title, description, status, procurement method, and procuring entity, plus tenderer information and budget and contract values where available. This makes it possible to reconstruct a complete picture of a procurement process from notice through award.

Data Coverage and Standards

All records conform to the OCDS format (prefix ocds-23g63a01), the international open contracting standard used by governments to publish procurement data. The API covers procurements managed through ZPPA, Zambia's central procurement authority. Dates are provided as epoch milliseconds, so convert to ISO 8601 before display. Pagination is fixed at 20 records per page across all three endpoints.

Reliability & maintenance

The Org API is a managed, monitored endpoint for zppa.org.zm — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when zppa.org.zm changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.

This isn't an official zppa.org.zm API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.

Will this API break when the source site changes?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Monitor new Zambian government tenders by polling get_current_tenders and filtering on process_date
  • Build a tender alert system that notifies vendors when procurement records matching their sector appear
  • Cross-reference OCID values from external sources against ZPPA records using search_tenders
  • Aggregate contract values and procurement methods from get_tender_details for public spending analysis
  • Track procuring entities across multiple tender records to identify active buyers in the Zambian government
  • Feed ZPPA OCDS data into a compliance or due-diligence workflow for tenderers listed in procurement records
  • Archive historical procurement records for auditing or research on Zambian public sector contracting trends
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo1005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min

One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does ZPPA provide an official developer API?+
ZPPA does not publish a documented public developer API. The procurement data it manages is available through the ZPPA OCDS portal at zppa.org.zm, but there is no official REST API with keys, documentation, or versioning offered to developers.
What does `get_tender_details` actually return beyond the basic record summary?+
It returns the full OCDS compiled release for the record, including the tender block (title, description, status, procurement method, procuring entity), tenderer details, budget figures, and contract values where the record has progressed to award stage. The record summary from get_current_tenders only includes id, ocid, status, and two date fields — the detail endpoint is required for all substantive procurement information.
Can I search by tender title, procuring entity name, or procurement method?+
Not currently. search_tenders only matches against the numeric portion of an OCID. Title, entity name, and procurement method are returned inside get_tender_details but are not filterable query parameters at this time. You can fork this API on Parse and revise it to add a full-text or field-specific search endpoint.
Are procurement records from all Zambian public entities included, or only central government?+
The API covers records published through the ZPPA OCDS system. ZPPA is Zambia's central procurement authority and oversees procurement across public entities, but coverage depends on what has been published to the ZPPA platform. Records for entities that submit outside this system would not appear. You can fork this API on Parse and revise it to integrate additional Zambian procurement data sources if broader coverage is needed.
How are dates represented and is there a way to filter by date range?+
creation_date and process_date are both returned as epoch milliseconds in the record summary objects. Date-range filtering is not a supported parameter on any of the three endpoints. get_current_tenders is sorted by most recent process_date descending, so paginating from page 1 gives the newest records first.
Page content last updated . Spec covers 3 endpoints from zppa.org.zm.
Related APIs in Government PublicSee all →
tenders.gov.uk API
Search and access UK government public procurement notices, tenders, and contract opportunities in real-time, with the ability to retrieve detailed notice information and browse standardized classification codes. Get comprehensive procurement data in structured formats to analyze tender patterns and find relevant contracting opportunities.
boz.zm API
Access historical and current 91-day treasury bill auction data from the Bank of Zambia, including tender results, bid amounts, prices, and yield rates spanning from 2014 to present. Search and retrieve structured tender information to analyze Zambia's treasury bill market trends and performance over time.
tenders.gov.in API
Search and monitor current government tenders from India's Central Public Procurement Portal and GePNIC systems, filtering by organizations and accessing detailed tender information. Stay updated on the latest procurement opportunities and bids from Indian government agencies in one centralized location.
eprocurement.gov API
Monitor India's public procurement opportunities by accessing active tenders, bids closing today, global tenders, high-value contracts, and cancelled tenders from the Central Public Procurement Portal. Search tender details, browse participating organizations, and track real-time procurement statistics to stay informed on government contracting opportunities.
offenevergaben.at API
Search and explore Austrian public procurement contracts, including details about contracting authorities, suppliers, and product categories. Track government spending by accessing comprehensive information about individual contracts, the organizations that issue them, and the vendors that supply them.
evergabe-online.de API
Search and retrieve public tender opportunities from Germany's e-Vergabe platform by keywords, contract types, CPV codes, and publication dates. Access detailed tender information and discover the latest procurement opportunities across construction and other sectors.
doffin.no API
Search for public procurement tenders across Norway and retrieve detailed information about bidding opportunities, including tender specifics, CPV category codes, and location data. Stay informed about government contracts and procurement notices from the official Norwegian national database.
bdtender.com API
Search and browse tender listings from Bangladesh's largest tender portal, discovering opportunities by category, organization, and location while accessing real-time tender data and site statistics. Get detailed information on individual tenders, view live postings, and see what was published today to stay updated on the latest bidding opportunities.