Skip to content

API Endpoints Reference

Complete API reference for the New Hires Reporting System backend API.

Base URL

  • Development: http://localhost:8000
  • Production: https://api.your-domain.com

Interactive Documentation

Swagger UI: {BASE_URL}/docs

Provides: - Interactive API testing - Request/response examples - Schema documentation - Try-it-out functionality

ReDoc: {BASE_URL}/redoc - Alternative API documentation view - Cleaner reading experience


Health & Status

GET /health

Check system health and configuration.

Response:

{
  "status": "healthy",
  "database": "connected",
  "workers": "operational",
  "version": "v1.0.0",
  "timestamp": "2025-01-24T10:00:00Z"
}

Status Codes: - 200 - Service healthy - 500 - Service unhealthy (database or workers down)

Example:

curl http://localhost:8000/health | jq


File Validation

POST /api/v1/files

Upload and validate an employer reporting file.

Parameters: - file (multipart/form-data) - File to validate - state (form-data) - State format: "Louisiana", "Texas", "Colorado", or "Ohio"

Request Example:

curl -X POST http://localhost:8000/api/v1/files \
  -F "[email protected]" \
  -F "state=Louisiana"

Response:

{
  "file_id": "uuid-here",
  "file_name": "sample.txt",
  "state": "Louisiana",
  "total_records": 50,
  "total_errors": 28,
  "records_with_errors": 15,
  "uploaded_at": "2025-01-24T10:00:00Z",
  "validation_status": "completed",
  "errors": [
    {
      "line_number": 5,
      "record_number": 5,
      "field_name": "EMPLOYEE-FIRSTNAME",
      "error_type": "MISSING_REQUIRED_FIELD",
      "error_message": "Required field cannot be blank",
      "current_value": "",
      "position": {"start": 50, "end": 80}
    }
  ]
}

Status Codes: - 200 - Validation successful - 400 - Invalid request (wrong format, missing parameters, unsupported state) - 413 - File too large (>50MB) - 422 - Validation error (file format issues) - 500 - Server error


GET /api/v1/files/{file_id}

Get validation results for a previously uploaded file.

Parameters: - file_id (path) - File identifier from upload response

Response: Same as POST /api/v1/files

Status Codes: - 200 - File found - 404 - File not found

Example:

curl http://localhost:8000/api/v1/files/uuid-here | jq


GET /api/v1/files

List all uploaded files.

Query Parameters: - skip (int, optional) - Number of records to skip (pagination) - limit (int, optional) - Max records to return (default: 100) - state (string, optional) - Filter by state

Response:

{
  "total": 150,
  "files": [
    {
      "file_id": "uuid-here",
      "file_name": "sample.txt",
      "state": "Louisiana",
      "total_errors": 28,
      "uploaded_at": "2025-01-24T10:00:00Z",
      "validation_status": "completed"
    }
  ]
}

Example:

curl "http://localhost:8000/api/v1/files?limit=10&state=Louisiana" | jq


Correction Jobs

POST /api/v1/jobs

Create a correction job for a validated file.

Request Body:

{
  "file_id": "uuid-here"
}

Response:

{
  "job_id": "job-uuid",
  "file_id": "uuid-here",
  "status": "pending",
  "created_at": "2025-01-24T10:00:00Z",
  "estimated_completion": "2025-01-24T10:02:00Z"
}

Status Codes: - 201 - Job created - 404 - File not found - 400 - No errors to correct or job already exists - 500 - Server error

Example:

curl -X POST http://localhost:8000/api/v1/jobs \
  -H "Content-Type: application/json" \
  -d '{"file_id":"uuid-here"}' | jq


GET /api/v1/jobs/{job_id}

Get correction job status and results.

Parameters: - job_id (path) - Job identifier

Response:

{
  "job_id": "job-uuid",
  "file_id": "uuid-here",
  "status": "completed",
  "created_at": "2025-01-24T10:00:00Z",
  "started_at": "2025-01-24T10:00:15Z",
  "completed_at": "2025-01-24T10:01:30Z",
  "corrections_applied": 18,
  "corrections_failed": 2,
  "error_message": null,
  "corrected_file_url": "/api/v1/jobs/job-uuid/download"
}

Job Status Values: - pending - Waiting for worker to pick up - processing - Worker is processing corrections - completed - Corrections successfully applied - failed - Job failed (see error_message)

Status Codes: - 200 - Job found - 404 - Job not found

Example:

curl http://localhost:8000/api/v1/jobs/job-uuid | jq


GET /api/v1/jobs

List all correction jobs.

Query Parameters: - skip (int, optional) - Number of records to skip - limit (int, optional) - Max records to return (default: 100) - status (string, optional) - Filter by status: "pending", "processing", "completed", "failed"

Response:

{
  "total": 75,
  "jobs": [
    {
      "job_id": "job-uuid",
      "file_id": "uuid-here",
      "status": "completed",
      "created_at": "2025-01-24T10:00:00Z",
      "completed_at": "2025-01-24T10:01:30Z"
    }
  ]
}

Example:

curl "http://localhost:8000/api/v1/jobs?status=completed&limit=20" | jq


GET /api/v1/jobs/{job_id}/download

Download corrected file.

Parameters: - job_id (path) - Job identifier

Response: File download (text/plain)

Status Codes: - 200 - File downloaded - 404 - Job not found or not completed - 500 - Server error

Example:

curl http://localhost:8000/api/v1/jobs/job-uuid/download \
  -o corrected.txt


Error Responses

All endpoints may return error responses:

{
  "detail": "Error message here"
}

