Building BidRadar with Google AI Studio: Part 6 — Designing the REST API and Application Contracts

BidRadar Development Progress

██████░░░░░░░░░░░░░░ 6/60

Current phase: Strategy and development foundations
Current milestone: Define the application contracts before generating frontend or backend code
Previous article: Designing the Database Schema
Next article: Establishing the BidRadar Design System and User Experience
Primary deliverable: docs/api-specification.md
API framework: FastAPI
API style: Resource-oriented REST over HTTPS and JSON
Application code generated: None


Introduction

In the previous five articles, we established the foundation for BidRadar.

We defined:

  • The product vision
  • The target customer
  • The development workflow
  • The Product Requirements Document
  • The high-level system architecture
  • The PostgreSQL and pgvector database schema

We now understand:

  • What BidRadar must do
  • Which users it serves
  • How its major components fit together
  • Which data must be stored
  • How tenant ownership is represented
  • Which records require versioning
  • Which processes run asynchronously
  • Which AI activities require evidence and human review

The next step is to define how the application components communicate.

The React frontend will need to communicate with the FastAPI backend.

Background-processing interfaces will need to expose job status.

Tender-source connectors will need stable internal contracts.

Future Microsoft 365, CRM, and procurement-portal integrations will need controlled access points.

The frontend should not guess:

  • How an opportunity is represented
  • Which fields are required
  • How errors are formatted
  • How pagination works
  • How organization context is selected
  • How long-running jobs report progress
  • How versions are handled
  • How an AI analysis is requested
  • How approval actions are submitted

These decisions belong in an API specification.

This article defines the BidRadar REST API and Application Contracts.

The document we create will act as a boundary between:

  • Frontend and backend
  • API routes and service logic
  • Internal modules and external integrations
  • Synchronous requests and background processing
  • AI execution requests and persisted results
  • Human actions and automated workflows

The goal is not to implement every endpoint yet.

The goal is to create stable, consistent rules that future Google AI Studio prompts must follow when generating:

  • FastAPI routers
  • Pydantic schemas
  • React API clients
  • TanStack Query hooks
  • Integration tests
  • Mock data
  • Error handling
  • OpenAPI documentation

Objectives

After completing this article, we should have:

  • A documented REST API strategy
  • API versioning rules
  • Resource naming conventions
  • Authentication contracts
  • Organization-context rules
  • Authorization behavior
  • Standard request and response envelopes
  • Pagination contracts
  • Filtering and sorting conventions
  • Search conventions
  • Error-response formats
  • Validation-error formats
  • Idempotency rules
  • Optimistic-concurrency rules
  • Background-job contracts
  • File-upload contracts
  • Opportunity API contracts
  • Tender-document API contracts
  • Requirement API contracts
  • Analysis and scoring contracts
  • Knowledge-base API contracts
  • Proposal API contracts
  • Compliance API contracts
  • Workflow and approval contracts
  • Export contracts
  • AI execution and usage boundaries
  • Audit-access boundaries
  • Webhook and integration principles
  • A complete Google AI Studio API-design prompt
  • A manual review and validation checklist

Why Design the API Before Generating Code?

Google AI Studio could generate React screens and FastAPI endpoints immediately.

That would likely produce working code quickly.

It could also create inconsistencies such as:

  • One endpoint using camelCase while another uses snake_case
  • Different pagination formats across resources
  • Organization IDs supplied in unsafe request bodies
  • Raw database models returned directly
  • Different error formats for each module
  • Long-running AI operations blocking HTTP requests
  • Proposal versions overwritten through ordinary update endpoints
  • Approval actions mixed into generic patch requests
  • File uploads without checksums or processing states
  • AI prompts exposed to frontend clients
  • Inconsistent status names
  • Sensitive audit details returned to unauthorized users

A stable API contract prevents these inconsistencies.

The correct design sequence is:

Product requirements
Architecture
Database schema
API contracts
Frontend and backend generation

The API specification becomes the formal agreement between application layers.


API Design Principles

The BidRadar API should follow several core principles.

Principle 1 — Resource-Oriented Design

Primary business concepts should be represented as resources.

Examples include:

  • Organizations
  • Opportunities
  • Documents
  • Requirements
  • Knowledge documents
  • Proposals
  • Tasks
  • Exports

Principle 2 — Business Actions Are Explicit

Actions with business meaning should not be hidden inside generic updates.

Examples:

POST /opportunities/{id}/bid-decisions
POST /proposal-sections/{id}/approve
POST /documents/{id}/process
POST /proposals/{id}/exports

Principle 3 — Tenant Context Is Derived Securely

The backend must not trust arbitrary organization ownership supplied in request bodies.

Organization context should be derived from:

  • Authenticated user
  • Active organization selection
  • Verified organization membership
  • Resource ownership

Principle 4 — Long-Running Work Is Asynchronous

Operations such as:

  • OCR
  • Gemini analysis
  • Requirement extraction
  • Embedding generation
  • Proposal drafting
  • Compliance validation
  • DOCX export

should return a job reference rather than blocking the request until completion.

Principle 5 — Contracts Are Versioned

Breaking changes require a new API version or controlled compatibility strategy.

Principle 6 — Responses Are Predictable

Pagination, errors, metadata, and timestamps should use consistent structures.

Principle 7 — Internal Models Are Not Public Contracts

SQLAlchemy models should not be returned directly.

Pydantic response schemas define the API.

Principle 8 — Sensitive Internal Details Stay Server-Side

Clients should not receive:

  • Secret keys
  • Provider credentials
  • Raw stack traces
  • Internal prompt instructions
  • Storage credentials
  • Unredacted security metadata

API Base URL

The initial API should use a versioned prefix.

/api/v1

Example local URL:

http://localhost:8000/api/v1

Example production URL:

https://api.bidradar.example/api/v1

The actual domain will be configured later.


API Versioning Strategy

The initial version will be:

v1

Versioning applies to externally visible contracts.

Breaking Changes

Examples include:

  • Removing a field
  • Renaming a field
  • Changing a field type
  • Changing response structure
  • Changing mandatory request fields
  • Changing pagination behavior

These require:

  • A new API version
  • A documented migration
  • Or a controlled deprecation period

Non-Breaking Changes

Examples may include:

  • Adding an optional response field
  • Adding a new endpoint
  • Adding an optional filter
  • Adding a new enum value where clients are designed to tolerate it

Even non-breaking changes should be documented.


Content Types

Normal JSON requests should use:

Content-Type: application/json

File uploads should use:

multipart/form-data

Downloads should return the appropriate MIME type or a short-lived authorized download URL.


JSON Naming Convention

The recommended external JSON naming convention is:

snake_case

Example:

{
"submission_deadline": "2027-03-15T12:00:00Z",
"estimated_value_min": 250000.00,
"organization_id": "..."
}

This aligns naturally with Python and Pydantic.

The React application can use generated or shared TypeScript types using the same field names.

Consistency is more important than choosing camelCase or snake_case.


Date and Time Format

All timestamps should use ISO 8601.

Example:

2027-03-15T12:00:00Z

Rules:

  • Return UTC where practical.
  • Include timezone offsets.
  • Do not return ambiguous local timestamps.
  • Preserve original source text separately where imported deadlines were unclear.

Date-only values should use:

2027-03-15

Monetary Values

Money should be represented using decimal-safe JSON values and explicit currency codes.

Example:

