Skip to main content
Technology

The Tenders-SA Developer API: Programmatic Access to South African Procurement Data

A technical guide to the Tenders-SA Developer API — authentication, endpoints, pagination, rate limiting, error handling, and sparse field support. For developers building on top of SA public procurement data.

Programmatic Access to South African Procurement Data

Tenders-SA.org aggregates tenders from national, provincial, and municipal government departments, SOEs (Eskom, Transnet, SANRAL), and public entities across South Africa. The data is sourced directly from official OCDS (Open Contracting Data Standard) feeds and then enriched through AI pipelines for summarisation, requirement extraction, value estimation, and classification.

The Tenders-SA Developer API exposes this enriched procurement data through a set of RESTful endpoints. It runs on a dedicated infrastructure layer with its own database — synced from the main platform — so the API remains fast and available independently of the web application. This guide covers the API architecture, authentication, available endpoints, and usage patterns.

API Base URL and Authentication

All API requests are made to the following base URL:

1https://api.tenders-sa.org/v1
TEXT

Authentication is handled via Bearer tokens passed in the Authorization header. API keys use the format tsa_prod_ followed by a unique generated string:

1Authorization: Bearer tsa_prod_your_api_key
TEXT

API keys are generated through the Developer Portal

. Access requires a Professional or Enterprise subscription with the following rate limits:

PlanMax API KeysDaily LimitMonthly Limit
Professional350015,000
Enterprise2510,000300,000

Response Format

Every API response follows a consistent envelope structure. A successful response contains a success boolean, a data payload, and a meta object with pagination and rate limit information:

1{
2  "success": true,
3  "data": { ... },
4  "meta": {
5    "requestId": "req_uuid",
6    "timestamp": "2026-01-01T00:00:00Z",
7    "apiVersion": "v1",
8    "page": 1,
9    "pageSize": 20,
10    "totalCount": 142,
11    "totalPages": 8,
12    "hasNext": true,
13    "hasPrev": false,
14    "rateLimit": {
15      "limit": 500,
16// ... (truncated)
JSON

Error responses follow a similar pattern with an error string, a machine-readable code, a human-readable message, and a docs URL pointing to the relevant error documentation:

1{
2  "success": false,
3  "error": "Not found",
4  "code": "NOT_FOUND",
5  "message": "The requested resource was not found",
6  "requestId": "req_xxx",
7  "docs": "https://tenders-sa.org/developers/docs/errors#NOT_FOUND",
8  "timestamp": "2026-01-01T00:00:00Z"
9}
JSON

Available Endpoints

The API is organised into five resource groups. Here is every available endpoint with its purpose:

Tenders

EndpointMethodDescription
/v1/tendersGETList tenders with filters (status, province, category, value range, closing date)
/v1/tenders/{id}GETGet a single tender with all enriched fields
/v1/tenders/searchGETAI-powered semantic search across all active tenders
/v1/tenders/{id}/documentsGETList associated tender documents with download URLs
/v1/tenders/{id}/awardsGETGet award history for a specific tender
/v1/tenders/{id}/timelineGETFull procurement timeline from publication to award
/v1/tenders/{id}/analysisGETAI-generated analysis including summary, requirements, and scoring
/v1/tenders/{id}/value-estimateGETEstimated value range based on document content analysis

Awards

EndpointMethodDescription
/v1/awardsGETList awards with filters (supplier, province, category, value range, date range)
/v1/awards/{id}GETGet a single award with full supplier and contract details
/v1/awards/analyticsGETAggregated award analytics grouped by province, category, enterprise type, or BEE level

Companies

EndpointMethodDescription
/v1/companies/{name}GETCompany intelligence profile with award history, contract values, and compliance data
/v1/companies/searchGETSearch companies by name, BEE level, province, or industry

Organisations (Procurement Bodies)

EndpointMethodDescription
/v1/organizations/{id}GETProcurement body profile with contact information
/v1/organizations/{id}/tendersGETTenders issued by a specific procurement body

Meta

EndpointMethodDescription
/v1/meta/statusGETAPI health and data freshness information
/v1/meta/provincesGETList of provinces with active tender counts
/v1/meta/categoriesGETList of procurement categories with tender counts
/v1/meta/usageGETYour API usage statistics across all keys

Pagination

All list endpoints are paginated with a page-based cursor system. You control pagination with page and pageSize query parameters. The response meta includes everything you need to navigate: page, pageSize, totalCount, totalPages, hasNext, and hasPrev.

1GET /v1/tenders?status=OPEN&page=2&pageSize=50
TEXT

Page size defaults to 20 items and can be set up to 100. All three official SDKs implement pagination iterators that handle page traversal automatically.

Rate Limiting

Rate limit status is returned in both HTTP response headers and the response body's meta.rateLimit object:

  • Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-RateLimit-Policy
  • Body: meta.rateLimit.limit, meta.rateLimit.remaining, meta.rateLimit.reset, meta.rateLimit.policy

When a rate limit is exceeded, the API returns a 429 status with either RATE_LIMIT_DAILY_EXCEEDED or RATE_LIMIT_MONTHLY_EXCEEDED error code.

Error Codes

HTTP StatusCodeDescription
400BAD_REQUESTInvalid request parameters or malformed input
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDEN / KEY_NOT_ACTIVE / KEY_EXPIREDKey not active, expired, or lacks permissions
404NOT_FOUNDThe requested resource does not exist
409CONFLICT / KEY_LIMIT_REACHEDKey limit reached for your plan tier
429RATE_LIMIT_DAILY_EXCEEDED / RATE_LIMIT_MONTHLY_EXCEEDEDRate limit exceeded
500INTERNAL_ERRORServer error — please retry with exponential backoff
502SERVICE_UNAVAILABLEService temporarily unavailable

Sparse Fields

Reduce response payload size by specifying only the fields you need with the fields query parameter:

1GET /v1/tenders?fields=tenderId,title,status,closingDate,estimatedValue
TEXT

This is particularly useful for list endpoints where you may only need a subset of fields for display purposes — for example, populating a table or a dropdown selector without loading the full tender object.

Filtering Parameters

List endpoints support a common set of filter parameters. The exact set varies by resource, but the most widely supported are:

ParameterTypeApplies To
statusstringFilter by tender status: OPEN, CLOSED, AWARDED, CANCELLED
provincestringFilter by province name (e.g. 'Gauteng', 'Western Cape')
categorystringFilter by procurement category slug
minAmount / maxAmountnumberFilter by contract value range (awards)
minValue / maxValuenumberFilter by estimated value range (tenders)
beeLevelstringFilter by B-BBEE contributor level
sortstringSort field with optional '-' prefix for descending order
qstringFree-text search query

Getting Started

The quickest way to start exploring the API is through the official SDKs, which handle authentication, pagination, error handling, and retry logic:

For direct API access, the full API reference is available at tenders-sa.org/developers/docs

. API keys can be generated at tenders-sa.org/developers/api-keys
.

Tags

APIDeveloper ToolsREST APIGovernment DataProcurementOpen DataDocumentation
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

The Tenders-SA Developer API: Programmatic Access to South African Procurement Data

A technical guide to the Tenders-SA Developer API — authentication, endpoints, pagination, rate limiting, error handling, and sparse field support. For developers building on top of SA public procurement data.

https://www.tenders-sa.org/blog/tendersa-developer-api-guide