Skip to main content
Technology

Accessing SA Tender Data with the Python SDK

A practical guide to the tendersa-sdk Python package — async/await client, resource methods, paginated iteration, error handling, and rate limit tracking. For data analysts, researchers, and Python developers.

SA Procurement Data in Python: Async, Typed, and Open Source

The tendersa-sdk Python package provides an idiomatic async client for the Tenders-SA Developer API. It uses httpx for asynchronous HTTP, maps every API response to typed Python objects, and supports async iteration through paginated results. It is designed for data analysts, researchers, and Python backend developers who need to integrate SA procurement data into their workflows.

The SDK is open source under the MIT license and published on PyPI. The source code is available at github.com/Tenders-SA/python

.

Installation

1pip install tendersa-sdk
BASH

The SDK requires Python 3.9+ and httpx 0.27+ (installed automatically as a dependency).

Quick Start

The SDK uses async/await throughout. Here is a minimal example to verify connectivity and pull live data:

1import asyncio
2from tendersa import TendersaClient
3
4async def main():
5    client = TendersaClient(api_key="tsa_prod_your_key")
6
7    # List open tenders
8    tenders = await client.tenders.list({
9        "status": "OPEN",
10        "province": "Western Cape",
11    })
12
13    for t in tenders.data:
14        print(t.title, t.status)
15
16// ... (truncated)
PYTHON

The client also supports async context manager usage, which handles cleanup automatically:

1async with TendersaClient(api_key="tsa_prod_your_key") as client:
2    result = await client.tenders.list({"status": "OPEN"})
PYTHON

Client Configuration

1from tendersa import TendersaClient
2
3client = TendersaClient(
4    api_key="tsa_prod_your_key",
5    base_url="https://api.tenders-sa.org",  # default
6    timeout=30.0,                            # 30 seconds (default)
7    max_retries=3,                           # exponential backoff (default)
8)
PYTHON

Resource Methods

The SDK is organised into five resource classes, mirroring the API structure. Each method maps directly to a REST endpoint.

Tenders

1# List with filters
2result = await client.tenders.list({
3    "status": "OPEN",
4    "category": "Construction",
5    "province": "Gauteng",
6    "sort": "-closingDate",
7})
8
9# Get detail
10# Access AI-enriched fields: .summary, .requirements, .estimated_value
11detail = await client.tenders.get("tender_001")
12
13# Sub-resources
14docs = await client.tenders.documents("tender_001")
15awards = await client.tenders.awards("tender_001")
16// ... (truncated)
PYTHON

Awards

1result = await client.awards.list({
2    "province": "Western Cape",
3    "beeLevel": "Level 1",
4    "minAmount": 1_000_000,
5})
6
7award = await client.awards.get("award_001")
8
9analytics = await client.awards.analytics({
10    "groupBy": "province",
11    "from": "2025-01-01",
12    "to": "2025-12-31",
13})
PYTHON

Companies

1# Full company intelligence profile
2company = await client.companies.get("BuildCorp SA")
3
4# Search by name, BEE level, or province
5results = await client.companies.search({
6    "q": "Construction",
7    "beeLevel": "Level 1",
8    "province": "Gauteng",
9})
PYTHON

Organisations (Procurement Bodies)

1org = await client.organizations.get("org_001")
2tenders = await client.organizations.tenders("org_001", {"status": "OPEN"})
PYTHON

Meta

1status = await client.meta.status()
2provinces = await client.meta.provinces()
3categories = await client.meta.categories()
4usage = await client.meta.usage()
PYTHON

Pagination

The Python SDK supports idiomatic async iteration through paginated results. Use the paginated() method on list resources:

1# Iterate through all pages of open tenders
2async for page in client.tenders.paginated({
3    "status": "OPEN",
4    "category": "Construction",
5}):
6    for tender in page:
7        print(tender.title, tender.closing_date)
8
9# Control max pages
10async for page in client.awards.paginated(
11    {"province": "Gauteng"},
12    max_pages=5,
13):
14    print(f"Page {page.page}: {len(page)} items")
15    print(f"  Total: {page.total_count}, Has next: {page.has_next}")
PYTHON

Each page is a PaginatedResponse object with convenience properties: .page, .page_size, .total_count, .total_pages, .has_next, and .has_prev.

Error Handling

The SDK raises typed exceptions for every HTTP status code the API can return. Catch specific exceptions for targeted handling:

1from tendersa.errors import (
2    TendersaError,
3    AuthError,
4    NotFoundError,
5    RateLimitError,
6    BadRequestError,
7    ForbiddenError,
8    ConflictError,
9)
10
11try:
12    tender = await client.tenders.get("nonexistent")
13except AuthError:
14    print("Invalid API key. Get one at https://tenders-sa.org/developers/api-keys")
15except NotFoundError:
16// ... (truncated)
PYTHON

Rate Limit Tracking

1rl = client.last_rate_limit
2if rl:
3    print(f"{rl.remaining}/{rl.limit} requests remaining ({rl.policy})")
PYTHON

Use Cases in Python

The Python SDK is particularly useful for data analysis and automation workflows:

  • Market research: Pull tender data into pandas DataFrames for sector analysis. Iterate through all pages of awards and export to CSV for offline analysis.
  • Competitive monitoring: Script periodic scans that check for new awards in your sector and send alerts when specific suppliers win contracts.
  • Compliance tracking: Monitor procurement opportunities in specific categories or regions. Use the analytics endpoint to track spending trends over time.
  • Data enrichment: Combine Tenders-SA data with other datasets (e.g. company registries, geographic data) for enriched analysis.

The full SDK source code is on GitHub at github.com/Tenders-SA/python

. The package is published to PyPI as tendersa-sdk
. The complete API reference is available at tenders-sa.org/developers/docs
.

The repository includes the full Python source code with type annotations, comprehensive test coverage, async context manager support, and a README with examples for every endpoint.

Tags

PythonSDKPyPIAsyncData AnalysisAPI ClientOpen SourceDeveloper Tools
AI-Powered Matching
Never Miss a Perfect Tender Again
Our AI analyzes thousands of tenders and finds the ones YOUR company can actually win
AI Match Scoring for every tender
Instant alerts for 85%+ matches
B-BBEE level optimization
Document readiness checks

Share this article

Accessing SA Tender Data with the Python SDK

A practical guide to the tendersa-sdk Python package — async/await client, resource methods, paginated iteration, error handling, and rate limit tracking. For data analysts, researchers, and Python developers.

https://www.tenders-sa.org/blog/tendersa-python-sdk-guide