{
"estimated_value_min": "250000.00",
"estimated_value_max": "500000.00",
"currency": "USD"
}

Returning decimal values as strings prevents accidental floating-point corruption across languages.

The final implementation may standardize this through shared money schemas.


Identifier Format

Public resource identifiers should use UUID strings.

Example:

8c1654d1-9f78-49f8-89ed-e5cf577bd28a

Clients should treat identifiers as opaque.

They should not infer:

  • Record age
  • Tenant
  • Sequence
  • Resource type

Authentication Contract

The initial API will support email-and-password authentication.

Future versions may add Microsoft Entra ID and other identity providers.


Registration

POST /api/v1/auth/register

Example request:

{
"email": "owner@example.com",
"password": "secure-password",
"display_name": "Proposal Owner"
}

Example response:

{
"user": {
"id": "uuid",
"email": "owner@example.com",
"display_name": "Proposal Owner",
"status": "pending_verification"
}
}

The registration response should not include:

  • Password hash
  • Verification token
  • Internal security fields

Login

POST /api/v1/auth/login

Example request:

{
"email": "owner@example.com",
"password": "secure-password"
}

Example response:

{
"access_token": "token",
"token_type": "bearer",
"expires_in": 900,
"refresh_token": "refresh-token",
"user": {
"id": "uuid",
"email": "owner@example.com",
"display_name": "Proposal Owner"
},
"memberships": [
{
"organization_id": "uuid",
"organization_name": "Example IT Consulting",
"role": "owner"
}
]
}

Refresh-token storage and transport security will be refined during authentication implementation.


Refresh Session

POST /api/v1/auth/refresh

The endpoint should rotate or validate refresh credentials according to the security design.


Logout

POST /api/v1/auth/logout

Logout should invalidate or revoke the relevant refresh session where supported.


Current User

GET /api/v1/auth/me

Example response:

{
"id": "uuid",
"email": "owner@example.com",
"display_name": "Proposal Owner",
"status": "active",
"memberships": [
{
"organization_id": "uuid",
"organization_name": "Example IT Consulting",
"role": "owner",
"membership_status": "active"
}
]
}

Organization Context

BidRadar supports tenant-scoped resources.

The API must know which organization the user is operating within.

The recommended pattern is an explicit request header:

X-Organization-ID: <uuid>

The backend must verify:

  1. The user is authenticated.
  2. The organization exists.
  3. The user has an active membership.
  4. The requested resource belongs to that organization.
  5. The role permits the requested action.

The header selects context.

It does not grant access.


Why Not Put Organization IDs in Every URL?

An alternative would be:

/organizations/{organization_id}/opportunities

This is explicit but creates long paths throughout the API.

The chosen design can still use organization-scoped routes for administrative resources while using the verified header for primary application resources.

Example:

GET /api/v1/opportunities
X-Organization-ID: uuid

This keeps resource URLs concise while preserving explicit tenant context.

The final choice must remain consistent.


Organization Endpoints

POST /organizations
GET /organizations
GET /organizations/{organization_id}
PATCH /organizations/{organization_id}

Membership endpoints:

GET /organizations/{organization_id}/members
POST /organizations/{organization_id}/invitations
PATCH /organizations/{organization_id}/members/{membership_id}
DELETE /organizations/{organization_id}/members/{membership_id}

Administrative organization routes should validate that the user has sufficient permissions for the target organization.


Authorization Response Behavior

Unauthorized and inaccessible resources must not leak information.

Unauthenticated

Return:

401 Unauthorized

Authenticated but Insufficient Permission

Return:

403 Forbidden

Resource Outside Active Tenant

Depending on security policy, return:

404 Not Found

This can avoid confirming that a resource exists in another organization.

The policy should be consistent and documented.


Standard Resource Metadata

Most resource responses should include:

{
"id": "uuid",
"created_at": "2027-03-01T10:00:00Z",
"updated_at": "2027-03-02T11:30:00Z"
}

Versioned resources may also include:

{
"version_number": 3,
"version_token": "opaque-concurrency-token"
}

Standard Collection Response

Collections should use a predictable structure.

{
"items": [],
"page": {
"limit": 25,
"offset": 0,
"total": 146,
"has_more": true
}
}

For very large or rapidly changing collections, cursor pagination may be preferable.

The initial API can support offset pagination for administrative lists and cursor pagination for activity streams and large data sets.


Pagination Parameters

Standard offset pagination:

limit
offset

Example:

GET /opportunities?limit=25&offset=50

Rules:

  • Default limit: 25
  • Maximum limit: 100
  • Negative values rejected
  • Total count may be omitted for expensive queries if documented

Cursor Pagination

Activity feeds, audit events, or notifications may use:

cursor
limit

Example response:

{
"items": [],
"next_cursor": "opaque-cursor",
"has_more": true
}

Cursors must be opaque to clients.


Filtering Convention

Filters should use query parameters.

Example:

GET /opportunities?status=reviewing&country_code=NL

Multiple values can use repeated parameters:

GET /opportunities?status=new&status=reviewing

or comma-separated values if standardized.

Repeated query parameters are easier to represent accurately.


Sorting Convention

Use:

sort

Example:

GET /opportunities?sort=submission_deadline
GET /opportunities?sort=-created_at

Rules:

  • A leading minus means descending.
  • Only documented fields are sortable.
  • Invalid fields return a validation error.
  • Stable secondary sorting should be applied internally.

Search Convention

Use:

q

Example:

GET /opportunities?q=azure+migration

Structured filters should remain separate from free-text search.

Example:

GET /opportunities?q=azure&country_code=NL&status=reviewing

Field Selection and Expansion

The initial API should avoid excessive complexity.

Optional controlled expansion may use:

include

Example:

GET /opportunities/{id}?include=buyer,latest_analysis

Expansion should be limited to documented relationships.

Clients should not be allowed to create arbitrary deep joins.


Standard Success Response

Single-resource endpoints may return the resource directly.

Example:

{
"id": "uuid",
"title": "Cloud Migration Services",
"status": "reviewing"
}

Action endpoints may return:

{
"data": {
"job_id": "uuid",
"status": "queued"
},
"message": "Tender analysis was queued."
}

The API should not wrap some resources and not others without a clear rule.

A simple approach is:

  • Direct resource objects for ordinary CRUD
  • Explicit action-result objects for business operations
  • Standard collection envelopes for lists

Standard Error Contract

Errors should use one consistent format.

Example:

{
"error": {
"code": "opportunity_not_found",
"message": "The requested opportunity could not be found.",
"request_id": "req_123",
"details": null
}
}

Validation error example:

{
"error": {
"code": "validation_error",
"message": "The request contains invalid values.",
"request_id": "req_123",
"details": [
{
"field": "submission_deadline",
"message": "Submission deadline must be later than publication date.",
"type": "value_error"
}
]
}
}

Error-Code Principles

Error codes should be:

  • Stable
  • Machine-readable
  • Lowercase snake_case
  • More precise than HTTP status alone

Examples:

authentication_required
invalid_credentials
organization_context_required
membership_inactive
permission_denied
opportunity_not_found
document_type_unsupported
processing_already_running
version_conflict
ai_provider_unavailable
usage_limit_exceeded

HTTP Status Codes

Use standard HTTP semantics.

200 OK

Successful retrieval or update.

201 Created

Resource created.

202 Accepted

Asynchronous operation accepted.

204 No Content

Successful deletion or action without response body.

