Garaad Coding Students

Mock REST API

A free, read-only API seeded with Somali-diaspora data. No auth, no signup — just start fetching. Built for students learning React, JavaScript, and REST APIs.

20
Jobs
15
Users
15
Products
10
Companies
10
Posts

Quick Start

1
Copy any endpoint URL from this page
2
Paste into your React component inside useEffect
3
Call fetch(url).then(r => r.json()) and render json.data
4
All responses have the same shape: { success, count, data }
🌐 Base URL
All API endpoints are prefixed with /api. Locally the server runs on port 3001.
Local http://localhost:3001
Deployed https://your-app.railway.app
📦 Response Format
Every response uses the same consistent shape so your code stays predictable.

List (200)

{
  "success": true,
  "count": 20,
  "data": [ ... ]
}

Single item (200)

{
  "success": true,
  "data": { ... }
}

Not found (404)

{
  "success": false,
  "error": "Job with id 99
  not found"
}
🖼️ Images & Avatars
Every resource includes image fields. All URLs are real, publicly hosted, and load without auth.
ResourceFieldProviderExample
users avatar pravatar.cc Photo avatar, deterministic by email
jobs companyLogo ui-avatars.com Coloured initials logo, unique per company
products image picsum.photos Deterministic photo by product name seed
companies logo ui-avatars.com Coloured initials logo, unique per company
posts coverImage picsum.photos 800×400 banner, deterministic by post slug
💼 Jobs
20 job listings across Dublin, London, Minneapolis, Mogadishu, and Toronto.
GET /api/jobs All jobs
GET /api/jobs/:id Single job by ID
GET /api/jobs?type=Remote Filter by type (Remote, Full-time, Part-time, Contract)
GET /api/jobs?location=Dublin Filter by location (partial match)
GET /api/jobs?isOpen=true Open listings only
React Example
function JobList() {
  const [jobs, setJobs] = useState([]);

  useEffect(() => {
    fetch('/api/jobs?isOpen=true')
      .then(r => r.json())
      .then(json => setJobs(json.data));
  }, []);

  return (
    <ul>
      {jobs.map(job => (
        <li key={job.id}>
          <img src={job.companyLogo} alt={job.company} width="40" />
          <strong>{job.title}</strong> — {job.company}
        </li>
      ))}
    </ul>
  );
}
👤 Users
15 users with Somali names across all cities. Includes photo avatars via pravatar.cc.
GET /api/users All users
GET /api/users/:id Single user by ID
GET /api/users?role=developer Filter by role (student, developer, designer, manager)
GET /api/users?city=London Filter by city (partial match)
React Example — Rendering Avatars
function UserCard({ user }) {
  return (
    <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
      <img
        src={user.avatar}
        alt={user.name}
        width="48"
        height="48"
        style={{ borderRadius: '50%' }}
      />
      <div>
        <strong>{user.name}</strong>
        <p>{user.city} · {user.role}</p>
        <p>{user.bio}</p>
      </div>
    </div>
  );
}
🛍️ Products
15 products (tech + lifestyle). All include a image URL from picsum.photos.
GET /api/products All products
GET /api/products/:id Single product by ID
GET /api/products?category=tech Filter by category
GET /api/products?inStock=true In-stock items only
GET /api/products?minPrice=10&maxPrice=100 Filter by price range
React Example — Product Card with Image
function ProductCard({ product }) {
  return (
    <div style={{ border: '1px solid #ddd', borderRadius: '8px', overflow: 'hidden' }}>
      <img src={product.image} alt={product.name} style={{ width: '100%', height: '200px', objectFit: 'cover' }} />
      <div style={{ padding: '16px' }}>
        <h3>{product.name}</h3>
        <p>${product.price} {product.currency}</p>
        <p>⭐ {product.rating} ({product.reviews} reviews)</p>
        <span>{product.inStock ? '✅ In stock' : '❌ Out of stock'}</span>
      </div>
    </div>
  );
}
🏢 Companies
10 fictional Somali-diaspora tech companies, each with a unique coloured logo.
GET /api/companies All companies
GET /api/companies/:id Single company by ID
GET /api/companies?industry=fintech Filter by industry (partial match)
📝 Blog Posts
10 tech blog posts with cover images. Topics include React, CSS, Git, deployment, and JavaScript.
GET /api/posts All posts
GET /api/posts/:id Single post by ID
GET /api/posts?category=react Filter by category
GET /api/posts?author=Faadumo Filter by author (partial match)
React Example — Blog Post with Cover Image
function BlogCard({ post }) {
  return (
    <article>
      <img
        src={post.coverImage}
        alt={post.title}
        style={{ width: '100%', height: '220px', objectFit: 'cover', borderRadius: '8px' }}
      />
      <h2>{post.title}</h2>
      <p>By {post.author} · {post.publishedAt}</p>
      <p>{post.content}</p>
      <p>{post.tags.map(t => `#${t}`).join(' ')}</p>
    </article>
  );
}
🎲 Random
Returns a different item every request. Great for "featured" or "job of the day" UIs.
GET /api/random/job Random job
GET /api/random/user Random user
GET /api/random/product Random product
React Example
function FeaturedJob() {
  const [job, setJob] = useState(null);

  useEffect(() => {
    fetch('/api/random/job')
      .then(r => r.json())
      .then(json => setJob(json.data));
  }, []);

  if (!job) return <p>Loading...</p>;

  return (
    <div>
      <img src={job.companyLogo} alt={job.company} width="48" />
      <h3>{job.title}</h3>
      <p>{job.company} — {job.location}</p>
    </div>
  );
}
⚛️ Full React Fetch Pattern
Copy this pattern for any endpoint. Handles loading, success, and error states.
import { useState, useEffect } from 'react';

function JobList() {
  const [jobs, setJobs] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('/api/jobs')
      .then(res => {
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return res.json();
      })
      .then(json => {
        if (json.success) setJobs(json.data);
        else setError(json.error);
      })
      .catch(err => setError(err.message))
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error)   return <p style={{ color: 'red' }}>Error: {error}</p>;

  return (
    <div style={{ display: 'grid', gap: '16px' }}>
      {jobs.map(job => (
        <div key={job.id} style={{ display: 'flex', gap: '12px' }}>
          <img src={job.companyLogo} alt={job.company} width="48" height="48" />
          <div>
            <strong>{job.title}</strong>
            <p>{job.company} · {job.location} · {job.type}</p>
            <p>{job.salary}</p>
          </div>
        </div>
      ))}
    </div>
  );
}
🖼️ Rendering Images in React
Use the image fields directly in <img> tags. All URLs are stable and load without any API key.
// User avatar (circle photo)
<img src={user.avatar} alt={user.name} style={{ borderRadius: '50%', width: '48px' }} />

// Company logo (initials badge)
<img src={company.logo} alt={company.name} style={{ borderRadius: '8px', width: '64px' }} />

// Job company logo
<img src={job.companyLogo} alt={job.company} width="40" height="40" />

// Product image (square)
<img src={product.image} alt={product.name} style={{ width: '100%', aspectRatio: '1', objectFit: 'cover' }} />

// Blog post cover (wide banner)
<img src={post.coverImage} alt={post.title} style={{ width: '100%', height: '220px', objectFit: 'cover' }} />