Developer docs

Tenderen API (v1)

The Tenderen API is a JSON REST API for searching tenders, managing saved tenders, bids, alerts, teams and documents, and running AI analysis. It is available on the Enterprise plan and authenticated with API keys.

Base URL

All endpoints are versioned under /api/v1. Requests and responses are JSON over HTTPS.

https://api.tenderen.com/api/v1

Authentication

Send your API key as a Bearer token in the Authorization header. Keys are created in the app under Developers → API keys by a company Owner or Admin on the Enterprise plan. The full key is shown once; Tenderen stores only a SHA-256 hash of it. Keys can have an expiry date and can be revoked at any time.

curl "https://api.tenderen.com/api/v1/tenders?q=software&cpvCodes=72000000&limit=20" \
  -H "Authorization: Bearer $TENDEREN_API_KEY"

Scopes

Each key carries a list of scopes. New keys default to read-only (tenders:read). Calling an endpoint whose scope the key lacks returns 403 INSUFFICIENT_SCOPE.

Endpoints

Paths are relative to the base URL. The scope column shows the permission the key needs.

Tenders

MethodPathScopeWhat it does
GET/tenderstenders:readSearch tenders with filters and pagination.
GET/tenders/:idtenders:readGet one tender.
GET/tenders/:id/documentstenders:readList the documents attached to a tender.
GET/tenders/:id/requirementstenders:readList the requirements extracted from a tender.
GET/tenders/savedtenders:readList your company's saved tenders.
POST/tenders/savedtenders:writeSave a tender.
PATCH/tenders/saved/:idtenders:writeUpdate a saved tender.

Bids

MethodPathScopeWhat it does
POST/bidsbids:writeCreate a bid for a tender.
GET/bidsbids:readList bids.
GET/bids/:idbids:readGet one bid.
PATCH/bids/:idbids:writeUpdate a bid.
POST/bids/:id/submitbids:writeMark a bid as submitted.

AI analysis

MethodPathScopeWhat it does
POST/analysis/tender/:idanalysis:writeRun an AI analysis of a tender.
POST/analysis/risk/:idanalysis:writeRun an AI risk analysis of a tender.
POST/analysis/match/:idanalysis:writeScore how well a tender matches your company.
POST/analysis/gaps/:idanalysis:writeFind gaps between the requirements and your company profile.

Market data

MethodPathScopeWhat it does
GET/market/insightsmarket:readMarket statistics.
GET/market/awardsmarket:readSearch contract awards.
GET/market/competitorsmarket:readCompetitors seen in contract awards.

Alerts and notifications

MethodPathScopeWhat it does
GET/alertsalerts:readList alerts.
POST/alertsalerts:writeCreate an alert.
GET/alerts/:idalerts:readGet one alert.
PATCH/alerts/:idalerts:writeUpdate an alert.
DELETE/alerts/:idalerts:writeDelete an alert.
GET/alerts/notifications/listalerts:readList notifications.
PATCH/alerts/notifications/:id/readalerts:writeMark a notification as read.

Teams

MethodPathScopeWhat it does
GET/teamsteams:readList teams.
POST/teamsteams:writeCreate a team.
GET/teams/:idteams:readGet one team.
PATCH/teams/:idteams:writeUpdate a team.
GET/teams/:id/membersteams:readList team members.
POST/teams/:id/membersteams:writeAdd a team member.
DELETE/teams/:id/members/:memberIdteams:writeRemove a team member.

Consortiums

MethodPathScopeWhat it does
GET/consortiumstenders:readList consortiums.
POST/consortiumstenders:writeCreate a consortium for a tender.
GET/consortiums/:idtenders:readGet one consortium.
GET/consortiums/:id/memberstenders:readList consortium members.
POST/consortiums/:id/memberstenders:writeInvite a partner company.
GET/consortiums/:id/responsibilitiestenders:readList who is responsible for what.

Documents (assets)

MethodPathScopeWhat it does
GET/assetsassets:readList documents in your library.
POST/assetsassets:writeCreate a document record.
GET/assets/:idassets:readGet one document.
DELETE/assets/:idassets:writeDelete a document.
POST/assets/:id/uploadassets:writeUpload a file to a document record.
GET/assets/:id/downloadassets:readDownload a document.

Compliance

MethodPathScopeWhat it does
GET/compliance/:tenderIdcompliance:readCompliance matrix for a tender.
POST/compliance/espdcompliance:readGenerate an ESPD response.
GET/compliance/certifications/listcompliance:readList your company's certifications.

Chat with a tender

MethodPathScopeWhat it does
POST/chatchat:writeAsk a question about a tender.
GET/chat/:sessionId/messageschat:readGet the messages in a chat session.