400 Bad Request

Malformed or semantically invalid request.

401 Unauthorized

Authentication required or invalid.

403 Forbidden

Authenticated but not authorized.

404 Not Found

Resource unavailable within the authorized context.

409 Conflict

Version conflict, duplicate record, or invalid state transition.

413 Payload Too Large

File exceeds allowed size.

415 Unsupported Media Type

Unsupported file format.

422 Unprocessable Entity

Schema validation error.

429 Too Many Requests

Rate or usage limit reached.

500 Internal Server Error

Unexpected application error.

502 Bad Gateway

External provider returned an invalid response.

503 Service Unavailable

Dependency temporarily unavailable.


Request Correlation

Every API response should expose a request identifier.

Example header:

X-Request-ID: req_123

Clients should display or record this identifier when reporting errors.

Background jobs should also use correlation IDs linking:

  • Initial request
  • Job
  • Worker logs
  • Gemini execution
  • Persisted result

Idempotency

Certain POST operations may be retried by clients.

Examples include:

  • Creating an opportunity from an external event
  • Starting a document upload
  • Requesting an export
  • Submitting a Bid/No-Bid approval

The API should support:

Idempotency-Key: <client-generated-value>

The backend should scope idempotency by:

  • Organization
  • User or client
  • Endpoint
  • Key

Repeated equivalent requests should return the original result where practical.


Optimistic Concurrency

Collaborative and versioned resources must protect against lost updates.

Clients should submit a version token or revision number.

Example header:

If-Match: "version-token"

or request field:

{
"expected_version": 4
}

If the stored version changed, return:

409 Conflict

Example error code:

version_conflict

This is particularly important for:

  • Opportunity updates
  • Requirement edits
  • Proposal-section edits
  • Organization settings
  • Workflow tasks

Soft Deletion API Behavior

Ordinary deletion endpoints should generally archive or soft-delete records where history matters.

Example:

DELETE /opportunities/{id}

Possible response:

204 No Content

The implementation may set deleted_at rather than physically removing the record.

Restore endpoints may be introduced for authorized administrators.

Permanent deletion should use specialized administrative workflows.


Background Job Contract

Long-running operations should return:

202 Accepted

Example response:

{
"job": {
"id": "uuid",
"job_type": "requirement_extraction",
"status": "queued",
"resource_type": "opportunity",
"resource_id": "uuid",
"progress_percent": 0,
"created_at": "2027-03-01T10:00:00Z"
}
}

Job Status Endpoint

GET /jobs/{job_id}

Example response:

{
"id": "uuid",
"job_type": "requirement_extraction",
"status": "running",
"progress_percent": 65,
"attempt_count": 1,
"started_at": "2027-03-01T10:01:00Z",
"completed_at": null,
"result": null,
"error": null
}

Completed example:

{
"id": "uuid",
"status": "completed",
"progress_percent": 100,
"result": {
"resource_type": "requirement_batch",
"resource_id": "uuid"
}
}

Job Error Contract

{
"id": "uuid",
"status": "failed",
"error": {
"code": "document_extraction_failed",
"message": "Text could not be extracted from the uploaded document.",
"retryable": true
}
}

The frontend should not receive raw provider errors.


Cancelling Jobs

Where safe:

POST /jobs/{job_id}/cancel

Cancellation may be unavailable after an irreversible processing stage.

The API should return a conflict if cancellation is not possible.


File-Upload Contract

The document-upload workflow should separate registration, transfer, and processing where practical.

For the MVP, a direct multipart endpoint is acceptable.

POST /opportunities/{opportunity_id}/documents
Content-Type: multipart/form-data

Fields:

file
document_type
title

Example response:

{
"document": {
"id": "uuid",
"title": "Technical Specification",
"document_type": "technical_specification",
"status": "uploaded",
"current_version": {
"id": "uuid",
"original_filename": "technical-specification.pdf",
"mime_type": "application/pdf",
"file_size_bytes": 3259184,
"checksum_sha256": "..."
}
},
"processing_job": {
"id": "uuid",
"status": "queued"
}
}

Upload Validation

The API must validate:

  • Organization permission
  • Opportunity ownership
  • File size
  • File type
  • MIME type
  • File name
  • Checksum
  • Malware-scanning policy hook
  • Duplicate status where relevant

Direct-to-Storage Uploads

A later optimized flow may use:

POST /documents/upload-sessions

Response:

{
"upload_session_id": "uuid",
"upload_url": "short-lived-authorized-url",
"expires_at": "..."
}

After upload:

POST /documents/upload-sessions/{id}/complete

Permanent storage credentials must never be returned.


Opportunity API


List Opportunities

GET /opportunities

Supported filters may include:

status
owner_user_id
buyer_id
country_code
publication_date_from
publication_date_to
submission_deadline_from
submission_deadline_to
estimated_value_min
estimated_value_max
currency
classification_code
q
sort
limit
offset

Create Opportunity

POST /opportunities

Example request:

{
"title": "Cloud Infrastructure Modernization",
"buyer_id": "uuid",
"external_reference": "RFP-2027-102",
"description": "Modernization of public-sector cloud infrastructure.",
"publication_date": "2027-03-01",
"submission_deadline": "2027-04-15T12:00:00Z",
"estimated_value_min": "500000.00",
"estimated_value_max": "1000000.00",
"currency": "USD",
"country_code": "US"
}

The client should not supply organization_id in the body.


Get Opportunity

GET /opportunities/{opportunity_id}

The response may include links or summary references to:

  • Buyer
  • Documents
  • Requirements
  • Latest analysis
  • Latest score
  • Current Bid decision
  • Proposal
  • Processing state

Large nested collections should remain separate endpoints.


Update Opportunity

PATCH /opportunities/{opportunity_id}

Use partial updates.

Immutable source fields may require specialized endpoints or permissions.

Concurrency controls should apply.


Archive Opportunity

POST /opportunities/{opportunity_id}/archive

Explicit action endpoints may be clearer than generic deletion when lifecycle meaning matters.


Opportunity Documents

GET /opportunities/{opportunity_id}/documents
POST /opportunities/{opportunity_id}/documents

Opportunity Requirements

GET /opportunities/{opportunity_id}/requirements

Opportunity Analysis

GET /opportunities/{opportunity_id}/analyses
POST /opportunities/{opportunity_id}/analyses

Example request:

{
"analysis_type": "executive_briefing",
"document_version_ids": [
"uuid",
"uuid"
]
}

Response:

202 Accepted

with a job reference.


Opportunity Score

GET /opportunities/{opportunity_id}/scores
POST /opportunities/{opportunity_id}/scores

Scoring requests may allow selected configuration:

{
"scoring_profile_id": "uuid",
"include_ai_analysis": true
}

Weights should not be accepted arbitrarily from unauthorized users.


Bid Decision Contract

Create a decision:

POST /opportunities/{opportunity_id}/bid-decisions

Example request:

{
"decision": "bid_with_conditions",
"opportunity_score_id": "uuid",
"reason": "Strong technical fit, subject to partner confirmation.",
"conditions": [
"Confirm subcontractor availability",
"Complete security certification review"
]
}

The backend records the authenticated human actor.


Tender Document API

GET /documents/{document_id}
PATCH /documents/{document_id}
POST /documents/{document_id}/versions
POST /documents/{document_id}/process
GET /documents/{document_id}/extractions
POST /documents/{document_id}/archive

