Appearance
Response Storage API Documentation
Version: 1.0.0 Last Updated: 2025-11-22
Overview
The Response Storage API provides endpoints for managing AI response storage with configurable retention policies and automatic cleanup. This feature allows users to:
- Store AI responses with configurable retention periods
- View and export stored responses
- Manage storage limits at company and prompt levels
- Track storage usage statistics
Retention Options
The following retention periods are available:
| Value | Description | Duration |
|---|---|---|
| 0 | No Storage (Zero Copy) | No retention |
| 5 | 5 Days | 5 days |
| 30 | 30 Days | 30 days |
| 60 | 60 Days (Default) | 60 days |
| 180 | 180 Days | 180 days |
| 360 | 360 Days (Maximum) | 360 days |
Retention Policy Hierarchy
- Prompt-level setting (if configured) - Takes precedence
- Company default - Used if prompt-level not set
- Package default - Fallback from subscription package
API Endpoints
1. Get Responses for a Prompt
GET /api/responses?promptId={promptId}&limit={limit}&offset={offset}
Retrieves a paginated list of responses for a specific prompt.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| promptId | string | Yes | - | The prompt ID to fetch responses for |
| limit | number | No | 50 | Maximum number of responses to return |
| offset | number | No | 0 | Offset for pagination |
Response
json
{
"responses": [
{
"id": "resp_abc123",
"executionId": "exec_xyz789",
"responsePreview": "This is a sample response text...",
"provider": "OPENAI",
"model": "gpt-4",
"totalTokens": 1250,
"costCents": 25,
"executionTime": 1500,
"createdAt": "2025-11-22T10:30:00Z",
"expiresAt": "2026-01-21T10:30:00Z",
"contentSize": 5240
}
],
"pagination": {
"limit": 50,
"offset": 0,
"hasMore": false
}
}2. Get Storage Statistics
GET /api/responses?action=stats
Retrieves company-wide storage usage statistics.
Response
json
{
"currentStorageBytes": "1048576",
"maxStorageBytes": "10737418240",
"storagePercentage": 0.01,
"currentCount": 150,
"maxCount": 5000,
"countPercentage": 3.0,
"defaultRetentionDays": 60,
"packageName": "Professional Plan"
}3. Get Single Response
GET /api/responses/{responseId}
Retrieves a single response with full content.
Response
json
{
"id": "resp_abc123",
"executionId": "exec_xyz789",
"promptId": "prompt_def456",
"content": "Full response content here...",
"contentHash": "sha256_hash_here",
"provider": "OPENAI",
"model": "gpt-4",
"quality": "high",
"inputTokens": 250,
"outputTokens": 1000,
"totalTokens": 1250,
"costCents": 25,
"executionTime": 1500,
"companyId": "company_123",
"userId": "user_456",
"isDeleted": false,
"createdAt": "2025-11-22T10:30:00Z",
"responsePreview": "Full response content here...",
"expiresAt": "2026-01-21T10:30:00Z",
"contentSize": 5240,
"prompt": {
"name": "Customer Support Response",
"promptId": "prompt_def456"
}
}4. Export Response
GET /api/responses/{responseId}?action=export&format={format}
Exports a response in the specified format.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| format | string | No | json | Export format: json or txt |
Response
Returns a file download with appropriate Content-Type and Content-Disposition headers.
5. Get Retention Settings
GET /api/settings/response-retention?promptId={promptId}
Retrieves current retention settings for a prompt or company.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| promptId | string | No | Prompt ID (omit for company-level settings) |
Response (Prompt-level)
json
{
"promptRetention": 30,
"effectiveRetention": 30,
"isUsingDefault": false
}Response (Company-level)
json
{
"defaultRetentionDays": 60
}6. Update Retention Settings
POST /api/settings/response-retention
Updates retention settings for a prompt or company.
Request Body
json
{
"promptId": "prompt_def456", // Optional, required for prompt scope
"retentionDays": 30, // Must be one of: 0, 5, 30, 60, 180, 360
"scope": "prompt" // "prompt" or "company"
}Response
json
{
"success": true,
"message": "Prompt retention updated to 30 days"
}Storage Management
Automatic Cleanup
The system automatically:
- Deletes expired responses - Responses are marked as deleted when they reach their expiration date
- Enforces storage limits - When limits are exceeded, oldest responses are deleted first
- Updates usage tracking - Storage and count metrics are updated in real-time
Storage Limits by Package
| Package | Storage Limit | Response Count Limit |
|---|---|---|
| Basic | 100 MB | 500 responses |
| Professional | 1 GB | 5,000 responses |
| Growth | 10 GB | 50,000 responses |
| Enterprise | 100 GB | Unlimited |
Cleanup Service
The cleanup service can be triggered manually or scheduled:
typescript
import { cleanupExpiredResponses } from '@/lib/response-cleanup'
// Run cleanup
const result = await cleanupExpiredResponses(false)
console.log(`Deleted ${result.deletedCount} responses, freed ${result.freedBytes} bytes`)Response Storage Service
Storing Responses
typescript
import { storeResponse } from '@/lib/response-storage'
const result = await storeResponse({
executionId: 'exec_123',
promptId: 'prompt_456',
content: 'AI response content...',
contentHash: 'sha256_hash',
provider: 'OPENAI',
model: 'gpt-4',
inputTokens: 250,
outputTokens: 1000,
totalTokens: 1250,
costCents: 25,
executionTime: 1500,
companyId: 'company_123',
userId: 'user_456'
})
if (result.success) {
console.log('Response stored:', result.responseId)
} else {
console.error('Storage failed:', result.error)
}Calculating Retention
typescript
import { calculateExpirationDate } from '@/lib/response-storage'
const expiresAt = await calculateExpirationDate('prompt_456', 'company_123')
// Returns Date or null (for zero-copy mode)Checking Limits
typescript
import { checkStorageLimits } from '@/lib/response-storage'
const limits = await checkStorageLimits('company_123')
if (!limits.canStore) {
console.log('Storage limit exceeded:', limits.reason)
}UI Components
ResponseList
Displays a list of stored responses with previews.
tsx
import { ResponseList } from '@/components/response-storage'
<ResponseList promptId="prompt_456" />ResponseViewerModal
Modal for viewing full response content with export options.
tsx
import { ResponseViewerModal } from '@/components/response-storage'
<ResponseViewerModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
responseId={responseId}
/>StorageSettings
Component for configuring retention policies.
tsx
import { StorageSettings } from '@/components/response-storage'
<StorageSettings
promptId="prompt_456"
scope="prompt"
onSave={() => console.log('Settings saved')}
/>StorageStatistics
Display company-wide storage usage.
tsx
import { StorageStatistics } from '@/components/response-storage'
<StorageStatistics refreshInterval={60000} />Error Handling
All API endpoints return standard error responses:
json
{
"error": "Error message description"
}Common HTTP status codes:
400- Bad Request (invalid parameters)401- Unauthorized (not authenticated)403- Forbidden (no access to resource)404- Not Found (resource doesn't exist)500- Internal Server Error
Best Practices
- Zero-Copy Mode - Use for sensitive data that shouldn't be stored
- Appropriate Retention - Balance between convenience and storage costs
- Regular Cleanup - Schedule cleanup jobs to run daily
- Monitor Usage - Track storage statistics to avoid hitting limits
- Export Important Responses - Download responses before they expire
Migration Guide
When enabling response storage:
- Run database migrations:
npm run db:generate && npm run db:push - Update package limits in database
- Configure company default retention policies
- Enable storage in prompt configurations
- Schedule cleanup cron job
Security Considerations
- Responses are associated with companies for access control
- Users can only view responses from their company
- Soft-delete mechanism allows recovery if needed
- Content hashing for integrity verification
- Encryption support via existing encryption keys
Performance Notes
- Response previews are limited to first 10 words for fast loading
- Full content only loaded when viewing individual responses
- Indexes on
promptId,companyId, andexpiresAtfor fast queries - Cleanup runs in background to avoid blocking
