Skip to main content
POST
/
api
/
proposals
/
{proposal_id}
/
generate-concept-document
Generate Concept Document
curl --request POST \
  --url https://api.example.com/api/proposals/{proposal_id}/generate-concept-document \
  --header 'Content-Type: application/json' \
  --data '
{
  "concept_evaluation": {
    "concept_analysis": {},
    "status": "<string>"
  }
}
'
{
  "status": "<string>",
  "message": "<string>",
  "started_at": "<string>",
  "completed_at": "<string>",
  "concept_document": "<string>",
  "error": "<string>"
}

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AllianceBioversityCIAT/alliance-IGAD/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Generates an enhanced concept document based on RFP analysis and user’s concept evaluation. This endpoint takes the sections identified in concept analysis and creates a comprehensive, AI-enhanced version of the concept document.
Prerequisites:
  • RFP analysis must be completed
  • Concept analysis must be completed
  • User must have selected/evaluated sections (via /concept-evaluation endpoint)

Workflow Pattern

Follows the asynchronous Lambda worker pattern:
  1. Trigger: POST to /generate-concept-document starts generation
  2. Validation: Backend validates required data exists in DynamoDB
  3. Lambda Worker: Invokes worker with analysis_type: "concept_document"
  4. Polling: Poll GET /concept-document-status for completion
  5. Result: Returns enhanced concept document in markdown format

Request

proposal_id
string
required
The proposal ID or code (format: PROP-YYYYMMDD-XXXX)
concept_evaluation
object
required
User’s evaluation of concept analysis sections. This is typically populated by the frontend after the user reviews the concept analysis.
Important: The backend uses the concept_analysis data stored in DynamoDB (which includes user selections from the /concept-evaluation endpoint), NOT the concept_evaluation parameter. The parameter acts as a trigger, but the source of truth is DynamoDB.

Response

status
string
  • processing: Document generation started
message
string
Instruction to poll the status endpoint

Example Request

curl -X POST "https://api.igad-innovation.org/api/proposals/PROP-20260304-A1B2/generate-concept-document" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "concept_evaluation": {
      "concept_analysis": {
        "sections_needing_elaboration": [
          {
            "title": "Technical Architecture",
            "selected": true
          }
        ]
      },
      "status": "completed"
    }
  }'

Example Response

{
  "status": "processing",
  "message": "Concept document generation started. Poll /concept-document-status for updates."
}

User Selection Workflow

Before generating the concept document, users should review and select sections:

Step 1: Update Concept Evaluation

// Save user's section selections
const response = await fetch(
  `/api/proposals/${proposalId}/concept-evaluation`,
  {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      selected_sections: [
        { title: 'Technical Architecture', selected: true },
        { title: 'Methodology', selected: true },
        { title: 'Risk Management', selected: false }
      ],
      user_comments: {
        'Technical Architecture': 'Please emphasize scalability'
      }
    })
  }
)

Step 2: Generate Document

// Trigger document generation
const response = await fetch(
  `/api/proposals/${proposalId}/generate-concept-document`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      concept_evaluation: { status: 'completed' }
    })
  }
)

Step 3: Poll Status

const pollStatus = async () => {
  const interval = setInterval(async () => {
    const response = await fetch(
      `/api/proposals/${proposalId}/concept-document-status`,
      { headers: { Authorization: `Bearer ${token}` } }
    )
    const data = await response.json()

    if (data.status === 'completed') {
      clearInterval(interval)
      displayConceptDocument(data.concept_document)
    }
  }, 3000)
}

Lambda Worker Details

Environment Variables

worker_function = os.getenv("WORKER_FUNCTION_NAME")

Lambda Invocation Payload

payload = {
    "analysis_type": "concept_document",
    "proposal_id": proposal_code,  # PROP-YYYYMMDD-XXXX format
    "user_id": user_id,
    "concept_evaluation": final_concept_evaluation  # From DynamoDB with selections
}

lambda_client.invoke(
    FunctionName=worker_function,
    InvocationType="Event",  # Asynchronous
    Payload=json.dumps(payload)
)

DynamoDB Updates