Download:

GET /document-versions/{document_version_id}/download

The response may redirect to or return a short-lived authorized URL.


Document Extraction Response

{
"id": "uuid",
"document_version_id": "uuid",
"status": "completed",
"processor_type": "pdf_native",
"processor_version": "1.0",
"page_count": 142,
"character_count": 385921,
"language_code": "en",
"quality_score": 0.97,
"created_at": "..."
}

Extracted content may use separate paginated endpoints.

GET /document-extractions/{id}/pages

Requirement API


List Requirements

GET /opportunities/{opportunity_id}/requirements

Filters:

category
mandatory_level
status
reviewed
q

Create Requirement Manually

POST /opportunities/{opportunity_id}/requirements

Example request:

{
"title": "ISO 27001 Certification",
"requirement_text": "The supplier must maintain ISO 27001 certification.",
"category": "security",
"mandatory_level": "mandatory",
"response_type": "evidence",
"evidence_expected": "Valid ISO 27001 certificate"
}

Origin should be recorded as human-created.


Start Requirement Extraction

POST /opportunities/{opportunity_id}/requirement-extractions

Example request:

{
"document_version_ids": [
"uuid",
"uuid"
],
"extraction_profile": "standard_tender_requirements"
}

Response:

202 Accepted

Get Requirement

GET /requirements/{requirement_id}

Include:

  • Current accepted content
  • Source reference
  • Confidence
  • Review status
  • Version summary

Edit Requirement

POST /requirements/{requirement_id}/versions

Creating a new version is safer than overwriting accepted text.

Example request:

{
"requirement_text": "Updated reviewed requirement text.",
"category": "security",
"mandatory_level": "mandatory",
"change_summary": "Clarified certificate validity requirement.",
"expected_version": 2
}

Review Requirement

POST /requirements/{requirement_id}/reviews

Example request:

{
"decision": "accepted",
"comments": "Confirmed against page 32 of the specification."
}

Possible decisions:

accepted
edited
rejected

Analysis API

Analysis resources should expose versioned records.

GET /analyses/{analysis_id}
GET /opportunities/{opportunity_id}/analyses

The response should include:

  • Type
  • Version
  • Status
  • Structured result
  • Confidence
  • Evidence references
  • AI execution metadata summary
  • Human review status

It should not expose private system prompts.


Knowledge API


List Knowledge Documents

GET /knowledge-documents

Filters:

knowledge_type
status
security_classification
owner_user_id
effective_at
q

Upload Knowledge Document

POST /knowledge-documents

Multipart fields:

file
knowledge_type
title
description
security_classification

Response includes:

  • Knowledge document
  • Initial version
  • Processing job

Review Knowledge Metadata

PATCH /knowledge-documents/{knowledge_document_id}

Approve Knowledge Version

POST /knowledge-versions/{version_id}/approve

Example request:

{
"comments": "Approved for proposal evidence use."
}

Archive Knowledge Document

POST /knowledge-documents/{id}/archive

Search Knowledge

POST /knowledge-search

A POST request is appropriate because search may include a structured body.

Example request:

{
"query": "Azure migration experience for healthcare customers",
"search_mode": "hybrid",
"filters": {
"knowledge_types": [
"case_study",
"project_reference"
],
"technologies": [
"Microsoft Azure"
],
"industries": [
"Healthcare"
],
"approval_status": "approved"
},
"limit": 10
}

Example response:

{
"results": [
{
"knowledge_chunk_id": "uuid",
"knowledge_document_id": "uuid",
"title": "Healthcare Azure Migration",
"heading": "Project Outcomes",
"content_excerpt": "...",
"semantic_score": 0.91,
"keyword_score": 0.72,
"combined_score": 0.88,
"source_reference": "Page 4",
"metadata": {
"industry": "Healthcare",
"technology": "Microsoft Azure"
}
}
],
"search_metadata": {
"query_id": "uuid",
"search_mode": "hybrid",
"latency_ms": 184
}
}

Permission filtering must happen server-side.


Proposal API


Create Proposal

POST /opportunities/{opportunity_id}/proposals

Example request:

{
"title": "Response to Cloud Infrastructure Modernization RFP",
"template_key": "standard_it_services"
}

Get Proposal

GET /proposals/{proposal_id}

Response may include:

  • Proposal metadata
  • Status
  • Owner
  • Section summary
  • Requirement coverage summary
  • Pending approvals
  • Latest compliance status

List Proposal Sections

GET /proposals/{proposal_id}/sections

Return hierarchy and ordering.


Create Proposal Outline

POST /proposals/{proposal_id}/outline-generations

Example request:

{
"requirement_ids": [
"uuid",
"uuid"
],
"template_key": "standard_it_services",
"include_contributor_recommendations": true
}

Response:

202 Accepted

Create or Update Section Structure

POST /proposals/{proposal_id}/sections
PATCH /proposal-sections/{section_id}

Structural updates should not overwrite section content versions.


Generate Proposal Section Draft

POST /proposal-sections/{section_id}/draft-generations

Example request:

{
"requirement_ids": [
"uuid"
],
"knowledge_chunk_ids": [],
"generation_profile": "evidence_backed_standard",
"instructions": "Emphasize phased migration and service continuity."
}

The backend may retrieve evidence automatically.

User-supplied knowledge chunk IDs must still be authorized.


Get Section Versions

GET /proposal-sections/{section_id}/versions

Create Human-Edited Version

POST /proposal-sections/{section_id}/versions

Example request:

{
"content": "Reviewed proposal content...",
"content_format": "markdown",
"change_summary": "Added delivery governance and transition detail.",
"expected_version": 5
}

Approve Proposal Section

POST /proposal-sections/{section_id}/approve

Example request:

{
"version_id": "uuid",
"comments": "Technical review completed."
}

The version must belong to the section and active organization.


Request Changes

POST /proposal-sections/{section_id}/request-changes

Lock and Unlock Section

POST /proposal-sections/{section_id}/locks
DELETE /proposal-sections/{section_id}/locks/{lock_id}

Locks should be temporary and separately authorized.


Comments API

GET /proposal-sections/{section_id}/comments
POST /proposal-sections/{section_id}/comments
POST /comments/{comment_id}/resolve

Threaded replies may use:

{
"content": "Please add stronger evidence for this claim.",
"parent_comment_id": "uuid"
}

Reviews API

POST /proposal-sections/{section_id}/reviews
GET /proposal-sections/{section_id}/reviews
POST /reviews/{review_id}/complete

Review completion request:

{
"decision": "changes_requested",
"comments": "Clarify the identity and access-management approach."
}

Compliance API

Start validation:

POST /proposals/{proposal_id}/compliance-runs

Example request:

{
"proposal_section_version_policy": "latest_approved_or_current",
"include_ai_semantic_review": true
}

Response:

202 Accepted

List runs:

GET /proposals/{proposal_id}/compliance-runs

Get findings:

GET /compliance-runs/{run_id}/findings

Filters:

severity
finding_type
coverage_status
review_status

Review finding:

POST /compliance-findings/{finding_id}/reviews

Workflow API


Workflow Templates

GET /workflow-templates
POST /workflow-templates
GET /workflow-templates/{id}
PATCH /workflow-templates/{id}
POST /workflow-templates/{id}/archive

Start Workflow

POST /proposals/{proposal_id}/workflows

Example request:

{
"workflow_template_id": "uuid",
"name": "Standard Government IT Proposal Workflow"
}

