go-first/docs/API.md
2026-10-07 15:21:47 +02:00

7.9 KiB

API Documentation — go-first / URPI

Base URL: https://www.urpi.be/api/v1
Local: http://localhost:8080/api/v1

All responses follow a consistent envelope format.


Response Format

Success

{
  "success": true,
  "data": {},
  "meta": {
    "page": 1,
    "page_size": 20,
    "total": 100,
    "total_pages": 5
  }
}

Error

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human readable message",
    "details": "Optional technical details"
  }
}

Common Error Codes

Code HTTP Status Description
VALIDATION_ERROR 400 Request body validation failed
INVALID_ID 400 UUID format invalid
NOT_FOUND 404 Resource not found
UNAUTHORIZED 401 Authentication required
FORBIDDEN 403 Insufficient permissions
CONFLICT 409 Resource conflict
RATE_LIMITED 429 Too many requests
INTERNAL_ERROR 500 Server error
SERVICE_UNAVAILABLE 503 Service temporarily unavailable

Endpoints

Health Check

GET /health

No authentication required.

Response

{
  "success": true,
  "data": {
    "status": "ok",
    "service": "go-first",
    "version": "1.0.0"
  }
}

Skills

List Skills

GET /skills

Query Param Type Description
category string Filter by category (Backend, Frontend, Architecture, DevOps, Database, API)

Response

{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "name": "Go",
      "category": "Backend",
      "proficiency": 5,
      "icon": "go",
      "order": 1,
      "created_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ]
}

Get Skill

GET /skills/:id

Path Param Type Description
id uuid Skill UUID

Response

{
  "success": true,
  "data": {
    "id": "uuid",
    "name": "Go",
    "category": "Backend",
    "proficiency": 5,
    "icon": "go",
    "order": 1,
    "created_at": "2024-01-01T00:00:00Z",
    "updated_at": "2024-01-01T00:00:00Z"
  }
}

Projects

List Projects

GET /projects

Query Param Type Description
category string Filter by category
featured boolean Filter featured projects only

Response

{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "title": "E-Commerce Platform",
      "description": "Full description...",
      "short_desc": "Scalable e-commerce platform...",
      "tech_stack": ["Go", "React", "PostgreSQL", "Redis", "Kubernetes"],
      "image_url": "/images/projects/ecommerce.jpg",
      "demo_url": "https://demo.urpi.be/ecommerce",
      "repo_url": "https://github.com/urpi/ecommerce-platform",
      "category": "Full Stack",
      "featured": true,
      "order": 1,
      "created_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ]
}

GET /projects/featured

Returns only projects with featured: true.

Get Project

GET /projects/:id

Path Param Type Description
id uuid Project UUID

Experience

List Experience

GET /experience

Returns all work experience entries ordered by order field.

Response

{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "company": "URPI",
      "role": "Founder & Lead Developer",
      "location": "Belgium",
      "start_date": "2020-01-01T00:00:00Z",
      "end_date": null,
      "current": true,
      "description": "Founded URPI to provide web application...",
      "tech_stack": ["Go", "Java", "React", "Kubernetes", "AWS"],
      "order": 1,
      "created_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ]
}

Services

List Services

GET /services

Returns all active services offered.

Response

{
  "success": true,
  "data": [
    {
      "id": "uuid",
      "title": "Web Application Development",
      "description": "Custom web applications built with modern technologies...",
      "icon": "code",
      "features": [
        "React/Next.js Frontend",
        "Go/Java Backend",
        "REST/GraphQL APIs"
      ],
      "order": 1,
      "active": true,
      "created_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ]
}

Contact

Submit Contact Form

POST /contact

Content-Type: application/json

Field Type Required Validation
name string Yes 2-100 chars
email string Yes Valid email format
subject string Yes 5-200 chars
message string Yes 10-5000 chars

Request

{
  "name": "John Doe",
  "email": "john@example.com",
  "subject": "Project Inquiry",
  "message": "Hello, I'd like to discuss a potential project..."
}

Response (201 Created)

{
  "success": true,
  "data": {
    "id": "uuid",
    "name": "John Doe",
    "email": "john@example.com",
    "subject": "Project Inquiry",
    "message": "Hello, I'd like to discuss a potential project...",
    "status": "new",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  }
}

Validation Error (400)

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request body",
    "details": "Key: 'ContactForm.Email' Error:Field validation for 'Email' failed on the 'email' tag"
  }
}

Rate Limiting

Endpoint Limit
/api/v1/* (general) 10 req/s per IP
/api/v1/contact 5 req/min per IP
/api/v1/health No limit

Headers returned:

  • X-RateLimit-Limit
  • X-RateLimit-Remaining
  • X-RateLimit-Reset

CORS

Allowed origins (configured in config.yaml):

  • https://www.urpi.be
  • https://urpi.be
  • http://localhost:3000
  • http://localhost:5173

Allowed methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Allowed headers: Origin, Content-Type, Accept, Authorization, X-Requested-With
Credentials: true


Versioning

API version in URL path: /api/v1/

Breaking changes will result in /api/v2/ etc.
Non-breaking additions (new fields, new endpoints) may be added to v1.


Authentication

Currently no authentication required for public endpoints.

Future plans:

  • JWT-based auth for admin endpoints
  • API keys for programmatic access
  • OAuth2 for third-party integrations

SDKs / Clients

JavaScript/TypeScript

const API_BASE = '/api/v1';

async function fetchAPI<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
  const res = await fetch(`${API_BASE}${endpoint}`, {
    headers: { 'Content-Type': 'application/json', ...options.headers },
    ...options,
  });
  const data = await res.json();
  if (!res.ok || !data.success) throw new Error(data.error?.message || 'Error');
  return data.data;
}

// Usage
const skills = await fetchAPI<Skill[]>('/skills');
const project = await fetchAPI<Project>('/projects/uuid');
await fetchAPI<ContactSubmission>('/contact', {
  method: 'POST',
  body: JSON.stringify({ name, email, subject, message })
});

Go

type APIResponse struct {
    Success bool        `json:"success"`
    Data    interface{} `json:"data,omitempty"`
    Error   *APIError   `json:"error,omitempty"`
}

func GetSkills(ctx context.Context) ([]Skill, error) {
    req, _ := http.NewRequestWithContext(ctx, "GET", "https://www.urpi.be/api/v1/skills", nil)
    resp, err := http.DefaultClient.Do(req)
    // ... parse response
}

Changelog

v1.0.0 (2024-01-15)

  • Initial API release
  • Skills, Projects, Experience, Services, Contact endpoints
  • Rate limiting and CORS configuration
  • Health check endpoint