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
useEffect3
Call
fetch(url).then(r => r.json()) and render json.data4
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.
| Resource | Field | Provider | Example |
|---|---|---|---|
| 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> ); }
🔍 Search
Cross-resource search across jobs (title, description, skills), posts (title, content, tags), and users (name, bio, skills).
GET
/api/search?q=react
Search across jobs, posts, and users
Response shape
{
"success": true,
"query": "react",
"data": {
"jobs": [ ... ],
"posts": [ ... ],
"users": [ ... ]
}
}
React Example — Search Component
function Search() { const [q, setQ] = useState(''); const [results, setResults] = useState(null); const handleSearch = async () => { const res = await fetch(`/api/search?q=${q}`); const json = await res.json(); setResults(json.data); }; return ( <div> <input value={q} onChange={e => setQ(e.target.value)} /> <button onClick={handleSearch}>Search</button> {results && <p>{results.jobs.length} jobs found</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' }} />