REST API

JSON over HTTPS. Base URL:

https://portal-demo.tender-lock.co/api/v1

Authentication

Send your organisation API key as a Bearer token on every request. Keys start with tl_live_ and are created in Settings → API & MCP.

Authorization: Bearer tl_live_YOUR_KEY

Errors

Errors return a non-2xx status and a JSON body:

{ "error": { "type": "not_found", "message": "Tender not found." } }
StatusMeaning
401Missing, invalid, expired or revoked key
402Not included in your plan
403Key lacks write access, or bids are still sealed
404Not found in your organisation
409Not allowed in the tender's current state
422Invalid input
429Rate limit: 120 requests per minute per key

Endpoints

GET/me

Who you are: organisation, key name, scopes and plan.

GET/tenders

List your organisation's tenders, newest first. Optional status filter: draft, pending_approval, live, closed, awarded, no_award, cancelled.

Query: status limit

GET/tenders/{id}

Full detail of one tender: scope, dates, requirements, evaluation criteria and invited suppliers.

POST/tenders needs write access

Create a DRAFT tender (never published). A person must review, run checks and publish it in TenderLock. closes_at is ISO 8601 in your organisation's time zone, e.g. 2026-11-30T12:00.

FieldType
titlestringrequired
descriptionstringrequired
closes_atstringrequired
categorystringoptional
estimated_valuenumberoptional
requirementsarrayoptional
criteriaarrayoptional
POST/tenders/{id}/suppliers needs write access

Add a supplier to a DRAFT tender. Nothing is sent: invitations go out only when a person publishes the tender.

FieldType
supplier_namestringrequired
emailstringrequired
GET/tenders/{id}/clarifications

Clarification questions and answers for a tender.

GET/tenders/{id}/submissions

Submitted bids for a tender, with prices and weighted scores. Only available after the closing date; bids stay sealed until then.

GET/tenders/{id}/audit

The append-only audit trail for a tender.

Query: limit

GET/suppliers

Search your supplier address book by company, email or category.

Query: q limit

POST/suppliers needs write access

Add a supplier to your address book.

FieldType
company_namestringrequired
emailstringrequired
contact_namestringoptional
categorystringoptional
GET/suppliers/{id}

One supplier from your address book with Companies House rating, latest Creditsafe credit check (score, band, limit, turnover, profit, CCJs) and the tenders they were invited to.

POST/suppliers/{id}/credit-check needs write access

Run a Creditsafe credit check on a supplier (Business plan and above). Uses credits; you are not charged if the check fails.

FieldType
supplier_idstringrequired
GET/tenders/{id}/blue-team

Blue Team items for a tender: gaps found, suggested fixes and whether each was applied or dismissed.

GET/tenders/{id}/red-team

The latest Red Team stress test for a tender: readiness, summary and every finding with severity, explanation and status.

GET/tenders/{id}/review

Who is on the Blue and Red review teams for a tender and the sign-offs recorded.

GET/entities

The companies (entities) in your group, with tender and people counts.

GET/team

Your team: roles, super admin and owner flags, entities, 2FA, invite status and last sign-in. Key must be created by an owner, super admin or team admin. Optional status: active, invited, disabled.

Query: status

GET/team/{id}

Full audit of one team member: details, roles, entities, 2FA devices, signed-in devices, failed sign-ins, tender stats and recent activity.

Query: limit

POST/team needs write access

Invite someone to your team with one or more roles (role keys or names, e.g. "Evaluator"). Emails the invitation and returns the invite link. Key must be created by an owner, super admin or team admin. Super admin can only be given in TenderLock.

FieldType
emailstringrequired
rolesarrayrequired
GET/templates

Your saved tender templates.

GET/reports/summary

Headline reporting numbers: tenders by status, created, published, awarded value, submissions and credits used. Optional days (default 90).

Query: days

GET/credits

Your organisation's plan and current credit balance.

Examples

Create a draft tender (curl)

curl -X POST https://portal-demo.tender-lock.co/api/v1/tenders \
  -H "Authorization: Bearer tl_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Office cleaning, Manchester HQ",
    "description": "Daily office cleaning for a 4,000 sq ft office...",
    "closes_at": "2026-11-30T12:00",
    "estimated_value": 24000,
    "requirements": [
      {"text": "Confirm you hold public liability insurance of at least £5m", "kind": "mandatory"}
    ],
    "criteria": [
      {"name": "Quality", "weight": 60},
      {"name": "Price", "weight": 40, "is_price": true}
    ]
  }'

List live tenders (Python)

import requests
r = requests.get("https://portal-demo.tender-lock.co/api/v1/tenders", params={"status": "live"},
                 headers={"Authorization": "Bearer tl_live_YOUR_KEY"})
for t in r.json()["data"]:
    print(t["title"], t["closes_at"])

Results after close (JavaScript)

const res = await fetch("https://portal-demo.tender-lock.co/api/v1/tenders/TENDER_ID/submissions", {
  headers: { Authorization: "Bearer tl_live_YOUR_KEY" }
});
const { data } = await res.json(); // ranked bids with weighted scores

Before you renew. Before you appoint. Before you buy.
TenderLock it.

Run your first live tender free. No card required.