Loading…
Loading…
Tenderkart Client API
Use this page to connect to Tenderkart, read the saved filters on your account, sync matching tenders, download documents, and fetch market stats.
Base URL
https://tenderkart.in/api/v1/clientAuth header
X-API-Key or Authorization: Bearer
Rate limit
30 requests per minute, per API key
Responses
JSON, UTF-8, ISO-8601 timestamps
Three calls take you from an API key to tender data.
List the saved filters on your account
curl -H "X-API-Key: YOUR_API_KEY" "https://tenderkart.in/api/v1/client/filters"Sync tenders from one filter
curl -H "X-API-Key: YOUR_API_KEY" \
"https://tenderkart.in/api/v1/client/filters/d2b051b7-f42e-4962-a00c-66a5765ea36a/tenders?limit=100"Open full details for one tender
curl -H "X-API-Key: YOUR_API_KEY" "https://tenderkart.in/api/v1/client/tenders/6c4c27e1-4c8a-4d62-9a32-2b1c9c4f73e9"GET /filters/{filter_id}/tenders?limit=100GET /filters/{filter_id}/tenders?updated_after=ISO_TIMESTAMPGET /filters/{filter_id}/tenders?cursor=OPAQUE_CURSORGET /filters/{filter_id}/tenders?updated_after=ISO_TIMESTAMP&status=active,under_evaluationGET /tenders?keywords=...&state=...| Need | Use | Why |
|---|---|---|
| First backfill | GET /filters/{filter_id}/tenders?limit=100 | Omit updated_after the first time. The response freezes a safe updated_before for the run. |
| Scheduled sync | GET /filters/{filter_id}/tenders?updated_after=ISO_TIMESTAMP | Use sync.next_updated_after from the previous completed run. |
| Next page | GET /filters/{filter_id}/tenders?cursor=OPAQUE_CURSOR | Use pagination.next_cursor until has_more is false. |
| Restrict by stage | GET /filters/{filter_id}/tenders?updated_after=ISO_TIMESTAMP&status=active,under_evaluation | Use simple status buckets when a client only wants certain tender stages. |
| Ad-hoc question | GET /tenders?keywords=...&state=... | Search the full corpus outside your saved filters. Optional capability, enabled per API key. |
All paths are relative to the base URL above.
/openapi.yaml/filters/filters/{filter_id}/tenders/tenders/tenders/{tender_uuid}/documents/{id}/tenders/lookup/stats| Method | Endpoint | Use |
|---|---|---|
| GET | /openapi.yaml | Machine-readable OpenAPI specification. The only endpoint that needs no API key. |
| GET | /filters | List the saved filters on your account, including exact filter criteria. |
| GET | /filters/{filter_id}/tenders | Sync tenders changed in Tenderkart using updated_at cursor pagination. |
| GET | /tenders | Search the full tender corpus. Optional capability, enabled per API key. |
| GET | /tenders/{tender_uuid} | Fetch full tender details and document IDs. |
| GET | /documents/{id} | Download a tender document. |
| GET | /tenders/lookup | Lookup one tender by portal tender ID or reference number. |
| POST | /stats | Fetch aggregate tender market statistics for a date range. |
Send the API key in the X-API-Key header, or as Authorization: Bearer YOUR_API_KEY. Every endpoint accepts either form. Keep the key private and never put it in frontend code, public repositories, logs, or shared screenshots.
curl -H "X-API-Key: YOUR_API_KEY" "https://tenderkart.in/api/v1/client/filters"Rate limits are applied per API key and shared across REST and MCP. The default limit is 30 requests per minute. Authenticated responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. If the API returns 429, wait for the Retry-After response header before retrying.
A filter is one of the saved filters on your Tenderkart account, the same ones you create and edit in the web app. Every one of them is available to your API key, and edits made in the app take effect on the next call. The criteria object explains the subject matter the filter searches for. Filters with no criteria saved are omitted, because they cannot drive a sync.
Filter IDs are stable, but the set changes whenever a filter is added, renamed, or deleted in the web app. Call /filters at the start of a sync run rather than hardcoding IDs.
curl -H "X-API-Key: YOUR_API_KEY" "https://tenderkart.in/api/v1/client/filters"GET /tenders.{
"filters": [
{
"id": "d2b051b7-f42e-4962-a00c-66a5765ea36a",
"name": "Sound, Light & Immersive AV Shows",
"criteria": {
"keywords": ["sound and light show", "projection mapping"],
"exclude_keywords": ["CCTV", "surveillance"],
"states": []
}
}
]
}Copy the filter's id into the endpoint path. Tenderkart reads the saved criteria from your account and applies them automatically.
curl -H "X-API-Key: YOUR_API_KEY" \
"https://tenderkart.in/api/v1/client/filters/d2b051b7-f42e-4962-a00c-66a5765ea36a/tenders?limit=100"keywordsexclude_keywordsstatescitiesauthoritiescategoriesprocurement_typestender_typesportalspayment_modestender_amount_mintender_amount_maxshow_na_amountemd_amount_minemd_amount_maxshow_na_emdtender_fee_exemptedemd_fee_exemptedhas_contractlow_competitiongem_bid_typesgem_mse_exemptiongem_startup_exemptiongem_turnover_min / gem_turnover_maxgem_oem_turnover_min / gem_oem_turnover_maxgem_experience_min / gem_experience_max| Field | Meaning |
|---|---|
keywords | Tender keywords included in the filter. Multiple values are matched with OR logic. |
exclude_keywords | Negative keywords used to remove noisy or irrelevant tenders. |
states | State filters. Empty or missing means all India. |
cities | City filters. Empty or missing means all cities. |
authorities | Buyer or organisation filters. |
categories | Product or work categories when configured. |
procurement_types | Procurement types such as Works, Goods, or Services when configured. |
tender_types | Competition-type filters on two axes — access (open, limited, single_source, reserved) and bidder origin (global, domestic). Values within an axis are OR-ed; the two axes are AND-ed. Tenders whose portal publishes no method are not matched. The raw portal wording stays in the tender's tender_type field. |
portals | Source portal filters. |
payment_modes | Payment mode filters when configured. |
tender_amount_min | Minimum tender amount in absolute INR. |
tender_amount_max | Maximum tender amount in absolute INR. |
show_na_amount | With an amount range set, also include tenders whose amount is unavailable. |
emd_amount_min | Minimum EMD in INR. Leave unset to keep zero-EMD tenders in range. |
emd_amount_max | Maximum EMD in INR. |
show_na_emd | Also include tenders that publish no EMD amount. |
tender_fee_exempted | Restrict to tenders with no tender fee. |
emd_fee_exempted | Restrict to tenders with no EMD fee. |
has_contract | Restrict to tenders that carry contract data. |
low_competition | Restrict to tenders with low-competition signals such as bid auto extension. |
gem_bid_types | GeM bid type filters. |
gem_mse_exemption | GeM MSE relaxation filter. true keeps only bids that relax the experience and turnover bars for MSEs, false excludes them, omitted applies no constraint. GeM-only — other portals pass through unaffected. |
gem_startup_exemption | GeM startup relaxation filter, same three-valued semantics. Two true values OR together; two false values AND. |
gem_turnover_min / gem_turnover_max | GeM bidder turnover bounds. |
gem_oem_turnover_min / gem_oem_turnover_max | GeM OEM turnover bounds. |
gem_experience_min / gem_experience_max | GeM required-experience bounds, in years. |
Empty states or cities means the filter is not restricted to a specific location. For all-India filters, those fields are normally empty. Use the tender sync status query parameter to choose active, evaluation, awarded, or cancelled tenders.
Use GET /filters/{filter_id}/tenders to sync every Tenderkart record change from a configured filter. Sync on updated_at, not published_at, because source pipelines can lag by up to 24 hours for some sources: a tender published earlier can be added or refreshed in Tenderkart later.
The response also includes published_at and closing_at as business dates. Use them for tender-age reporting, deadline reminders, and open-tender workflows, but keep updated_at as the sync cursor.
curl -H "X-API-Key: YOUR_API_KEY" \
"https://tenderkart.in/api/v1/client/filters/d2b051b7-f42e-4962-a00c-66a5765ea36a/tenders?updated_after=2026-05-22T10:30:00Z&limit=100"For the first full backfill, omit updated_after. For regular runs, pass sync.next_updated_after from the previous completed run. Use ISO-8601 timestamps with timezone, normally UTC with Z. Date-only values are not accepted for sync. Process rows idempotently by id; a tender can appear again if it changes while you are paging.
When updated_before is omitted, Tenderkart chooses a safe upper bound slightly behind current server time. This prevents very recent writes from being skipped while they are still becoming searchable.
curl -H "X-API-Key: YOUR_API_KEY" \
"https://tenderkart.in/api/v1/client/filters/d2b051b7-f42e-4962-a00c-66a5765ea36a/tenders?cursor=eyJmaWx0ZXJfaWQiOiJkMmIwNTFiNy..."{
"tenders": [
{
"id": "6c4c27e1-4c8a-4d62-9a32-2b1c9c4f73e9",
"tenderkart_url": "https://tenderkart.in/tender/6c4c27e1-4c8a-4d62-9a32-2b1c9c4f73e9",
"portal_name": "gem",
"tender_id": "9355734",
"tender_reference_number": "GEM/2026/B/1234567",
"status": "under_evaluation",
"raw_status": "technical_evaluation",
"title": "Event Management Service",
"organisation": "Example Department",
"published_at": "2026-05-21T05:30:00Z",
"closing_at": "2026-06-10T12:00:00Z",
"added_at": "2026-05-21T05:45:00Z",
"updated_at": "2026-05-24T06:15:00Z"
}
],
"pagination": {
"next_cursor": "eyJmaWx0ZXJfaWQiOiJkMmIwNTFiNy...",
"has_more": true
},
"sync": {
"updated_after": "2026-05-22T10:30:00Z",
"updated_before": "2026-05-24T12:30:00Z"
}
}If pagination.has_more is true, request the next page using pagination.next_cursor. sync.next_updated_after appears only on the final page; store it and use it as updated_after on the next run. If a filter is edited while you are paging, the cursor can return 400; restart from your last stored sync.next_updated_after.
{
"pagination": {
"has_more": false
},
"sync": {
"updated_after": "2026-05-22T10:30:00Z",
"updated_before": "2026-05-24T12:30:00Z",
"next_updated_after": "2026-05-24T12:30:00Z"
}
}curl -H "X-API-Key: YOUR_API_KEY" \
"https://tenderkart.in/api/v1/client/filters/d2b051b7-f42e-4962-a00c-66a5765ea36a/tenders?updated_after=2026-05-22T10:30:00Z&status=active,under_evaluation"To open full details, call GET /tenders/{tender_uuid} with the Tenderkart tender UUID returned as id. This endpoint is global for authenticated API clients and does not require a filter ID.
curl -H "X-API-Key: YOUR_API_KEY" "https://tenderkart.in/api/v1/client/tenders/6c4c27e1-4c8a-4d62-9a32-2b1c9c4f73e9"If you already know a portal tender ID or reference number, use lookup:
curl -H "X-API-Key: YOUR_API_KEY" \
"https://tenderkart.in/api/v1/client/tenders/lookup?tender_id=GEM%2F2026%2FB%2F7406250"Lookup does not require a filter ID. It can return any tender available in Tenderkart when the portal tender ID or reference number is valid.
403 and the matching MCP tool is hidden. Contact Tenderkart to have it enabled for your key.GET /tenders searches every tender in Tenderkart, independent of your saved filters. Use it for ad-hoc questions and discovery, and keep filter sync as your integration cursor: search is ranked and page-based, so it is not a reliable way to detect changes.
400.curl -H "X-API-Key: YOUR_API_KEY" --get \
--data-urlencode "keywords=sound and light show" \
--data-urlencode "keywords=projection mapping" \
--data-urlencode "exclude_keywords=CCTV" \
--data-urlencode "exclude_keywords=surveillance" \
"https://tenderkart.in/api/v1/client/tenders"Empty states in a saved filter means all India, so the equivalent free-form request omits state. Repeat state=... to select one or more states.
keywords, exclude_keywordsstate, city, authorityproduct_category, tender_category, portalstatustender_amount_min, tender_amount_maxshow_na_amountshow_na_emdpublish_date_from, publish_date_toclosing_date_from, closing_date_tosortpage, limit| Parameter | Notes |
|---|---|
keywords, exclude_keywords | Repeatable. Up to 20 values, each at most 120 characters. |
state, city, authority | Repeatable geography filters. Up to 50 values each. |
product_category, tender_category, portal | Repeatable classification filters. Up to 50 values each. |
status | Status buckets, repeatable or comma-separated. Defaults to active. |
tender_amount_min, tender_amount_max | Amount bounds in absolute INR. |
show_na_amount | Literal true or false. Includes tenders with no usable amount. |
show_na_emd | Literal true or false. Includes tenders that publish no EMD amount. |
publish_date_from, publish_date_to | Inclusive YYYY-MM-DD bounds in Asia/Kolkata. |
closing_date_from, closing_date_to | Inclusive YYYY-MM-DD bounds in Asia/Kolkata. |
sort | relevance, closing_date_asc/desc, tender_amount_asc/desc, publish_date_desc, last_activity_desc, updated_at_desc, or created_at_desc. |
page, limit | Page defaults to 1. Limit defaults to 50, maximum 100. page * limit cannot exceed 10,000. |
Repeatable parameters combine with OR logic within a parameter and AND logic across parameters. Unknown query parameters are rejected with 400 rather than ignored, so a typo fails loudly instead of silently widening your results.
The searchable window is capped at 10,000 records. pagination.total reports the true match count even when it exceeds the window, while pagination.pages reports only the pages you can reach. Narrow the query with dates or geography rather than paging deeper.
{
"tenders": [
{
"id": "6c4c27e1-4c8a-4d62-9a32-2b1c9c4f73e9",
"tenderkart_url": "https://tenderkart.in/tender/6c4c27e1-4c8a-4d62-9a32-2b1c9c4f73e9",
"portal_name": "gem",
"tender_id": "186782",
"status": "active",
"raw_status": "active",
"title": "Supply and installation of solar water pumping systems",
"organisation": "Karnataka Renewable Energy Development Limited",
"state": ["Karnataka"],
"tender_value": 24500000,
"closing_at": "2026-06-09T12:00:00Z",
"updated_at": "2026-05-19T04:15:00Z"
}
],
"pagination": {
"total": 214,
"page": 1,
"limit": 50,
"pages": 5
}
}Search returns the same tender summary shape as filter sync. For descriptions, award details, and document IDs, follow up with GET /tenders/{tender_uuid}.
Tender detail responses include document IDs when documents are available, including NIT, BOQ, corrigendum, financial result, and award/AOC documents. Use GET /documents/{id} to download a file.
curl -L -H "X-API-Key: YOUR_API_KEY" \
"https://tenderkart.in/api/v1/client/documents/doc_xxxxxxxxxxxxxxxxx" \
-o "tender-document.pdf"Use stats for aggregate tender counts and value totals. Date ranges can cover at most 30 days, and amounts in the response are returned in INR crores. Stats uses date_from and date_to because the same range is applied to new tender publish dates and awarded tender activity dates.
curl -X POST \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
"https://tenderkart.in/api/v1/client/stats" \
-d '{
"date_from": "2026-05-01",
"date_to": "2026-05-20",
"keywords": ["event management", "projection mapping"],
"states": ["Delhi", "Maharashtra"],
"portals": ["gem"],
"tender_amount_min": 1000000,
"tender_amount_max": 50000000
}'{
"range": {
"from": "2026-05-01",
"to": "2026-05-20"
},
"filters": {
"keywords": ["event management", "projection mapping"],
"states": ["Delhi", "Maharashtra"],
"portals": ["gem"],
"tender_amount_min": 1000000,
"tender_amount_max": 50000000
},
"new_tenders_count": 128,
"awarded_tenders_count": 17,
"total_new_tender_amount_crores": 42.5,
"total_awarded_amount_crores": 7.8,
"new_tender_amount": {
"total_crores": 42.5,
"known_tender_value_crores": 39.8,
"estimated_from_emd_crores": 2.7,
"known_tender_value_count": 113,
"estimated_from_emd_count": 9,
"missing_tender_value_count": 6
},
"awarded_amount": {
"total_crores": 7.8,
"known_contract_value_count": 15,
"missing_contract_value_count": 2
},
"generated_at": "2026-05-20T08:15:30Z"
}400401403404409429500503| Status | Meaning |
|---|---|
400 | Bad request: invalid timestamp, cursor, status, or an unsupported search parameter. |
401 | Missing or invalid API key. |
403 | API access is disabled for the account, or the request needs a capability not enabled for this key. |
404 | Filter, tender, or document not found. |
409 | Document is not available yet. Retry later. |
429 | Rate limit exceeded. Wait for Retry-After seconds. |
500 | Server error. Retry later or contact Tenderkart support. |
503 | A search query took too long. Retry with a narrower query. |
tenderkart_urlupdated_atpublished_atclosing_atcursornext_updated_afterunder_evaluationunknownboq| Term | Meaning |
|---|---|
tenderkart_url | Direct public Tenderkart page for the tender. Included in list, lookup, and detail responses. |
updated_at | Tenderkart system timestamp. Use it for integration sync. |
published_at | Source portal publication timestamp. Useful for tender-age reporting, not sync. |
closing_at | Tender bid submission deadline. Useful for reminders and open-tender workflows. |
cursor | Opaque pagination token. Send it exactly as returned for the next page. |
next_updated_after | Returned on the final page. Store it and pass it as updated_after next time. |
under_evaluation | Simple status bucket covering technical and financial evaluation stages. |
unknown | Response-only status for unmapped source statuses. It is not accepted as a query filter. |
boq | Bill of quantities document, usually an Excel or PDF pricing schedule. |
When to reach for each surface, incremental sync code, the shared rate-limit budget, and the hybrid setup most bid teams land on.
The full walkthrough: what MCP is, the seven tools your assistant gets, the OAuth model, and how to confirm the connection worked.
Copy-paste prompts for weekly triage, bid/no-bid screening, BOQ extraction, corrigendum diffs, and award analysis.