Webhooks

MethodPathScopeWhat it does
POST/webhookswebhooks:manageRegister a webhook endpoint.
GET/webhookswebhooks:manageList webhook endpoints.
DELETE/webhooks/:idwebhooks:manageDelete a webhook endpoint.
GET/webhooks/:id/deliverieswebhooks:manageDelivery history for a webhook.

Account

MethodPathScopeWhat it does
GET/meaccount:readThe user and company the key belongs to.
GET/me/usageaccount:readAPI usage for the key.
GET/healthnoneHealth check (no authentication).

Pagination and filtering

List endpoints accept page (starting at 1) and limit (1–100, default 20) and return a pagination object with page, limit, total and pages. GET /tenders also accepts q, cpvCodes and regions (comma-separated), status, source, minValue, maxValue, deadlineBefore, deadlineAfter, sort (publishedAt, deadline or estimatedValue) and order (asc or desc).

{
  "success": true,
  "data": [ { "id": "…", "title": "…", "deadline": "…" } ],
  "pagination": { "page": 1, "limit": 20, "total": 412, "pages": 21 }
}

Errors

Errors return success: false with a human-readable error and a machine-readable code.

{
  "success": false,
  "error": "Insufficient permissions. Required scope: bids:write",
  "code": "INSUFFICIENT_SCOPE"
}
CodeHTTP statusMeaning
INVALID_AUTH401Missing, malformed or unknown API key.
KEY_INACTIVE401The key has been revoked.
KEY_EXPIRED401The key has passed its expiry date.
INSUFFICIENT_SCOPE403The key lacks the scope this endpoint needs.
INVALID_DATA400The request body failed validation; see details.
INVALID_PARAMS400A query or path parameter is invalid.
FORBIDDEN403You are not allowed to change this resource.
NOT_FOUND404The resource does not exist or belongs to another company.
RATE_LIMIT_EXCEEDED429Too many requests in the current hour.
INTERNAL_ERROR500Something failed on our side; retry later.

Rate limits

Each API key may make 1,000 requests per hour by default (the limit is stored per key). Going over returns 429 RATE_LIMIT_EXCEEDED; wait for the hourly window to reset. The MCP endpoint has its own limit of 1,000 requests per hour per token.

Webhooks

Status: you can register, list and delete webhook endpoints today, but event delivery is not live yet — no events are sent to registered endpoints at the moment. The format below is what deliveries will use. Poll the REST API (for example GET /alerts/notifications/list) until delivery ships.

Register an HTTPS endpoint with POST /webhooks and choose the events you want. The response contains a signing secret, shown only once.

Events

  • tender.new — A new tender matches one of your alerts.
  • tender.deadline — A followed tender's deadline is approaching.
  • tender.awarded — A followed tender has been awarded.
  • bid.submitted — A bid was marked as submitted.
  • bid.status_changed — A bid changed status.
  • alert.triggered — An alert produced new matches.

Verifying signatures

Every delivery is a POST with the JSON body {event, data, timestamp, webhookId} and the headers X-Tenderen-Event, X-Tenderen-Delivery and X-Tenderen-Signature. The signature is sha256= followed by the hex HMAC-SHA256 of the raw request body, keyed with your signing secret. Compare it in constant time before you trust the payload.

import crypto from 'node:crypto';

function isValidTenderenSignature(rawBody, signatureHeader, secret) {
  const expected =
    'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(signatureHeader ?? '');
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

A delivery that fails, or does not answer with a 2xx status within 10 seconds, is retried up to two more times: after 1 minute and after 5 minutes. The delivery history is available from GET /webhooks/:id/deliveries.

MCP connector for AI assistants

Tenderen runs a remote Model Context Protocol server, so AI assistants such as Claude, ChatGPT and Cursor can search tenders, assess fit, track a pipeline, draft bids and ask the tender documents on your behalf — 18 capability tools, with read access granted by default and writes, submissions and deletions as separate grants on the consent screen. Connect with OAuth (authorization code with PKCE; dynamic client registration is supported) or with an API key as a Bearer token. Tools that cannot be undone preview first and need confirmation. Every call is listed under Developers → AI connections, where connections can be tested and revoked.

MCP endpoint (Streamable HTTP)

https://tenderen.com/api/mcp

Legacy endpoint (HTTP+SSE)

https://tenderen.com/api/mcp/sse

OAuth discovery

https://tenderen.com/.well-known/oauth-authorization-server
https://tenderen.com/.well-known/oauth-protected-resource

Support

Questions about the API or a specific integration: [email protected].

Last reviewed 4 October 2026