DEV Community

Isaac
Isaac

Posted on

🐱How I Built a Simple Go API to Return My Profile and a Random Cat Fact For my HNG13 stage 0 backend task

So I'm participating in the HNG13 internship program and our stage 0 task was to build a simple API to Return your Profile and a Random Cat Fact.

I’ve been learning Go (Golang) for a while now and wanted to build it with that and here's how it went.

In this post, I’ll walk you through how I built this tiny Go + Gin API.

🔧 Stack

Go (Golang)

Gin - HTTP web framework

catfact.ninja API - Free API to fetch random cat facts

🛠️ What the API Does

When you hit the endpoint /me, the API returns:

My name, email, and stack

The current timestamp (UTC)

A random cat fact 🐱

Here’s an example response:

{
"status": "success",
"user": {
"email": "",
"name": "",
"stack": "Go/Gin"
},
"timestamp": "2025-10-21T14:42:11Z",
"fact": "Cats sleep for 70% of their lives."
}

🚀 Setting Up the Controller

The core logic lives inside the controller. Here's the full code:

package controllers

import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"time"

"github.com/gin-gonic/gin"
Enter fullscreen mode Exit fullscreen mode

)

func GetProfile(c *gin.Context) {
ctx := c.Request.Context()

fact, err := fetchCatFact(ctx)
if err != nil {
    log.Printf("Error fetching cat fact: %v", err)
    fact = "Unable to fetch cat fact at this time. Did you know cats are amazing creatures?"
}

c.JSON(200, gin.H{
    "status": "success",
    "user": gin.H{
         "email": "<your-email>",
                     "name": "<your-name>",
        "stack": "Go/Gin",
    },
    "timestamp": time.Now().UTC().Format(time.RFC3339),
    "fact":      fact,
})
Enter fullscreen mode Exit fullscreen mode

}

🐾 Fetching the Cat Fact

This function handles calling the catfact.ninja
API and parsing the response.

func fetchCatFact(ctx context.Context) (string, error) {
catFactAPIURL := "https://catfact.ninja/fact"

req, err := http.NewRequestWithContext(ctx, http.MethodGet, catFactAPIURL, nil)
if err != nil {
    return "", fmt.Errorf("failed to create request: %w", err)
}

req.Header.Set("Accept", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    return "", fmt.Errorf("failed to fetch cat fact: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
    return "", fmt.Errorf("cat fact API returned status: %d", resp.StatusCode)
}

type CatFactResponse struct {
    Fact   string `json:"fact"`
    Length int    `json:"length"`
}
var catFact CatFactResponse
if err := json.NewDecoder(resp.Body).Decode(&catFact); err != nil {
    return "", fmt.Errorf("failed to decode response: %w", err)
}

return catFact.Fact, nil
Enter fullscreen mode Exit fullscreen mode

}

🌐 Routing

To expose this functionality, I created a route under /me:

package routes

import (
"profile-api/internal/controllers"
"github.com/gin-gonic/gin"
)

func RegisterRoutes() {
r := gin.Default()

// Optional: Skip ngrok browser warning
r.Use(func(c *gin.Context) {
    c.Header("ngrok-skip-browser-warning", "1")
    c.Next()
})

r.GET("/me", controllers.GetProfile)

r.Run(":8080") // Start server on port 8080
Enter fullscreen mode Exit fullscreen mode

}

🧪 Testing It Out

Run your app:

go run main.go

Then visit: http://localhost:8080/me

You should see your profile and a random cat fact returned in JSON.

📌 Final Thoughts

This was a small but fun project to reinforce using context, external APIs, and building structured JSON responses in Go. Plus, it’s always nice to sprinkle a little joy into development — and what’s more joyful than random cat facts?

Want to build your own version? Fork the idea, make it your own, and maybe add facts from other APIs (dog facts next? 🐶)

Let me know what you think!

Top comments (0)