Skip to main content

Overview

The Prompts Management API provides CRUD operations for managing AI prompts used throughout the Alliance IGAD Innovation Hub platform. Prompts control how AI models generate content for proposals, newsletters, and other features. Base URL: /api/admin/prompts Authentication: All endpoints require admin authentication via JWT Bearer token.

Prompt Schema

Prompts follow a structured schema with the following key fields:
FieldTypeDescription
idstringUnique prompt identifier (UUID)
namestringDisplay name for the prompt (1-200 chars)
sectionenumMain section (e.g., proposal_writer, newsletter_generator)
sub_sectionstringSub-section identifier (e.g., step-1, step-2)
routestringOptional route identifier for organizing prompts
categoriesstring[]Categories where this prompt applies
tagsstring[]Tags for filtering and organization
system_promptstringSystem-level instructions for the AI model
user_prompt_templatestringUser-facing prompt template with placeholders
versionintegerVersion number (starts at 1)
is_activebooleanWhether the prompt is active and available for use
tonestringDesired output tone (e.g., “Professional and informative”)
output_formatstringExpected output format description
created_bystringEmail of user who created the prompt
updated_bystringEmail of user who last updated the prompt
created_atdatetimeISO 8601 timestamp
updated_atdatetimeISO 8601 timestamp
comments_countintegerNumber of comments on this prompt

Prompt Sections

Available sections (from ProposalSection enum):
  • proposal_writer - Main proposal generation feature
  • newsletter_generator - Newsletter generation feature
  • Legacy sections: problem_statement, objectives, methodology, budget, etc.

Template Placeholders

Prompt templates support two placeholder formats:
  1. Double curly braces: {{VARIABLE_NAME}}
  2. Curly + square brackets: {[VARIABLE_NAME]}
Both formats are automatically replaced at runtime with actual values.

Endpoints

List Prompts

GET /api/admin/prompts/list
List prompts with filtering and pagination. Query Parameters:
ParameterTypeDescription
sectionProposalSectionFilter by section
sub_sectionstringFilter by sub-section
tagstringFilter by tag
searchstringSearch in name, prompts, route, and tags
routestringFilter by route
is_activebooleanFilter by active status
limitintegerResults per page (1-100, default: 20)
offsetintegerPagination offset (default: 0)
Response:
{
  "prompts": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "RFP Analysis Prompt",
      "section": "proposal_writer",
      "sub_section": "step-1",
      "categories": ["RFP Analysis"],
      "tags": ["analysis", "rfp"],
      "system_prompt": "You are an expert at analyzing RFPs...",
      "user_prompt_template": "Analyze the following RFP: {{rfp_text}}",
      "version": 1,
      "is_active": true,
      "created_by": "[email protected]",
      "updated_by": "[email protected]",
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:30:00Z",
      "comments_count": 3
    }
  ],
  "total": 42,
  "has_more": true
}

Get Prompt

GET /api/admin/prompts/{prompt_id}
Get a specific prompt by ID and optional version. Path Parameters:
  • prompt_id (string, required) - Prompt UUID
Query Parameters:
  • version (string, optional) - Version number or “latest” (default: latest)
Response:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "RFP Analysis Prompt",
  "section": "proposal_writer",
  "sub_section": "step-1",
  "categories": ["RFP Analysis"],
  "tags": ["analysis", "rfp"],
  "system_prompt": "You are an expert at analyzing RFPs...",
  "user_prompt_template": "Analyze the following RFP: {{rfp_text}}",
  "version": 1,
  "is_active": true,
  "tone": "Professional and analytical",
  "output_format": "Structured JSON with key findings",
  "created_by": "[email protected]",
  "updated_by": "[email protected]",
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z",
  "comments_count": 3
}
Error Responses:
  • 404 - Prompt not found
  • 400 - Invalid version format

Create Prompt

POST /api/admin/prompts/create
Create a new prompt. New prompts are active by default (version 1). Request Body:
{
  "name": "Concept Evaluation Prompt",
  "section": "proposal_writer",
  "sub_section": "step-2",
  "route": "/analyze-concept",
  "categories": ["Concept Analysis", "Feasibility"],
  "tags": ["concept", "evaluation"],
  "system_prompt": "You are an expert at evaluating project concepts for feasibility and alignment with organizational goals.",
  "user_prompt_template": "Evaluate this concept: {{concept_text}}\n\nOrganization focus: {{organization_focus}}",
  "tone": "Professional and constructive",
  "output_format": "Detailed evaluation with scores and recommendations"
}
Response: 201 Created
{
  "id": "660e8400-e29b-41d4-a716-446655440001",
  "name": "Concept Evaluation Prompt",
  "section": "proposal_writer",
  "sub_section": "step-2",
  "version": 1,
  "is_active": true,
  "created_by": "[email protected]",
  "created_at": "2024-01-16T14:20:00Z",
  "updated_at": "2024-01-16T14:20:00Z"
}
Error Responses:
  • 400 - Validation error or duplicate active prompt for same section/route/subsection/categories
  • 401 - Unauthorized (invalid or missing token)
Active Prompt Uniqueness: Only one prompt can be active for a unique combination of:
  • section
  • route
  • sub_section
  • categories (as a set)
Creating a new active prompt with the same combination will fail with a 400 error.

Update Prompt

PUT /api/admin/prompts/{prompt_id}/update
Update an existing prompt. All fields are optional. Path Parameters:
  • prompt_id (string, required) - Prompt UUID
Request Body:
{
  "system_prompt": "Updated system instructions...",
  "user_prompt_template": "Updated template: {{variable}}",
  "tags": ["updated", "v2"],
  "change_comment": "Improved clarity and added new variable"
}
Response:
{
  "id": "660e8400-e29b-41d4-a716-446655440001",
  "version": 1,
  "is_active": true,
  "updated_by": "[email protected]",
  "updated_at": "2024-01-16T15:45:00Z"
}
Error Responses:
  • 404 - Prompt not found
  • 400 - Validation error or duplicate active prompt conflict