Tasks

GET /tasks
GET /tasks/{task_id}
POST /workflows/{workflow_id}/tasks
PATCH /tasks/{task_id}
POST /tasks/{task_id}/complete
POST /tasks/{task_id}/reassign

Task filters:

status
priority
owner_user_id
proposal_id
due_before
overdue

Approvals API

Create approval request:

POST /approvals

Example request:

{
"approval_type": "final_proposal",
"resource_type": "proposal",
"resource_id": "uuid",
"assigned_to_user_id": "uuid",
"message": "Please approve the final proposal for export."
}

Decide:

POST /approvals/{approval_id}/decisions

Example:

{
"decision": "approved",
"reason": "All mandatory requirements are covered."
}

The decision actor is derived from authentication.


Notifications API

GET /notifications
POST /notifications/{id}/read
POST /notifications/read-all
POST /notifications/{id}/dismiss

Notifications should not expose confidential content beyond the recipient’s permissions.


Export API

Create export:

POST /proposals/{proposal_id}/exports

Example request:

{
"export_type": "docx",
"template_key": "standard_it_services",
"citation_mode": "footnotes",
"include_appendices": true,
"appendix_types": [
"consultant_cvs",
"certifications",
"case_studies"
]
}

Response:

202 Accepted

Get export:

GET /exports/{export_id}

Download:

GET /exports/{export_id}/download

The download endpoint should verify:

  • Organization
  • User permission
  • Export status
  • Retention state

AI Execution API Boundary

Most product users should not interact with raw AI executions directly.

Product endpoints should initiate domain actions such as:

  • Analyze opportunity
  • Extract requirements
  • Generate outline
  • Draft section
  • Validate proposal

Administrative or diagnostic access may use:

GET /ai-executions
GET /ai-executions/{id}

Responses should include safe metadata:

{
"id": "uuid",
"feature": "proposal_section_draft",
"status": "completed",
"provider": "google",
"model": "configured-model-name",
"prompt_key": "proposal-section-draft",
"prompt_version": "2",
"latency_ms": 5240,
"input_tokens": 18240,
"output_tokens": 1340,
"estimated_cost": "0.12",
"currency": "USD",
"created_at": "..."
}

It should not expose:

  • API keys
  • Full hidden instructions
  • Unauthorized source content
  • Sensitive provider diagnostics

AI Feedback API

POST /ai-executions/{id}/feedback

Example request:

{
"feedback_type": "edited",
"rating": 4,
"comment": "Useful draft, but technical assumptions required correction."
}

Usage API

Authorized users may access organization usage.

GET /usage/ai

Filters:

date_from
date_to
feature
model
user_id

Example response:

{
"summary": {
"request_count": 184,
"input_tokens": 2145000,
"output_tokens": 182000,
"estimated_cost": "87.42",
"currency": "USD"
},
"breakdown": []
}

Access should be limited to owners, administrators, or authorized financial roles.


Audit API

Audit events are sensitive.

GET /audit-events
GET /audit-events/{id}

Filters may include:

action
actor_user_id
resource_type
resource_id
date_from
date_to
correlation_id

Responses should redact:

  • Secrets
  • Password material
  • Raw tokens
  • Excessive document content
  • Sensitive provider payloads

Health and Operations API

Public or infrastructure endpoints should remain separate from normal business APIs.

GET /health
GET /ready
GET /version

/health

Confirms the process is running.

/ready

Confirms required dependencies are available.

/version

Returns release metadata without exposing sensitive configuration.

Example:

{
"service": "bidradar-api",
"version": "0.1.0",
"commit": "short-sha",
"environment": "staging"
}

API Schema Separation

Pydantic schemas should be separated by responsibility.

Example conceptual categories:

OpportunityCreate
OpportunityUpdate
OpportunitySummary
OpportunityDetail
OpportunityListResponse

Avoid using one schema for:

  • Create
  • Update
  • Database model
  • Response
  • Internal service input

Different contexts have different security and validation requirements.


Create Versus Update Contracts

Create schemas should include only client-settable fields.

Update schemas should:

  • Make fields optional
  • Exclude immutable fields
  • Support concurrency
  • Validate state transitions

Response schemas may include:

  • IDs
  • Timestamps
  • Derived state
  • Relationship summaries
  • Permissions

Permission Hints

The backend may include UI-support metadata.

Example:

{
"permissions": {
"can_edit": true,
"can_delete": false,
"can_request_analysis": true,
"can_approve": false
}
}

These hints improve the UI.

They do not replace backend authorization.


Status Transition Contracts

Clients should not freely patch statuses when transitions carry business meaning.

Unsafe:

PATCH /opportunities/{id}
{
"status": "submitted"
}

Safer:

POST /proposals/{id}/mark-submitted

or a documented transition endpoint.

This allows the service layer to validate:

  • Required approvals
  • Export status
  • Submission metadata
  • Current state
  • Actor permissions

Bulk Operations

Bulk endpoints may be useful later.

Examples:

POST /opportunities/bulk-archive
POST /requirements/bulk-review
POST /tasks/bulk-reassign

Bulk operations must:

  • Limit batch size
  • Validate every item
  • Report partial failures clearly
  • Preserve tenant scope
  • Use asynchronous processing for large operations

They are not required in the initial MVP unless a user journey clearly requires them.


Webhook Principles

Future integrations may receive event notifications.

Potential webhook events include:

opportunity.created
document.processing_completed
requirement.extraction_completed
proposal.approved
export.completed

Webhook design should include:

  • Signed requests
  • Event IDs
  • Event version
  • Retry behavior
  • Idempotency
  • Delivery history
  • Secret rotation

Production webhooks are deferred until integration phases.


Internal Events Versus Public Webhooks

Internal domain events coordinate BidRadar modules.

Public webhooks notify external systems.

These are not the same contract.

Internal event schemas may evolve more quickly.

Public webhook schemas require stronger compatibility guarantees.


Rate Limiting

Rate limits should consider:

  • IP address
  • User
  • Organization
  • Endpoint
  • AI cost
  • File size
  • External integration quotas

Example headers:

X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-Reset

AI operations may use budget limits rather than ordinary request counts alone.


Usage-Limit Errors

Example:

{
"error": {
"code": "ai_usage_limit_exceeded",
"message": "The organization has reached its monthly AI usage limit.",
"request_id": "req_123",
"details": {
"period": "2027-03",
"limit_type": "estimated_cost"
}
}
}

Security Requirements for API Contracts

The API must:

  • Require HTTPS in production.
  • Validate bearer tokens.
  • Validate organization membership.
  • Enforce permissions server-side.
  • Validate all request bodies.
  • Sanitize file names.
  • Restrict upload size and media type.
  • Avoid mass-assignment vulnerabilities.
  • Avoid returning internal database fields.
  • Avoid exposing secrets.
  • Redact sensitive logs.
  • Apply rate limits.
  • Record sensitive actions.
  • Enforce tenant scope during search and retrieval.

Mass-Assignment Prevention

Generated code should never automatically map all JSON fields to ORM objects.

Clients must not be able to set:

  • organization_id
  • created_by_user_id
  • approved_by_user_id
  • status where controlled by workflow
  • current_version_id
  • ai_execution_id
  • storage_key
  • checksum_sha256
  • Audit fields

Create and update schemas must explicitly permit fields.


Search Security