Before invocation:
await db_client.update_item(
    pk=proposal["PK"],
    sk=proposal["SK"],
    update_expression="SET concept_document_status = :status, concept_document_started_at = :started",
    expression_attribute_values={
        ":status": "processing",
        ":started": datetime.utcnow().isoformat()
    }
)
After completion (in worker):
db_client.update_item_sync(
    pk=pk,
    sk="METADATA",
    update_expression="SET concept_document_status = :status, concept_document_v2 = :doc, concept_document_completed_at = :completed",
    expression_attribute_values={
        ":status": "completed",
        ":doc": generated_document,
        ":completed": datetime.utcnow().isoformat()
    }
)

Status Values

The concept_document_status field tracks generation progress:
StatusDescription
not_startedNo generation triggered
processingLambda worker is generating document
completedDocument generated successfully
failedGeneration encountered an error

Polling for Status

GET /api/proposals/{proposal_id}/concept-document-status

Check concept document generation status

Error Handling

Status Code 400 - Missing RFP Analysis

{
  "detail": "RFP analysis not found. Complete Step 1 first."
}

Status Code 400 - Missing Concept Analysis

{
  "detail": "Concept analysis not found. Complete Step 1 first."
}

Status Code 400 - Missing Proposal Code

{
  "detail": "Proposal code not found"
}

Status Code 404

{
  "detail": "Proposal not found"
}

Status Code 500

{
  "detail": "Worker lambda invocation failed"
}

GET Concept Document Status

Description

Poll this endpoint to check concept document generation status.

Request

proposal_id
string
required
The proposal ID or code

Response

status
string
Current status: not_started, processing, completed, or failed
started_at
string
ISO timestamp when generation started
completed_at
string
ISO timestamp when generation completed
concept_document
string
Generated concept document in markdown format (only when completed)
error
string
Error message (only when failed)

Example Response (Completed)

{
  "status": "completed",
  "started_at": "2026-03-04T10:40:00.000Z",
  "completed_at": "2026-03-04T10:42:15.000Z",
  "concept_document": "# Enhanced Concept Document\n\n## Executive Summary\n\nThis proposal aims to develop a comprehensive digital platform...\n\n## Technical Architecture\n\n### System Design\n\nThe platform will be built using a microservices architecture...\n\n### Scalability Considerations\n\nTo handle expected growth...\n\n## Methodology\n\n### Development Approach\n\nWe will employ Agile methodology with 2-week sprints..."
}

Example Response (Processing)

{
  "status": "processing",
  "started_at": "2026-03-04T10:40:00.000Z",
  "completed_at": null
}

Example Response (Failed)

{
  "status": "failed",
  "started_at": "2026-03-04T10:40:00.000Z",
  "error": "AI service temporarily unavailable"
}

Document Format

The generated concept document is returned as markdown with:
  • Hierarchical structure: Using #, ##, ### headers
  • Enhanced content: AI-generated elaborations for selected sections
  • Formatted lists: Bullet points and numbered lists where appropriate
  • Professional tone: Suitable for submission to funding organizations

Example Document Structure

# Enhanced Concept Document

## Executive Summary
[AI-generated summary]

## Problem Statement
[Elaborated problem context]

## Proposed Solution

### Technical Architecture
[Detailed technical description]

### Implementation Methodology
[Step-by-step approach]

## Expected Outcomes
[Measurable deliverables]

## Budget Overview
[Cost breakdown]

## Timeline
[Project schedule]

Next Steps

After the concept document is generated:
  1. User reviews the enhanced document
  2. User can download or export the document
  3. Proceed to structure and workplan analysis (Step 3)

POST /api/proposals/{proposal_id}/analyze-step-3

Generate proposal structure and workplan

Best Practices

Optimize generation time: Only select sections that truly need elaboration. Unselected sections will be excluded from AI processing, reducing generation time and cost.
Save user selections first: Always call PUT /concept-evaluation before generating the document to ensure user preferences are stored in DynamoDB.
Don’t retry immediately on failure: If status returns "failed", wait at least 30 seconds before retrying to avoid overwhelming the worker Lambda.

Build docs developers (and LLMs) love