Delete Prompt

DELETE /api/admin/prompts/{prompt_id}
Delete a specific version or all versions of a prompt. Path Parameters:
  • prompt_id (string, required) - Prompt UUID
Query Parameters:
  • version (integer, optional) - Specific version to delete. If omitted, deletes all versions.
Response:
{
  "message": "Prompt deleted successfully"
}
Error Responses:
  • 404 - Prompt not found
  • 500 - Deletion failed

Toggle Active Status

POST /api/admin/prompts/{prompt_id}/toggle-active
Toggle a prompt’s active status (active ↔ inactive). Path Parameters:
  • prompt_id (string, required) - Prompt UUID
Response:
{
  "id": "660e8400-e29b-41d4-a716-446655440001",
  "is_active": false,
  "updated_at": "2024-01-16T16:00:00Z"
}
Error Responses:
  • 404 - Prompt not found
  • 400 - Cannot activate due to conflict with another active prompt
Note: When activating a prompt, the system checks for conflicts with other active prompts that have the same section/route/subsection/categories combination.

Version Control

Prompts use a simple versioning system:
  1. Creation: New prompts start at version 1
  2. Updates: Updates modify the existing version in-place (not creating new versions)
  3. History: All changes are tracked in the change history

Change History

GET /api/admin/prompts/{prompt_id}/history
Get the complete change history for a prompt. Response:
{
  "prompt_id": "660e8400-e29b-41d4-a716-446655440001",
  "changes": [
    {
      "id": "change-123",
      "prompt_id": "660e8400-e29b-41d4-a716-446655440001",
      "version": 1,
      "change_type": "update",
      "changes": {
        "system_prompt": {
          "old": "Original instructions...",
          "new": "Updated instructions..."
        }
      },
      "comment": "Improved clarity",
      "author": "[email protected]",
      "author_name": "[email protected]",
      "created_at": "2024-01-16T15:45:00Z"
    },
    {
      "id": "change-122",
      "prompt_id": "660e8400-e29b-41d4-a716-446655440001",
      "version": 1,
      "change_type": "create",
      "changes": {},
      "comment": "Initial prompt creation",
      "author": "[email protected]",
      "author_name": "[email protected]",
      "created_at": "2024-01-16T14:20:00Z"
    }
  ],
  "total": 2
}
Change Types:
  • create - Initial prompt creation
  • update - Content or metadata update
  • activate - Prompt activated
  • deactivate - Prompt deactivated

Comments

Add Comment

POST /api/admin/prompts/{prompt_id}/comments
Add a comment to a prompt (supports threaded replies). Request Body:
{
  "content": "This prompt works well but could use more examples",
  "parent_id": null
}
Response:
{
  "id": "comment-456",
  "prompt_id": "660e8400-e29b-41d4-a716-446655440001",
  "parent_id": null,
  "content": "This prompt works well but could use more examples",
  "author": "[email protected]",
  "author_name": "[email protected]",
  "created_at": "2024-01-16T16:30:00Z",
  "replies": []
}

Get Comments

GET /api/admin/prompts/{prompt_id}/comments
Get all comments for a prompt, organized as threads. Response:
[
  {
    "id": "comment-456",
    "prompt_id": "660e8400-e29b-41d4-a716-446655440001",
    "content": "This prompt works well but could use more examples",
    "author": "[email protected]",
    "author_name": "[email protected]",
    "created_at": "2024-01-16T16:30:00Z",
    "replies": [
      {
        "id": "comment-457",
        "parent_id": "comment-456",
        "content": "Agreed, I'll add some examples",
        "author": "[email protected]",
        "author_name": "[email protected]",
        "created_at": "2024-01-16T16:35:00Z",
        "replies": []
      }
    ]
  }
]

Preview Prompt

POST /api/admin/prompts/preview
Test a prompt against the AI model without saving it. Request Body:
{
  "system_prompt": "You are an expert analyst.",
  "user_prompt_template": "Analyze: {{text}}",
  "variables": {
    "text": "Sample text to analyze"
  }
}
Response:
{
  "output": "Here is the analysis...",
  "tokens_used": 450,
  "processing_time": 2.3
}

Authentication

All admin endpoints require authentication:
Authorization: Bearer <jwt_token>
The JWT token must belong to a user with admin privileges (is_admin: true). Tokens are obtained through the authentication endpoints. Error Responses:
  • 401 Unauthorized - Missing or invalid token
  • 403 Forbidden - Valid token but insufficient privileges (not an admin)

Error Handling

All endpoints follow consistent error response format:
{
  "detail": "Error description"
}
Common HTTP Status Codes:
  • 200 OK - Successful GET/PUT request
  • 201 Created - Successful POST (creation)
  • 400 Bad Request - Validation error or business logic violation
  • 401 Unauthorized - Authentication required or failed
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Resource not found
  • 500 Internal Server Error - Server-side error

Rate Limiting

No rate limiting is currently enforced on admin endpoints, but it is recommended to implement reasonable request frequencies to avoid overwhelming the system.

Best Practices

  1. Prompt Naming: Use clear, descriptive names that indicate the prompt’s purpose
  2. Versioning: Use the change_comment field when updating prompts to document changes
  3. Testing: Always use the preview endpoint to test prompts before activating them
  4. Active Status: Only one prompt should be active per section/route/subsection/categories combination
  5. Categories: Use consistent category names across related prompts
  6. Placeholders: Document required variables in the prompt name or comments
  7. History: Review change history before making significant updates

Build docs developers (and LLMs) love