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>"
}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.
/concept-evaluation endpoint)/generate-concept-document starts generationanalysis_type: "concept_document"/concept-document-status for completionPROP-YYYYMMDD-XXXX)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.processing: Document generation startedcurl -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"
}
}'
{
"status": "processing",
"message": "Concept document generation started. Poll /concept-document-status for updates."
}
// 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'
}
})
}
)
// 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' }
})
}
)
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)
}
worker_function = os.getenv("WORKER_FUNCTION_NAME")
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)
)
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()
}
)
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()
}
)
concept_document_status field tracks generation progress:
| Status | Description |
|---|---|
not_started | No generation triggered |
processing | Lambda worker is generating document |
completed | Document generated successfully |
failed | Generation encountered an error |
{
"detail": "RFP analysis not found. Complete Step 1 first."
}
{
"detail": "Concept analysis not found. Complete Step 1 first."
}
{
"detail": "Proposal code not found"
}
{
"detail": "Proposal not found"
}
{
"detail": "Worker lambda invocation failed"
}
not_started, processing, completed, or failed{
"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..."
}
{
"status": "processing",
"started_at": "2026-03-04T10:40:00.000Z",
"completed_at": null
}
{
"status": "failed",
"started_at": "2026-03-04T10:40:00.000Z",
"error": "AI service temporarily unavailable"
}
#, ##, ### headers# 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]
/concept-evaluation before generating the document to ensure user preferences are stored in DynamoDB."failed", wait at least 30 seconds before retrying to avoid overwhelming the worker Lambda.