Common Status Codes: - 400 - Bad Request (invalid parameters) - 404 - Not Found (resource doesn't exist) - 413 - Payload Too Large (file too big) - 422 - Unprocessable Entity (validation error) - 429 - Too Many Requests (rate limited) - 500 - Internal Server Error - 503 - Service Unavailable (database or workers down)


Rate Limiting

Development

No rate limits

Production

Configured at reverse proxy level: - API endpoints: 10 requests/second per IP - File uploads: 5 requests/minute per IP - Burst: 20 requests

Rate Limit Headers:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 8
X-RateLimit-Reset: 1642262400

When rate limited, you'll receive:

{
  "detail": "Rate limit exceeded. Try again in 60 seconds."
}


Authentication

Current

No authentication required

Future (Optional)

API key or bearer token authentication may be added:

curl http://localhost:8000/api/v1/files \
  -H "X-API-Key: your-api-key" \
  -F "[email protected]" \
  -F "state=Louisiana"

CORS

Allowed Origins (Production): - Frontend domain: https://your-domain.com - Configurable via VITE_API_URL in .env

Allowed Methods: - GET, POST, PUT, DELETE, OPTIONS

Allowed Headers: - Content-Type, Authorization, X-API-Key


File Size Limits

Environment Max Size Max Records Notes
Development 50 MB ~40,000 Configurable
Production 50 MB ~40,000 Set at reverse proxy

To increase, update reverse proxy configuration:

Nginx:

client_max_body_size 100M;

Caddy:

request_body {
    max_size 100MB
}


Timeout Settings

Operation Timeout Notes
File upload 60s Client-side
Validation 120s Backend processing
Job creation 30s Database write
Correction processing 5-120s Depends on errors and model
AWS Bedrock API call 60s Per API call to Bedrock
Download 30s File generation

Testing

Health Check

# Basic health check
curl http://localhost:8000/health

# With pretty JSON
curl http://localhost:8000/health | jq

Complete Workflow

# 1. Upload and validate file
FILE_RESPONSE=$(curl -s -X POST http://localhost:8000/api/v1/files \
  -F "[email protected]" \
  -F "state=Louisiana")

FILE_ID=$(echo $FILE_RESPONSE | jq -r '.file_id')
echo "File ID: $FILE_ID"

# 2. Check validation results
curl http://localhost:8000/api/v1/files/$FILE_ID | jq

# 3. Create correction job
JOB_RESPONSE=$(curl -s -X POST http://localhost:8000/api/v1/jobs \
  -H "Content-Type: application/json" \
  -d "{\"file_id\":\"$FILE_ID\"}")

JOB_ID=$(echo $JOB_RESPONSE | jq -r '.job_id')
echo "Job ID: $JOB_ID"

# 4. Check job status (poll until completed)
while true; do
  STATUS=$(curl -s http://localhost:8000/api/v1/jobs/$JOB_ID | jq -r '.status')
  echo "Status: $STATUS"
  if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then
    break
  fi
  sleep 2
done

# 5. Download corrected file
curl http://localhost:8000/api/v1/jobs/$JOB_ID/download \
  -o corrected.txt

echo "Corrected file saved as corrected.txt"

Python Example

import requests
import time

BASE_URL = "http://localhost:8000"

# 1. Upload and validate file
with open('sample.txt', 'rb') as f:
    response = requests.post(
        f'{BASE_URL}/api/v1/files',
        files={'file': f},
        data={'state': 'Louisiana'}
    )

file_data = response.json()
file_id = file_data['file_id']
print(f"File ID: {file_id}")
print(f"Total errors: {file_data['total_errors']}")

# 2. Create correction job
job_response = requests.post(
    f'{BASE_URL}/api/v1/jobs',
    json={'file_id': file_id}
)

job_data = job_response.json()
job_id = job_data['job_id']
print(f"Job ID: {job_id}")

# 3. Poll for completion
while True:
    status_response = requests.get(f'{BASE_URL}/api/v1/jobs/{job_id}')
    status_data = status_response.json()

    status = status_data['status']
    print(f"Status: {status}")

    if status in ['completed', 'failed']:
        if status == 'completed':
            print(f"Corrections applied: {status_data['corrections_applied']}")
        else:
            print(f"Error: {status_data['error_message']}")
        break

    time.sleep(2)

# 4. Download corrected file
if status == 'completed':
    download_response = requests.get(
        f'{BASE_URL}/api/v1/jobs/{job_id}/download'
    )

    with open('corrected.txt', 'wb') as f:
        f.write(download_response.content)

    print("Corrected file saved as corrected.txt")

OpenAPI Specification

Full API specification available at:

  • OpenAPI JSON: {BASE_URL}/openapi.json
  • Swagger UI: {BASE_URL}/docs
  • ReDoc: {BASE_URL}/redoc

Download specification:

curl http://localhost:8000/openapi.json > api-spec.json


Monitoring Endpoints

GET /metrics

Prometheus-compatible metrics endpoint (if enabled).

Response: Prometheus text format

Metrics Include: - Request counts - Response times - Error rates - Active connections - Job queue depth

Example:

curl http://localhost:8000/metrics


Database Health

The /health endpoint checks database connectivity. If unhealthy:

{
  "status": "unhealthy",
  "database": "disconnected",
  "error": "Could not connect to database"
}

Troubleshooting:

# Check database is running
docker ps | grep newhires-db

# Check backend can reach database
docker exec newhires-backend env | grep DATABASE_URL

# Restart backend
docker-compose -f docker-compose.prod.yml restart backend


Next Steps