Knowledge and semantic-search endpoints must enforce access before returning results.

The client must not be allowed to bypass filtering through:

  • Direct chunk IDs
  • Document IDs
  • Customer metadata
  • Security classification
  • Archived-version references

Every returned search result must be authorized.


Prompt-Injection Security

Document content is untrusted.

The API should not expose an endpoint that accepts arbitrary instructions and automatically grants unrestricted tool access.

AI action requests should use controlled fields such as:

{
"generation_profile": "evidence_backed_standard",
"instructions": "Emphasize service continuity."
}

User instructions are treated as bounded content, not system policy.


OpenAPI Documentation

FastAPI can generate OpenAPI documentation automatically.

The API specification should still be written first.

Generated OpenAPI must include:

  • Endpoint summary
  • Description
  • Authentication requirements
  • Request schema
  • Response schema
  • Error responses
  • Tags
  • Deprecation state
  • Examples where useful

Automatic documentation quality depends on well-designed routers and Pydantic schemas.


API Tags

Suggested tags include:

Authentication
Organizations
Opportunities
Tender Documents
Requirements
Analysis
Scoring
Knowledge
Proposals
Compliance
Workflows
Approvals
Notifications
Exports
Jobs
Usage
Audit
Operations

Contract Testing

The API implementation should later include:

  • Schema tests
  • Authentication tests
  • Permission tests
  • Tenant-isolation tests
  • Pagination tests
  • Filtering tests
  • Error-format tests
  • Concurrency tests
  • Idempotency tests
  • File-upload tests
  • Background-job tests
  • OpenAPI snapshot or compatibility tests

Frontend Contract Generation

The React frontend should not manually redefine every backend type.

Possible approaches include:

  • Generating TypeScript types from OpenAPI
  • Maintaining shared schema packages
  • Using a typed API client generator

The initial implementation can generate TypeScript contracts from the FastAPI OpenAPI document.

This reduces drift between:

  • Pydantic schemas
  • API clients
  • Form types
  • Query hooks

Mock API Strategy

Before the real FastAPI backend is complete, Google AI Studio may generate mock frontend data.

Mock contracts must match the API specification.

Mock data should not invent an alternate schema.

For example, a mock opportunity should use:

{
"id": "uuid",
"title": "Cloud Migration Services",
"status": "reviewing",
"submission_deadline": "2027-04-15T12:00:00Z",
"currency": "USD"
}

The mock layer should be replaceable by the real API client.


API Evolution Strategy

Each contract change should answer:

  • Is this breaking?
  • Which clients are affected?
  • Is a migration period required?
  • Must old fields remain temporarily?
  • Does the OpenAPI document change?
  • Do frontend types need regeneration?
  • Do integration tests need updates?

API changes should be reviewed like database migrations.


REST API Resource Map

The high-level endpoint map is:

/api/v1
├── /auth
├── /organizations
├── /opportunities
├── /buyers
├── /tender-sources
├── /tender-imports
├── /documents
├── /document-versions
├── /document-extractions
├── /requirements
├── /analyses
├── /opportunity-scores
├── /bid-decisions
├── /knowledge-documents
├── /knowledge-versions
├── /knowledge-search
├── /proposals
├── /proposal-sections
├── /comments
├── /reviews
├── /compliance-runs
├── /compliance-findings
├── /workflow-templates
├── /workflows
├── /tasks
├── /approvals
├── /notifications
├── /exports
├── /jobs
├── /ai-executions
├── /usage
└── /audit-events

Not all endpoints will be implemented immediately.

The contract document distinguishes MVP endpoints from future endpoints.


MVP API Scope

The initial MVP API should prioritize one complete vertical workflow.

Authentication and Organization

  • Register
  • Login
  • Current user
  • Create organization
  • List memberships
  • Invite user

Opportunity

  • Create
  • List
  • Get
  • Update

Tender Documents

  • Upload
  • List
  • Get processing status
  • Download

Analysis

  • Start summary
  • Start requirement extraction
  • Get job
  • Get results

Scoring

  • Start score
  • Get score
  • Create human Bid decision

Knowledge

  • Upload
  • List
  • Approve
  • Search

Proposal

  • Create
  • Generate outline
  • List sections
  • Generate section draft
  • Save human edit
  • Approve section

Compliance

  • Start validation
  • List findings

Export

  • Request DOCX
  • Get export status
  • Download

Deferred API Scope

Deferred endpoints include:

  • Live procurement-portal submissions
  • Advanced CRM synchronization
  • Microsoft Graph integrations
  • Slack and Teams external notification delivery
  • Real-time co-editing
  • Predictive analytics
  • External customer APIs
  • Public webhooks
  • Fine-grained custom permission management
  • Autonomous agent execution APIs

API Risks


Risk 1 — Overly Generic CRUD

Problem

Business rules are bypassed through unrestricted patch endpoints.

Mitigation

Use explicit action endpoints for approvals, processing, generation, and lifecycle transitions.


Risk 2 — Inconsistent Contracts

Problem

Each generated feature uses its own error and pagination format.

Mitigation

Define shared API conventions before implementation.


Risk 3 — Tenant IDs Trusted from Clients

Problem

Attackers may attempt cross-tenant access by changing organization IDs.

Mitigation

Verify membership, resource ownership, and active organization on every request.


Risk 4 — Long Requests Time Out

Problem

AI and document processing run synchronously.

Mitigation

Use 202 Accepted and durable background-job resources.


Risk 5 — Lost Collaborative Edits

Problem

One user overwrites another user’s proposal update.

Mitigation

Use version tokens and optimistic concurrency.


Risk 6 — Internal AI Details Exposed

Problem

Prompts, provider errors, or confidential context reach the browser.

Mitigation

Return safe summaries and retain sensitive diagnostics server-side.


Risk 7 — Contract Drift

Problem

React types, Pydantic schemas, and documentation diverge.

Mitigation

Generate OpenAPI, produce typed clients, and add contract tests.


Recommended API Specification Document

Create:

docs/
└── api-specification.md

Recommended structure:

# BidRadar REST API and Application Contracts
## Document Control
## Purpose
## API Principles
## Base URL and Versioning
## Authentication
## Organization Context
## Authorization
## Naming and Data Formats
## Standard Responses
## Pagination
## Filtering
## Sorting
## Search
## Error Contract
## Idempotency
## Concurrency
## Background Jobs
## File Uploads
## Organizations
## Opportunities
## Documents
## Requirements
## Analyses
## Opportunity Scoring
## Bid Decisions
## Knowledge
## Semantic Search
## Proposals
## Proposal Sections
## Collaboration
## Compliance
## Workflows
## Tasks
## Approvals
## Notifications
## Exports
## AI Execution Metadata
## Usage
## Audit
## Operations
## Rate Limits
## Security
## OpenAPI
## Contract Testing
## MVP Endpoints
## Deferred Endpoints
## Risks
## Open Questions

Open API Questions

Several decisions remain open.

  • Should organization context use a header, path prefix, or token claim?
  • Should refresh tokens use secure cookies or response bodies?
  • Which collections should use cursor pagination from the start?
  • Should monetary values always be returned as strings?
  • Should proposal content use Markdown, HTML, or a structured editor format?
  • Which operations require idempotency keys?
  • Should optimistic concurrency use ETags or explicit version fields?
  • Should file uploads use backend proxying or direct-to-storage sessions first?
  • Which nested resources should support include expansion?
  • Should knowledge search use REST, GraphQL, or a specialized search endpoint?
  • Which API responses may contain AI confidence values?
  • Which internal prompt metadata is safe to expose to administrators?
  • Which audit-event fields should be redacted?
  • Should the API support users belonging to multiple active organizations simultaneously?
  • Which endpoints require stricter rate limits?
  • Should OpenAPI clients be generated during CI?

