Skip to main content
PUT
/
api
/
proposals
/
{proposal_id}
Update Proposal
curl --request PUT \
  --url https://api.example.com/api/proposals/{proposal_id} \
  --header 'Content-Type: application/json' \
  --data '
{
  "title": "<string>",
  "description": "<string>",
  "status": "<string>",
  "uploaded_files": {},
  "text_inputs": {},
  "metadata": {}
}
'
{
  "id": "<string>",
  "proposalCode": "<string>",
  "title": "<string>",
  "description": "<string>",
  "status": "<string>",
  "created_at": "<string>",
  "updated_at": "<string>",
  "user_id": "<string>",
  "user_email": "<string>",
  "user_name": "<string>",
  "uploaded_files": {},
  "text_inputs": {},
  "metadata": {},
  "404 Not Found": {},
  "403 Forbidden": {}
}

Authentication

This endpoint requires authentication via Bearer token.
Authorization: Bearer <token>

Path Parameters

proposal_id
string
required
The proposal identifier. Can be either:
  • UUID format: a1b2c3d4-e5f6-7890-abcd-ef1234567890
  • Proposal code format: PROP-20260304-A1B2

Request Body

All fields are optional. Only provide the fields you want to update.
title
string
New title for the proposal.
description
string
New description for the proposal.
status
string
New status for the proposal (e.g., “draft”, “submitted”, “completed”).
uploaded_files
object
Dictionary of uploaded files organized by category.Common categories:
  • rfp-document: Array of RFP document URLs
  • concept-document: Array of concept document URLs
  • reference-proposals: Array of reference proposal URLs
Example:
{
  "rfp-document": ["s3://bucket/proposal/rfp.pdf"],
  "reference-proposals": ["s3://bucket/proposal/ref1.pdf", "s3://bucket/proposal/ref2.pdf"]
}
text_inputs
object
Dictionary of text inputs provided by the user.Common keys:
  • initial-concept: User’s initial concept text
Example:
{
  "initial-concept": "This project aims to improve climate resilience..."
}
metadata
object
Additional metadata for the proposal. This can include custom fields, analysis results, or processing flags.Example:
{
  "custom_field": "value",
  "processing_notes": "Additional information"
}

Response

Returns the updated proposal object with all current fields.
id
string
Unique proposal identifier (UUID).
proposalCode
string
Human-readable proposal code (format: PROP-YYYYMMDD-XXXX).
title
string
The updated title of the proposal.
description
string
The updated description of the proposal.
status
string
The updated status of the proposal.
created_at
string
ISO 8601 timestamp of when the proposal was created (unchanged).
updated_at
string
ISO 8601 timestamp of the update (automatically set to current time).
user_id
string
The ID of the user who owns the proposal.
user_email
string
The email of the user who owns the proposal.
user_name
string
The name of the user who owns the proposal.
uploaded_files
object
The updated dictionary of uploaded files.
text_inputs
object
The updated dictionary of text inputs.
metadata
object
The updated metadata object.

Example Requests

curl -X PUT https://api.igadregion.org/api/proposals/PROP-20260304-A1B2 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Updated Climate Resilience Project",
    "description": "Enhanced proposal for climate adaptation with new focus areas"
  }'

Response Example

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "proposalCode": "PROP-20260304-A1B2",
  "title": "Updated Climate Resilience Project",
  "description": "Enhanced proposal for climate adaptation with new focus areas",
  "template_id": null,
  "status": "draft",
  "created_at": "2026-03-04T10:30:00.000Z",
  "updated_at": "2026-03-04T16:20:00.000Z",
  "user_id": "user_123",
  "user_email": "[email protected]",
  "user_name": "John Doe",
  "uploaded_files": {
    "rfp-document": ["s3://bucket/PROP-20260304-A1B2/rfp.pdf"],
    "concept-document": ["s3://bucket/PROP-20260304-A1B2/concept.pdf"]
  },
  "text_inputs": {
    "initial-concept": "Brief description of the project concept..."
  },
  "metadata": {
    "rfp_analysis_status": "completed",
    "concept_analysis_status": "processing"
  }
}

Error Responses

404 Not Found
error
{
  "detail": "Proposal not found"
}
The proposal with the specified ID does not exist.
403 Forbidden
error
{
  "detail": "Access denied"
}
The proposal belongs to a different user.

Notes

  • Partial Updates: You only need to include the fields you want to update. All other fields will remain unchanged.
  • Automatic Timestamp: The updated_at field is automatically set to the current timestamp on every update.
  • Access Control: Users can only update their own proposals.
  • Flexible ID Format: You can use either the UUID or the proposal code (PROP-YYYYMMDD-XXXX) to identify the proposal.
  • Empty Update: If you send an empty request body or only fields that are not set, the endpoint returns the current proposal without making changes.
  • Metadata Merging: The metadata field is replaced entirely with the new value provided, not merged. To preserve existing metadata, retrieve it first and include all fields in your update.

Build docs developers (and LLMs) love