Developers
BidX Connect API
Bring your tenders and awarded suppliers into the systems you already run. One token, plain JSON, and examples you can paste.
Sandboxhttps://sandbox.zangupay.com
On this page
Getting started
Introduction
The BidX Connect API lets your ERP, finance or supplier systems read your tenders and the suppliers you award, so procurement data flows without re-keying.
It is a JSON-over-HTTPS REST API. Every response wraps its payload in a data field. During the preview, all calls go to the sandbox; production access is enabled per organisation on request.
https://sandbox.zangupay.comGetting started
Authentication
The API uses the OAuth 2.0 client credentials flow. An administrator creates credentials in the BidX buyer portal under Admin → API keys & integrations.
- The client secret is shown once. Store it in a secrets manager; BidX keeps only a hash and cannot show it again.
- Tokens last 20 hours (
expires_inseconds). Cache one and request a new token when it expires. - Call the API from your servers only. Never ship credentials in a browser or mobile app.
# 1. Exchange your credentials for a token (valid 20 hours)
curl --request POST "https://sandbox.zangupay.com/v1/oauth/token" \
--header "Content-Type: application/json" \
--data '{"client_id": "…", "client_secret": "…", "grant_type": "client_credentials"}'
# 2. Send it on every call
curl "https://sandbox.zangupay.com/v1/connect/bid" \
--header "Authorization: Bearer $BIDX_ACCESS_TOKEN"Getting started
Errors
Failed calls return a non-2xx status and an error object. Branch on error.code, which is stable; error.en is a readable message that may change.
| HTTP | error.code | When |
|---|---|---|
| 400 | invalid_request | A required field is missing. |
| 401 | invalid_access_token | The token is missing or expired. |
| 401 | invalid_access_token_format | The header is not Bearer <token>. |
| 500 | not_known | Something failed on our side; retry with backoff. |
{
"success": false,
"http_code": "401",
"error": {
"code": "invalid_access_token",
"en": "No access token submitted."
}
}Getting started
Conventions & limits
- IDs are 24-character hexadecimal strings. Treat them as opaque.
- Dates read like
30-Sep-2026 07:07, in East Africa Time (UTC+3). - Set a client timeout on every call; 30 seconds is plenty.
- Retry 5xx responses at most three times, with exponential backoff.
Authentication
Create an access token
/v1/oauth/tokenExchanges your client credentials for a bearer token. Request a new token when the current one expires, not before every call.
Body
client_idstringRequired- Your client ID.
client_secretstringRequired- Your client secret.
grant_typestringRequired- Always
client_credentials.
Returns (inside data)
access_tokenstringRequired- The bearer token.
token_typestringRequired- Always
Bearer. expires_inintegerRequired- Seconds until the token expires (72000, which is 20 hours).
Errors
| HTTP | error.code | When |
|---|---|---|
| 400 | invalid_request | client_id or client_secret is missing. |
| 400 | invalid_grant | grant_type is not client_credentials. |
| 500 | invalid_client | The client ID or secret is wrong, or the secret was regenerated. |
curl --request POST "https://sandbox.zangupay.com/v1/oauth/token" \
--max-time 30 \
--header "Content-Type: application/json" \
--data '{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"grant_type": "client_credentials"
}'{
"data": {
"access_token": "bidx_3f9c2a…",
"token_type": "Bearer",
"expires_in": 72000
}
}Tenders
List tenders
/v1/connect/bidReturns every tender, quotation and pre-qualification your organisation has created on BidX, including drafts.
Requires Authorization: Bearer with an access token.
- Filter out
status: "Creation"if you only want published tenders.
Returns (inside data)
idstringRequired- The tender's ID.
serial_nostringRequired- BidX serial number.
referencestringRequired- Your reference number.
descriptionstringRequired- The tender's title.
bid_typestringRequiredTENDER,QUOTATIONorPRE-QUALIFICATION.eligibilitystringRequiredOPEN-TO-ALL,BY-INVITATIONorAGGREGATED-SUPPLIERS.statusstringRequired- Lifecycle stage:
Creation(draft),Submitted,Running,Evaluation,InReview,FrozenorAwarded. expiresbooleanRequired- Whether it has a deadline.
expiry_date_timestringRequired- The deadline, in East Africa Time.
fee_per_categorynumberRequired- Fee to apply.
versionintegerRequired- Revision number.
slugstringRequired- URL-safe identifier.
timestampstringRequired- Created at, EAT.
projectobjectRequired- The owning organisation.
Errors
| HTTP | error.code | When |
|---|---|---|
| 401 | invalid_access_token | No token, or the token expired. |
| 401 | invalid_access_token_format | The Authorization header does not start with Bearer . |
curl --request GET "https://sandbox.zangupay.com/v1/connect/bid" \
--max-time 30 \
--header "Authorization: Bearer $BIDX_ACCESS_TOKEN"{
"data": [
{
"id": "6aa79462460da1f202aa6464",
"serial_no": "260911",
"reference": "RFQ/ICT/2026/014",
"description": "Supply of laptops and accessories",
"bid_type": "QUOTATION",
"eligibility": "OPEN-TO-ALL",
"status": "Awarded",
"expires": true,
"expiry_date_time": "30-Sep-2026 07:07",
"fee_per_category": 0,
"version": 1,
"slug": "supply-of-laptops-and-accessories-v7y4",
"visibility": null,
"timestamp": "14-Sep-2026 09:29",
"project": {
"id": null,
"business_entity": {
"id": "675bcad93ba6a684819d8974",
"business_name": "Acme Holdings Ltd",
"website": "www.example.com",
"media": {
"logo_url": "https://cdn.example.com/logo.png",
"uploaded": true
}
}
}
}
]
}Awarded suppliers
List awarded suppliers
/v1/connect/bid/{bid_id}/master-listReturns the master list for a tender: every supplier awarded at least one category.
Requires Authorization: Bearer with an access token.
- Returns at most 50 suppliers.
- An empty
dataarray means nothing is awarded yet.
Path parameters
bid_idstringRequired- The tender's
id, as returned by List tenders.
Returns (inside data)
application_idstringRequired- The award's bid application.
scorenumberRequired- The application's evaluation score.
category_countintegerRequired- How many categories of the tender the supplier applied for.
business_entityobjectRequired- The supplier:
business_entity_id,business_name,registration_number,registration_year,kra_pin,tcc_number,compliance_status,industry,country,town_city,physical_address,postal_code,website,applicant_name,email_address,phone_number,contacts,banksandowners.
Errors
| HTTP | error.code | When |
|---|---|---|
| 401 | invalid_access_token | No token, or the token expired. |
| 401 | invalid_access_token_format | The Authorization header does not start with Bearer . |
curl --request GET "https://sandbox.zangupay.com/v1/connect/bid/6aa79462460da1f202aa6464/master-list" \
--max-time 30 \
--header "Authorization: Bearer $BIDX_ACCESS_TOKEN"{
"data": [
{
"application_id": "6a0f5c2e9b1d4a7e3c8f2b61",
"score": 87.5,
"category_count": 2,
"business_entity": {
"business_entity_id": "65f1b2c3d4e5f60718293a4b",
"business_name": "Savanna Office Supplies Ltd",
"registration_number": "PVT-2019-004812",
"registration_year": "2019",
"kra_pin": "P051234567Z",
"tcc_number": "KRATCC0012345",
"compliance_status": "Compliant",
"industry": "Office supplies",
"country": "Kenya",
"town_city": "Nairobi",
"physical_address": "Mombasa Road, Nairobi",
"postal_code": "00100",
"website": "www.example.co.ke",
"applicant_name": "Jane Wanjiru",
"email_address": "tenders@example.co.ke",
"phone_number": "+254700000000",
"contacts": [],
"banks": [],
"owners": []
}
}
]
}Awarded suppliers
Retrieve an awarded supplier
/v1/connect/bid/{bid_id}/master-list/{application_id}Returns one entry of a tender's master list.
Requires Authorization: Bearer with an access token.
datais a list with one entry, or empty when that application was not awarded.
Path parameters
bid_idstringRequired- The tender's
id, as returned by List tenders. application_idstringRequired- The
application_idfrom List awarded suppliers.
Returns (inside data)
application_idstringRequired- The award's bid application.
scorenumberRequired- The application's evaluation score.
category_countintegerRequired- How many categories of the tender the supplier applied for.
business_entityobjectRequired- The supplier:
business_entity_id,business_name,registration_number,registration_year,kra_pin,tcc_number,compliance_status,industry,country,town_city,physical_address,postal_code,website,applicant_name,email_address,phone_number,contacts,banksandowners.
Errors
| HTTP | error.code | When |
|---|---|---|
| 401 | invalid_access_token | No token, or the token expired. |
| 401 | invalid_access_token_format | The Authorization header does not start with Bearer . |
curl --request GET "https://sandbox.zangupay.com/v1/connect/bid/6aa79462460da1f202aa6464/master-list/6a0f5c2e9b1d4a7e3c8f2b61" \
--max-time 30 \
--header "Authorization: Bearer $BIDX_ACCESS_TOKEN"{
"data": [
{
"application_id": "6a0f5c2e9b1d4a7e3c8f2b61",
"score": 87.5,
"category_count": 2,
"business_entity": {
"business_entity_id": "65f1b2c3d4e5f60718293a4b",
"business_name": "Savanna Office Supplies Ltd",
"registration_number": "PVT-2019-004812",
"registration_year": "2019",
"kra_pin": "P051234567Z",
"tcc_number": "KRATCC0012345",
"compliance_status": "Compliant",
"industry": "Office supplies",
"country": "Kenya",
"town_city": "Nairobi",
"physical_address": "Mombasa Road, Nairobi",
"postal_code": "00100",
"website": "www.example.co.ke",
"applicant_name": "Jane Wanjiru",
"email_address": "tenders@example.co.ke",
"phone_number": "+254700000000",
"contacts": [],
"banks": [],
"owners": []
}
}
]
}