These questions should remain documented until implementation decisions are approved.


Google AI Studio API Planning Prompt

Use this prompt before generating the formal specification.

You are helping design the REST API and application contracts for BidRadar.
BidRadar is a secure, multi-tenant AI Tender Intelligence and Proposal Automation SaaS platform for IT service providers.
Do not generate FastAPI code.
Do not generate React code.
Do not generate Pydantic models.
Do not generate SQLAlchemy models.
Read these documents if available:
- docs/project-vision.md
- docs/product-requirements.md
- docs/architecture.md
- docs/database-schema.md
- docs/google-ai-studio-workflow.md
Your task is to plan the REST API specification.
Provide:
1. API design principles.
2. Base URL and versioning strategy.
3. Authentication contracts.
4. Organization-context strategy.
5. Authorization behavior.
6. JSON naming conventions.
7. Identifier, date, timestamp, and monetary formats.
8. Standard single-resource responses.
9. Collection and pagination contracts.
10. Filtering, sorting, and search conventions.
11. Error-response format.
12. Validation-error format.
13. Request-correlation strategy.
14. Idempotency rules.
15. Optimistic-concurrency rules.
16. Background-job contracts.
17. File-upload and download contracts.
18. Organization endpoints.
19. Opportunity endpoints.
20. Tender-document endpoints.
21. Requirement endpoints.
22. Tender-analysis endpoints.
23. Scoring and Bid/No-Bid endpoints.
24. Knowledge-document endpoints.
25. Semantic-search endpoint.
26. Proposal endpoints.
27. Proposal-section versioning endpoints.
28. Comment and review endpoints.
29. Compliance endpoints.
30. Workflow and task endpoints.
31. Approval endpoints.
32. Notification endpoints.
33. Export endpoints.
34. AI execution and feedback boundaries.
35. Usage endpoints.
36. Audit endpoints.
37. Health and readiness endpoints.
38. Rate-limit behavior.
39. Security requirements.
40. OpenAPI and contract-testing strategy.
41. MVP endpoint set.
42. Deferred endpoints.
43. Risks.
44. Open questions.
Constraints:
- Use resource-oriented REST.
- Use /api/v1.
- Use JSON over HTTPS.
- Keep tenant context explicit and verified.
- Do not trust organization_id from request bodies.
- Long-running operations must return 202 and a job resource.
- Use stable machine-readable error codes.
- Use explicit business-action endpoints for approvals and state transitions.
- Use optimistic concurrency for collaborative and versioned resources.
- Keep Gemini prompts and secrets server-side.
- Do not expose SQLAlchemy models directly.
- Do not generate code.

Google AI Studio API Specification Prompt

After reviewing the plan, use:

Create the formal BidRadar REST API and Application Contracts document.
Write the result as Markdown suitable for:
docs/api-specification.md
Read and follow:
- docs/project-vision.md
- docs/product-requirements.md
- docs/architecture.md
- docs/database-schema.md
- docs/google-ai-studio-workflow.md
Include:
1. Document control
2. Purpose and scope
3. API design principles
4. Base URLs
5. API versioning
6. Content types
7. Naming conventions
8. UUID format
9. Date and timestamp format
10. Monetary-value format
11. Authentication endpoints
12. Session and token contracts
13. Current-user contract
14. Organization-context strategy
15. Organization and membership endpoints
16. Authorization response behavior
17. Standard resource metadata
18. Collection responses
19. Offset pagination
20. Cursor pagination
21. Filtering
22. Sorting
23. Free-text search
24. Expansion rules
25. Standard success responses
26. Standard error responses
27. Validation-error responses
28. HTTP status-code usage
29. Request and correlation IDs
30. Idempotency
31. Optimistic concurrency
32. Soft deletion and archive actions
33. Background-job contracts
34. Job cancellation
35. File-upload contracts
36. File-download authorization
37. Opportunity endpoints
38. Tender-document endpoints
39. Document-extraction endpoints
40. Requirement endpoints
41. Tender-analysis endpoints
42. Opportunity-scoring endpoints
43. Human Bid/No-Bid endpoints
44. Knowledge-document endpoints
45. Knowledge-version approval
46. Semantic and hybrid-search endpoints
47. Proposal endpoints
48. Proposal-outline generation
49. Proposal-section generation and versioning
50. Section approval and locking
51. Comments and reviews
52. Compliance endpoints
53. Workflow-template endpoints
54. Workflow and task endpoints
55. Approval endpoints
56. Notification endpoints
57. Export endpoints
58. AI execution metadata
59. AI feedback
60. Usage reporting
61. Audit access
62. Health, readiness, and version endpoints
63. Rate limiting
64. Security requirements
65. Prompt-injection boundaries
66. OpenAPI documentation
67. Generated TypeScript client strategy
68. Contract testing
69. Mock API requirements
70. API evolution and deprecation
71. MVP endpoint scope
72. Deferred endpoint scope
73. Risks and mitigations
74. Open questions
For every major endpoint:
- State the HTTP method.
- State the route.
- Explain the purpose.
- Describe required permission.
- Describe important request fields.
- Describe important response fields.
- List likely error responses.
- State whether the operation is synchronous or asynchronous.
Constraints:
- Use /api/v1.
- Use snake_case JSON.
- Use UUID identifiers.
- Use ISO 8601 timestamps.
- Use decimal-safe monetary contracts with explicit currency.
- Use tenant-aware authorization.
- Derive organization ownership server-side.
- Use 202 Accepted for long-running operations.
- Return durable job resources.
- Use explicit approval and lifecycle action endpoints.
- Use versioned proposal and requirement contracts.
- Preserve AI evidence and citations.
- Keep provider secrets and hidden prompts server-side.
- Do not generate code.
- Do not redefine the database schema.

API Review Prompt

After generating the specification, use:

Review the BidRadar REST API and Application Contracts document.
Do not rewrite it yet.
Do not generate code.
Evaluate:
1. Alignment with the Product Requirements Document.
2. Alignment with the architecture.
3. Alignment with the database schema.
4. Inconsistent naming.
5. Missing tenant context.
6. Unsafe organization_id handling.
7. Missing authorization requirements.
8. Missing error contracts.
9. Inconsistent pagination.
10. Unbounded search or list endpoints.
11. Long-running synchronous operations.
12. Missing durable job resources.
13. Missing idempotency.
14. Missing optimistic concurrency.
15. Unsafe generic status updates.
16. Missing explicit approval actions.
17. Missing proposal versioning.
18. Missing requirement versioning.
19. Missing file validation.
20. Missing AI traceability.
21. Exposure of secrets or hidden prompts.
22. Missing rate limits.
23. Missing audit boundaries.
24. Missing OpenAPI or contract testing.
25. Endpoints that should be deferred.
26. Contradictory request or response fields.
27. Open questions treated as final decisions.
Classify each finding as:
- Critical
- High
- Medium
- Low
For every finding:
- Identify the endpoint or section.
- Explain the risk.
- Recommend a specific correction.

Manual API Review Checklist

