Skip to main content

Delete RFP Document

proposal_id
string
required
Unique identifier for the proposal
filename
string
required
Name of the file to delete
success
boolean
Indicates if deletion was successful
message
string
Confirmation message
curl -X DELETE "https://api.igadinnovationhub.org/api/proposals/{proposal_id}/documents/{filename}" \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "success": true,
  "message": "Document deleted successfully"
}

What Gets Deleted

  1. S3 File: {proposal_code}/documents/rfp/{filename}
  2. DynamoDB Metadata:
    • Removes file from uploaded_files.rfp-document array
    • Clears RFP analysis data:
      • rfp_analysis
      • analysis_status_rfp
      • rfp_analysis_started_at
      • rfp_analysis_completed_at
      • rfp_analysis_error
  3. Updates: Sets updated_at timestamp
Deleting an RFP document also removes all associated analysis results. You’ll need to re-upload and re-analyze the RFP to restore this data.

Delete Concept Document

proposal_id
string
required
Unique identifier for the proposal
filename
string
required
Name of the concept file to delete
curl -X DELETE "https://api.igadinnovationhub.org/api/proposals/{proposal_id}/documents/concept/{filename}" \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "success": true,
  "message": "Concept file deleted successfully"
}

What Gets Deleted

  • S3 File: {proposal_code}/documents/initial_concept/{filename}
  • No vector cleanup needed (concept files are not vectorized)

Delete Concept Text

proposal_id
string
required
Unique identifier for the proposal
curl -X DELETE "https://api.igadinnovationhub.org/api/proposals/{proposal_id}/documents/concept-text" \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "success": true,
  "message": "Concept text deleted successfully"
}

What Gets Deleted

  • S3 File: {proposal_code}/documents/initial_concept/concept_text.txt
  • No DynamoDB update (text is stored in S3 only)

Delete Reference Proposal

proposal_id
string
required
Unique identifier for the proposal
filename
string
required
Name of the reference file to delete
success
boolean
Deletion success indicator
message
string
Confirmation message
curl -X DELETE "https://api.igadinnovationhub.org/api/proposals/{proposal_id}/documents/reference/{filename}" \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "success": true,
  "message": "Reference file deleted successfully"
}

What Gets Deleted

  1. S3 File: {proposal_code}/documents/references/{filename}
  2. Vector Embeddings:
    • Deletes all vectors from reference-proposals-index
    • Searches by document_name in vector keys
    • Key format: *|*|*|*|{filename}|*|*
  3. DynamoDB:
    • Removes filename from uploaded_files.reference-proposals array
    • Updates updated_at timestamp
Deleting a reference proposal removes all its vector embeddings. This affects AI retrieval for future proposal generation. Make sure you want to permanently remove this reference before deleting.

Vector Deletion Process

Deletion Flow
# 1. List all vectors in index
vectors = s3vectors.list_vectors(
    vectorBucketName=bucket,
    indexName="reference-proposals-index"
)

# 2. Filter by document_name (position 4 in key)
keys_to_delete = []
for vector in vectors:
    parts = vector['key'].split('|')
    if parts[4] == filename:  # document_name position
        keys_to_delete.append(vector['key'])

# 3. Delete matching vectors
s3vectors.delete_vectors(
    vectorBucketName=bucket,
    indexName="reference-proposals-index",
    keys=keys_to_delete
)

Delete Supporting Document

proposal_id
string
required
Unique identifier for the proposal
filename
string
required
Name of the supporting file to delete
success
boolean
Deletion success indicator
message
string
Confirmation message
curl -X DELETE "https://api.igadinnovationhub.org/api/proposals/{proposal_id}/documents/supporting/{filename}" \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "success": true,
  "message": "Supporting file and vectors deleted successfully"
}

What Gets Deleted

  1. S3 File: {proposal_code}/documents/supporting/{filename}
  2. Vector Embeddings:
    • Deletes all vectors from existing-work-index
    • Searches by document_name in vector keys
  3. DynamoDB:
    • Removes filename from uploaded_files.supporting-docs array
    • Updates updated_at timestamp

Delete Work Text

proposal_id
string
required
Unique identifier for the proposal
success
boolean
Deletion success indicator
message
string
Confirmation message
curl -X DELETE "https://api.igadinnovationhub.org/api/proposals/{proposal_id}/documents/work-text" \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "success": true,
  "message": "Work text deleted successfully"
}

