go-first/docs/API.md

405 lines
7.9 KiB
Markdown
Raw Normal View History

2026-10-07 15:21:47 +02:00
# 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
```json
{
"success": true,
"data": {},
"meta": {
"page": 1,
"page_size": 20,
"total": 100,
"total_pages": 5
}
}
```
### Error
```json
{
"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
```json
{
"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
```json
{
"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
```json
{
"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
```json
{
"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 Featured Projects
**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
```json
{
"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
```json
{
"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
```json
{
"name": "John Doe",
"email": "john@example.com",
"subject": "Project Inquiry",
"message": "Hello, I'd like to discuss a potential project..."
}
```
#### Response (201 Created)
```json
{
"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)
```json
{
"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
```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
```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