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 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
{
"success": true,
"data": [
{
"id": "uuid",
"company": "URPI",
"role": "Founder & Lead Developer",
"location": "Goorstraat 5, 2960 Brecht 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-LimitX-RateLimit-RemainingX-RateLimit-Reset
CORS
Allowed origins (configured in config.yaml):
https://www.urpi.behttps://urpi.behttp://localhost:3000http://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