Skip to content

API Endpoints

Base URL

  • Backend (direct access): http://localhost:8000 — use this when calling the API directly (curl, Python scripts, tests).
  • Via frontend proxy: The frontend accesses the API using the relative path /api/* — no host is hardcoded. Vite proxies it to localhost:8000 in dev; nginx proxies it to the backend container in production. See Frontend Architecture.
  • Production (direct): https://dna-prd-portfolio-we-ca-be.politepebble-2dcbf46f.westeurope.azurecontainerapps.io

Authentication

Currently, no authentication is required for public endpoints.

Endpoints

Health Check

Check if the API is running.

Endpoint: GET /health

Response:

{
  "status": "healthy",
  "message": "Portfolio API is running"
}

Example:

curl http://localhost:8000/health

Contact Form Submission

Submit a contact form message.

Endpoint: POST /api/contact

Request Body:

{
  "name": "John Doe",
  "email": "john@example.com",
  "message": "I'd like to discuss a project opportunity.",
  "company": "Example Corp"
}

Fields:

  • name (required): Full name of the sender
  • email (required): Valid email address
  • message (required): Message content (min 10 characters)
  • company (optional): Company name

Success Response (200):

{
  "success": true,
  "message": "Thank you for your message! I'll get back to you soon. A confirmation email has been sent to your address."
}

Error Response (400):

{
  "detail": [
    {
      "loc": ["body", "email"],
      "msg": "value is not a valid email address",
      "type": "value_error.email"
    }
  ]
}

Error Response (500):

{
  "success": false,
  "message": "Failed to send email. Please try again later."
}

Example:

curl -X POST http://localhost:8000/api/contact \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john@example.com",
    "message": "Hello, I would like to discuss a project.",
    "company": "Example Corp"
  }'

Email Behavior

When a contact form is submitted successfully:

  1. Notification Email sent to sven.relijveld@onedna.nl
  2. Contains all form details
  3. Professional HTML template
  4. Includes sender's contact information

  5. Confirmation Email sent to the form submitter

  6. Thanks them for reaching out
  7. Confirms message was received
  8. Professional branding

Rate Limiting

Currently no rate limiting is implemented. Consider adding in production:

  • Max 10 requests per minute per IP
  • Max 100 requests per hour per IP

CORS

CORS is configured to allow requests from:

  • Development: http://localhost:5173
  • Production: https://www.sven-relijveld.com

Error Codes

Code Description
200 Success
400 Bad Request (validation error)
422 Unprocessable Entity (invalid data)
500 Internal Server Error

Testing

Using curl

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

# Contact form
curl -X POST http://localhost:8000/api/contact \
  -H "Content-Type: application/json" \
  -d '{"name":"Test","email":"test@example.com","message":"Test message"}'

Using Python

import requests

# Health check
response = requests.get("http://localhost:8000/health")
print(response.json())

# Contact form
data = {
    "name": "Test User",
    "email": "test@example.com",
    "message": "This is a test message",
    "company": "Test Company"
}
response = requests.post("http://localhost:8000/api/contact", json=data)
print(response.json())

See Also