# API Reference This document provides a comprehensive reference for all API endpoints in the STUPA PDF API system. ## Base URL - **Development**: `http://localhost:8000` - **Production**: `https://your-domain.com/api` ## Authentication The API uses two types of authentication: ### Application Key Authentication - **Header**: `X-PA-KEY` - **Purpose**: Access specific application data - **Scope**: Read/write access to single application ### Master Key Authentication - **Header**: `X-MASTER-KEY` - **Purpose**: Administrative access - **Scope**: Full access to all resources ### Query Parameter Authentication For endpoints that need to work with direct browser access (like PDF downloads), you can use: - **Parameter**: `key` - **Example**: `/applications/25-0001?format=pdf&key=your-app-key` ## Response Format All API responses follow this general structure: ```json { "data": { ... }, // For successful responses "detail": "...", // For error messages "status": "success" // Optional status indicator } ``` ## Error Responses ```json { "detail": "Error message here" } ``` Common HTTP status codes: - `200 OK` - Success - `201 Created` - Resource created - `400 Bad Request` - Invalid request data - `401 Unauthorized` - Missing or invalid authentication - `403 Forbidden` - Insufficient permissions - `404 Not Found` - Resource not found - `429 Too Many Requests` - Rate limit exceeded - `500 Internal Server Error` - Server error ## Endpoints ### Health Check #### GET / Check if the API is running. **Response:** ```json { "message": "STUPA PDF API" } ``` --- ### PDF Upload and Processing #### POST /upload Upload a PDF form and create a new application. **Request:** - **Content-Type**: `multipart/form-data` - **Body**: - `file` (required): PDF file to upload - `form_type` (required): Type of form (`"pa_form"` or `"vsm_form"`) **Response:** ```json { "pa_id": "25-0001", "pa_key": "generated-secure-key", "data": { "projectBeginn": "2025-01-01", "name": "Student Project", // ... other parsed data } } ``` **Example:** ```bash curl -X POST "http://localhost:8000/upload" \ -F "file=@application.pdf" \ -F "form_type=pa_form" ``` --- ### Application Management #### GET /applications/{pa_id} Retrieve application data. **Parameters:** - `pa_id` (path): Application ID (e.g., "25-0001") - `format` (query): Response format (`"json"` or `"pdf"`) - `key` (query): Application key (alternative to header) **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Response (JSON):** ```json { "pa_id": "25-0001", "created_at": "2024-01-01T00:00:00", "updated_at": "2024-01-01T00:00:00", "data": { "projectBeginn": "2025-01-01", "name": "Student Project", // ... full application data } } ``` **Response (PDF):** Binary PDF file with filled form. --- #### PUT /applications/{pa_id} Update application data. **Parameters:** - `pa_id` (path): Application ID **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Request Body:** ```json { "projectBeginn": "2025-01-01", "name": "Updated Project Name", // ... fields to update } ``` **Response:** ```json { "pa_id": "25-0001", "data": { // ... updated application data } } ``` --- #### DELETE /applications/{pa_id} Delete an application (admin only). **Parameters:** - `pa_id` (path): Application ID **Headers:** - `X-MASTER-KEY` (required) **Response:** ```json { "detail": "Application deleted successfully" } ``` --- ### Attachment Management #### GET /applications/{pa_id}/attachments List all attachments for an application. **Parameters:** - `pa_id` (path): Application ID **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Response:** ```json { "attachments": [ { "id": 1, "filename": "receipt.pdf", "content_type": "application/pdf", "size": 102400, "created_at": "2024-01-01T00:00:00" } ], "total_count": 1, "total_size": 102400 } ``` --- #### POST /applications/{pa_id}/attachments Upload a new attachment. **Parameters:** - `pa_id` (path): Application ID **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Request:** - **Content-Type**: `multipart/form-data` - **Body**: - `file` (required): File to upload **Response:** ```json { "id": 1, "filename": "receipt.pdf", "content_type": "application/pdf", "size": 102400, "created_at": "2024-01-01T00:00:00" } ``` **Limits:** - Maximum 30 attachments per application - Maximum 100MB total size per application - Maximum 50MB per file --- #### GET /applications/{pa_id}/attachments/{attachment_id} Download a specific attachment. **Parameters:** - `pa_id` (path): Application ID - `attachment_id` (path): Attachment ID **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Response:** Binary file data --- #### DELETE /applications/{pa_id}/attachments/{attachment_id} Delete an attachment. **Parameters:** - `pa_id` (path): Application ID - `attachment_id` (path): Attachment ID **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Response:** ```json { "detail": "Attachment deleted successfully" } ``` --- ### Comparison Offers #### GET /applications/{pa_id}/costs/{cost_position_index}/offers Get comparison offers for a cost position. **Parameters:** - `pa_id` (path): Application ID - `cost_position_index` (path): Cost position index (0-based) **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Response:** ```json { "cost_position_index": 0, "offers": [ { "id": 1, "supplier_name": "Supplier A", "amount": 1000.00, "description": "Standard package", "url": "https://supplier-a.com/quote", "attachment_id": null, "is_preferred": false, "created_at": "2024-01-01T00:00:00" } ], "no_offers_required": false, "justification": null } ``` --- #### POST /applications/{pa_id}/costs/{cost_position_index}/offers Create a new comparison offer. **Parameters:** - `pa_id` (path): Application ID - `cost_position_index` (path): Cost position index **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Request Body:** ```json { "supplier_name": "Supplier A", "amount": 1000.00, "description": "Standard package", "url": "https://supplier-a.com/quote", "attachment_id": null, "is_preferred": false } ``` **Response:** ```json { "id": 1, "supplier_name": "Supplier A", "amount": 1000.00, "description": "Standard package", "url": "https://supplier-a.com/quote", "attachment_id": null, "is_preferred": false, "created_at": "2024-01-01T00:00:00" } ``` --- #### PUT /applications/{pa_id}/costs/{cost_position_index}/offers/{offer_id}/preferred Set an offer as preferred. **Parameters:** - `pa_id` (path): Application ID - `cost_position_index` (path): Cost position index - `offer_id` (path): Offer ID **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Response:** ```json { "detail": "Preferred offer updated successfully" } ``` --- #### DELETE /applications/{pa_id}/costs/{cost_position_index}/offers/{offer_id} Delete a comparison offer. **Parameters:** - `pa_id` (path): Application ID - `cost_position_index` (path): Cost position index - `offer_id` (path): Offer ID **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Response:** ```json { "detail": "Offer deleted successfully" } ``` --- #### PUT /applications/{pa_id}/costs/{cost_position_index}/justification Update justification for not requiring comparison offers. **Parameters:** - `pa_id` (path): Application ID - `cost_position_index` (path): Cost position index **Headers:** - `X-PA-KEY` or `X-MASTER-KEY` **Request Body:** ```json { "no_offers_required": true, "justification": "This is a unique service provider with no alternatives..." } ``` **Response:** ```json { "detail": "Justification updated successfully" } ``` --- ## Rate Limiting The API implements rate limiting to prevent abuse: - **Per IP**: 60 requests per minute (configurable) - **Per Key**: 30 requests per minute (configurable) - **Excluded**: localhost and Docker internal IPs Rate limit headers in responses: - `X-RateLimit-Limit`: Maximum requests allowed - `X-RateLimit-Remaining`: Requests remaining - `X-RateLimit-Reset`: Unix timestamp when limit resets --- ## WebSocket Endpoints Currently, the API does not provide WebSocket endpoints. All communication is via REST HTTP. --- ## Pagination For endpoints that return lists, pagination may be implemented in future versions using: - `limit`: Number of items per page - `offset`: Starting position - `page`: Page number (alternative to offset) --- ## Versioning The API currently does not use versioning. Future versions may implement versioning via: - URL path: `/v1/applications` - Header: `Accept: application/vnd.stupa.v1+json` --- ## OpenAPI Documentation Complete OpenAPI 3.0 documentation is available at: - **Swagger UI**: `/docs` - **ReDoc**: `/redoc` - **OpenAPI JSON**: `/openapi.json` These provide interactive documentation with the ability to test endpoints directly.