469 lines
8.8 KiB
Markdown
469 lines
8.8 KiB
Markdown
# 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. |