Consistency

  • Does every endpoint use the same naming convention?
  • Are dates and money represented consistently?
  • Are collection responses standardized?
  • Are error responses standardized?

Security

  • Is organization context verified?
  • Can clients set protected ownership fields?
  • Are authorization requirements documented?
  • Are file downloads protected?
  • Are AI secrets hidden?

Asynchronous Work

  • Do long operations return 202 Accepted?
  • Are job resources durable?
  • Can users inspect failures?
  • Are retries and cancellation considered?

Versioning

  • Are proposal sections versioned?
  • Are requirements versioned?
  • Is concurrency protected?
  • Are approvals tied to exact versions?

AI

  • Are AI operations requested through domain endpoints?
  • Is prompt metadata controlled?
  • Are citations preserved?
  • Are usage and feedback supported?

Frontend

  • Can TypeScript types be generated?
  • Can TanStack Query hooks map cleanly to resources?
  • Can mock data follow the same contracts?
  • Are loading and error states supported?

Validation Checklist

Before continuing to Part 7, verify that:

  • docs/api-specification.md exists.
  • Document version and status are included.
  • /api/v1 is defined.
  • JSON naming conventions are defined.
  • UUID contracts are defined.
  • Date and timestamp formats are defined.
  • Monetary-value formats are defined.
  • Authentication contracts are documented.
  • Organization context is explicit.
  • Membership validation is mandatory.
  • Authorization behavior is documented.
  • Standard resource metadata is defined.
  • Pagination is defined.
  • Filtering is defined.
  • Sorting is defined.
  • Search is defined.
  • Error responses are standardized.
  • Validation errors are standardized.
  • HTTP status codes are documented.
  • Request IDs are included.
  • Idempotency is documented.
  • Optimistic concurrency is documented.
  • Long-running operations use job resources.
  • Job statuses are defined.
  • File-upload contracts are documented.
  • File-download authorization is documented.
  • Opportunity endpoints are documented.
  • Tender-document endpoints are documented.
  • Requirement endpoints are documented.
  • Analysis endpoints are documented.
  • Scoring endpoints are documented.
  • Human Bid/No-Bid endpoints are documented.
  • Knowledge endpoints are documented.
  • Semantic-search contracts are documented.
  • Proposal endpoints are documented.
  • Proposal-section versioning is documented.
  • Approval endpoints are explicit.
  • Compliance endpoints are documented.
  • Workflow and task endpoints are documented.
  • Export endpoints are documented.
  • AI execution exposure is limited.
  • Usage endpoints are access-controlled.
  • Audit endpoints are restricted.
  • Health and readiness endpoints are documented.
  • Rate limits are acknowledged.
  • OpenAPI generation is planned.
  • Contract testing is planned.
  • MVP endpoints are separated from deferred endpoints.
  • No FastAPI code has been generated.
  • No React API client has been generated.
  • No Pydantic schemas have been generated.

Definition of Done

Part 6 is complete when:

  • The frontend and backend can be generated against one stable contract.
  • Tenant context is unambiguous.
  • Business actions are explicit.
  • Long-running work uses asynchronous contracts.
  • Error handling is predictable.
  • Collaborative updates are concurrency-safe.
  • File and AI operations are secure.
  • Proposal and requirement history is preserved.
  • The API supports the complete MVP workflow.
  • The OpenAPI document can later generate frontend types.
  • The team approves the specification as the basis for implementation.

Recommended Git Commit

docs(api): define BidRadar REST API and application contracts

A later correction may use:

docs(api): strengthen tenant context and asynchronous job contracts

What We Built

In this article, we designed the complete application contract for BidRadar.

The specification now defines:

  • API versioning
  • Authentication
  • Organization context
  • Authorization
  • Resource naming
  • JSON formats
  • Pagination
  • Filtering
  • Sorting
  • Search
  • Errors
  • Request IDs
  • Idempotency
  • Concurrency
  • Background jobs
  • File upload and download
  • Opportunities
  • Tender documents
  • Requirements
  • Tender analyses
  • Opportunity scoring
  • Human Bid/No-Bid decisions
  • Knowledge management
  • Semantic search
  • Proposal generation
  • Proposal versioning
  • Collaboration
  • Compliance
  • Workflows
  • Tasks
  • Approvals
  • Notifications
  • Exports
  • AI usage
  • Audit access
  • Health endpoints
  • Rate limits
  • OpenAPI and contract testing

No backend or frontend code has been generated yet.

The product requirements, architecture, database schema, and API contracts now form a coherent technical foundation.


Next Article

Part 7 — Establishing the BidRadar Design System and User Experience

In the next article, we will define how BidRadar should look and behave before Google AI Studio generates the initial application.

We will establish:

  • Brand identity
  • BidRadar colors
  • Typography
  • Spacing
  • Layout
  • Navigation
  • Dashboard structure
  • Cards
  • Tables
  • Forms
  • Status badges
  • Charts
  • Empty states
  • Loading states
  • Error states
  • Responsive design
  • Accessibility
  • Interaction patterns
  • Proposal-editor layout
  • Tender-analysis workspace
  • Knowledge-search experience
  • Workflow dashboard
  • Administrative interfaces

We will create:

docs/
└── design-system.md

This document will ensure that Google AI Studio generates one coherent enterprise SaaS application rather than a collection of unrelated screens.

Building BidRadar with Google AI Studio: Part 12 — Designing the Core Database Models

BidRadar Development Progress Current phase: Core Domain ImplementationCurrent milestone: Implement the multi-tenant identity and organization data modelPrevious article: Part 11 — Configuring PostgreSQL, SQLAlchemy, and AlembicNext article: Part 13 — Creating the Initial Core Database MigrationPrimary deliverables: Core SQLAlchemy models, relationships, constraints, and model testsApplication functionality added: Persistent organization, user, membership, role, invitation, and audit…

Building BidRadar with Google AI Studio: Part 11 — Configuring PostgreSQL, SQLAlchemy, and Alembic

BidRadar Development Progress Current phase: Backend Infrastructure Current milestone: Configure the database foundation Previous article: Part 10 — Creating the FastAPI Backend Foundation Next article: Part 12 — Designing the Core Database Models Primary deliverables Application functionality added: Database infrastructure only Introduction A modern SaaS platform is only as reliable as its data layer. BidRadar…

Building BidRadar with Google AI Studio: Part 10 — Creating the FastAPI Backend Foundation

BidRadar Development Progress Current phase: Backend FoundationCurrent milestone: Create the production-ready FastAPI application structurePrevious article: Part 9 — Setting Up the BidRadar Monorepo and Development EnvironmentNext article: Part 11 — Configuring PostgreSQL, SQLAlchemy, and AlembicPrimary deliverable: A modular FastAPI backend that starts successfully and exposes operational endpointsApplication functionality added: Backend foundation only Introduction In Part…

Building BidRadar with Google AI Studio: Part 9 — Setting Up the BidRadar Monorepo and Development Environment

BidRadar Development Progress Current phase: Implementation Foundations Current milestone: Create the BidRadar development environment Previous article: Part 8 — Writing the BidRadar Master Build Prompt Next article: Part 10 — Creating the FastAPI Backend Foundation Primary deliverables: Application code generated: Project foundation only Introduction After eight planning articles, we are finally ready to start building…

Designed with WordPress

Discover more from Learn Pydantic AI

Subscribe now to keep reading and get access to the full archive.

Continue reading