What Gets Deleted

  1. S3 File: {proposal_code}/documents/supporting/existing_work_text.txt
  2. Vector Embeddings:
    • Deletes all vectors from existing-work-index
    • Searches for document_name = "existing_work_text"
    • Removes all chunks (may be multiple vectors)
  3. DynamoDB:
    • Removes text_inputs.existing-work field
    • Updates updated_at timestamp
Work text is chunked during upload, so deleting it removes multiple vector entries from the index.

Error Handling

Common Error Codes

CodeErrorReason
404Proposal not foundInvalid proposal ID or user doesn’t own it
500S3 Delete ErrorFailed to delete file from S3
500Failed to delete vectorsVector service error (non-critical)
500DynamoDB update failedDatabase update error

Non-Critical Failures

Vector deletion failures are logged but don’t fail the request:
Example
try:
    vector_service.delete_vectors_by_document_name(filename, index)
except Exception as e:
    print(f"⚠️  Vector deletion error (non-critical): {e}")
    # Continue with S3 and DynamoDB cleanup

Error Response Examples

{
  "detail": "Proposal not found"
}

Best Practices

1. Confirm Before Deleting

Always show a confirmation dialog before deleting documents, especially reference proposals:
Confirmation Example
const deleteDocument = async (filename: string) => {
  const confirmed = window.confirm(
    `Delete "${filename}"? This will remove the file and all associated vectors. This action cannot be undone.`
  )

  if (!confirmed) return

  try {
    const response = await fetch(
      `${API_URL}/api/proposals/${proposalId}/documents/reference/${filename}`,
      {
        method: 'DELETE',
        headers: { 'Authorization': `Bearer ${token}` },
      }
    )

    if (response.ok) {
      showSuccess('Document deleted successfully')
      refreshDocumentList()
    } else {
      const error = await response.json()
      showError('Deletion failed', error.detail)
    }
  } catch (err) {
    showError('Network error', 'Failed to delete document')
  }
}

2. Handle Partial Failures

Vector deletion may fail silently. Check logs if you suspect incomplete cleanup:
Check Logs
# Backend logs will show:
⚠️  No vectors found for document: filename.pdf
# or
⚠️  Vector deletion error (non-critical): ...

3. Refresh UI After Deletion

Refresh Pattern
const handleDelete = async (filename: string) => {
  await deleteDocument(filename)
  
  // Refresh document list
  await queryClient.invalidateQueries(['documents', proposalId])
  
  // Update vectorization status
  await queryClient.invalidateQueries(['vectorization-status', proposalId])
}

4. Bulk Deletion

For deleting multiple files, use Promise.all but handle individual failures:
Bulk Delete
const deleteMultiple = async (filenames: string[]) => {
  const results = await Promise.allSettled(
    filenames.map(filename =>
      fetch(`${API_URL}/api/proposals/${proposalId}/documents/reference/${filename}`, {
        method: 'DELETE',
        headers: { 'Authorization': `Bearer ${token}` },
      })
    )
  )

  const succeeded = results.filter(r => r.status === 'fulfilled').length
  const failed = results.filter(r => r.status === 'rejected').length

  showSuccess(`Deleted ${succeeded} files`)
  if (failed > 0) {
    showWarning(`Failed to delete ${failed} files`)
  }
}

5. Vector Index Cleanup

If vectors aren’t deleted properly (e.g., network error), you may need to manually clean up:
Manual Cleanup
from app.shared.vectors.service import VectorEmbeddingsService

vector_service = VectorEmbeddingsService()

# Delete by document name
vector_service.delete_vectors_by_document_name(
    document_name="orphaned_file.pdf",
    index_name="reference-proposals-index"
)

# Delete all vectors for a proposal
vector_service.delete_proposal_vectors(proposal_id="PROP-2024-001")

Cascade Deletion Summary

Document TypeS3VectorsDynamoDBAnalysis Data
RFP Document✅ Clears analysis
Concept File
Concept Text
Reference Proposalreference-proposals-index
Supporting Fileexisting-work-index
Work Textexisting-work-index (all chunks)

Build docs developers (and LLMs) love