MemehCMS Public API Guide
Developer reference for building public websites, mobile apps, portals, dashboards, and Web Engine templates on top of MemehCMS.
MemehCMS Public API Guide
MemehCMS is headless-first. Public websites, portals, mobile apps, and Web Engine templates should read published content through the public API instead of scraping admin pages.
The API is tenant-scoped. Always send the institution tenant ID when building a public website.
Base URL
Use the MemehCMS application URL plus /api.
Example:
https://memehcms.com/api
For local development:
http://127.0.0.1:8000/api
Tenant Scope
Most public endpoints accept:
?tenant_id=<institution-uuid>
Example:
GET /api/articles?tenant_id=55c10ff5-fa35-4058-acfc-0e6f14df2b32
Do not hardcode another institution's tenant ID into a website. Each website should use the tenant ID from its own configuration.
Authentication
Public website endpoints do not require authentication for published content.
Authenticated users who belong to a tenant may preview drafts through selected endpoints when the request is made in an authenticated context. Public websites should normally request published content only.
Rate Limits
Public API endpoints are protected by the platform public API rate limit.
Developers should:
- Cache public responses where appropriate.
- Avoid polling too frequently.
- Use pagination.
- Avoid loading every module on every page.
- Handle HTTP
429gracefully.
Standard Query Parameters
Common parameters:
| Parameter | Purpose |
|---|---|
tenant_id |
Institution UUID. Strongly recommended for all public websites. |
page |
Pagination page number. |
per_page |
Items per page. Capped by the API. |
status |
Usually published; draft preview is allowed only for authorized tenant users. |
include |
Comma-separated related resources allowed by the endpoint. |
sort_field |
Sort field where supported. |
sort_dir |
asc or desc where supported. |
Standard Pagination Shape
List endpoints usually return:
{
"data": [],
"meta": {
"current_page": 1,
"per_page": 20,
"total": 0,
"last_page": 1
},
"links": {
"next": null,
"prev": null
}
}
Articles
Use articles for news, posts, speeches, press releases, and public updates.
List:
GET /api/articles?tenant_id=<uuid>&per_page=10&sort_field=published_at&sort_dir=desc
Show:
GET /api/articles/{id-or-slug}?tenant_id=<uuid>
Useful includes:
include=category,tags,featureImage,tenant
Example:
const url = `${API_BASE}/articles?tenant_id=${TENANT_ID}&include=category,featureImage&per_page=6`;
const res = await fetch(url);
if (!res.ok) throw new Error(`Articles failed: ${res.status}`);
const payload = await res.json();
Production note: the article API is used by live public websites. Do not assume draft content is available unless the viewer is authenticated and allowed to preview that tenant.
Categories
Use categories to group articles.
GET /api/categories?tenant_id=<uuid>
Category slugs are tenant-safe in the admin system so two institutions can both use names such as News or Press Releases.
Pages
Use pages for static public website pages.
List:
GET /api/pages?tenant_id=<uuid>
Show:
GET /api/pages/{id-or-slug}?tenant_id=<uuid>
Pages may include page-builder data, metadata, feature media, and body content depending on how the page was created.
Services And Products
Use services for public services, products, fees, application flows, and portal CTAs.
List:
GET /api/services?tenant_id=<uuid>&per_page=20
Show:
GET /api/services/{id-or-slug}?tenant_id=<uuid>
Service payloads may include title, slug, summary, body, fee, CTA label, CTA URL, department, and status.
Website rule: if a service has a CTA, render it as a clear button such as Apply, Pay, Book Appointment, Contact Office, or Learn More.
Departments
Use departments for organizational units, divisions, commands, directorates, and public structure.
GET /api/departments?tenant_id=<uuid>
Departments can power menu mega-dropdowns, directory pages, service filters, and staff pages.
Locations
Use locations for offices, stations, headquarters, regional branches, and service points.
List:
GET /api/locations?tenant_id=<uuid>
Show:
GET /api/locations/{id-or-slug}?tenant_id=<uuid>
Leadership
Use leadership for profiles and organogram-driven public pages.
List:
GET /api/leadership?tenant_id=<uuid>
Show:
GET /api/leadership/{id-or-slug}?tenant_id=<uuid>
Leadership photos should come from managed media where available.
Sliders
Use sliders for homepage or section hero slides.
List:
GET /api/sliders?tenant_id=<uuid>&include=image
Show:
GET /api/sliders/{id-or-slug}?tenant_id=<uuid>&include=image
Render only published slides on public websites. Respect sort order.
Media
Use media to retrieve managed files attached to content.
GET /api/media?tenant_id=<uuid>
Media payloads include URLs where possible. Do not expose private admin storage paths directly in a public website.
Publications
Use publications for official reports and PDF libraries.
GET /api/publications?tenant_id=<uuid>
Publications should link to managed media files when available.
Records, Laws, Policies, And Forms
Use library items for laws, policies, forms, manuals, templates, guidelines, circulars, and public records.
List:
GET /api/library-items?tenant_id=<uuid>
Show:
GET /api/library-items/{id-or-slug}?tenant_id=<uuid>
Public Notices
Use notices for formal notices and public advisories that are not standard articles.
GET /api/notices?tenant_id=<uuid>
Emergency Alerts
Use alerts for urgent public safety information.
List:
GET /api/emergency-alerts?tenant_id=<uuid>
Show:
GET /api/emergency-alerts/{id-or-slug}?tenant_id=<uuid>
Public websites should make active urgent alerts visible without requiring users to search.
FAQs
Use FAQs for help-centre content.
List:
GET /api/faqs?tenant_id=<uuid>
Show:
GET /api/faqs/{id-or-slug}?tenant_id=<uuid>
Jobs
Use jobs for recruitment notices.
GET /api/jobs?tenant_id=<uuid>
Render closing dates clearly.
Events
Use events for calendars, programmes, workshops, ceremonies, and public deadlines.
GET /api/events?tenant_id=<uuid>
Menus
Use menus to build website navigation.
Menu list:
GET /api/menus?tenant_id=<uuid>
Menu items:
GET /api/menus/{menuId}/items?tenant_id=<uuid>
Menus with items:
GET /api/menus-with-items?tenant_id=<uuid>
Menu locations:
GET /api/menu-locations?tenant_id=<uuid>
Menu by location:
GET /api/menus/by-location/{key}?tenant_id=<uuid>
Common locations include header, footer, services, publications, and other website-defined locations.
Accessibility Settings
Use accessibility settings to configure public website controls.
GET /api/accessibility-settings?tenant_id=<uuid>
Public websites should use these settings for language readiness, skip links, statement URLs, and related controls.
PHP Example
<?php
$apiBase = 'https://memehcms.com/api';
$tenantId = '55c10ff5-fa35-4058-acfc-0e6f14df2b32';
$url = $apiBase.'/articles?'.http_build_query([
'tenant_id' => $tenantId,
'include' => 'category,featureImage',
'per_page' => 6,
]);
$json = file_get_contents($url);
$payload = json_decode($json, true);
$articles = $payload['data'] ?? [];
JavaScript Example
async function apiGet(path, params = {}) {
const url = new URL(`https://memehcms.com/api/${path}`);
url.searchParams.set('tenant_id', '55c10ff5-fa35-4058-acfc-0e6f14df2b32');
for (const [key, value] of Object.entries(params)) {
if (value !== undefined && value !== null && value !== '') {
url.searchParams.set(key, value);
}
}
const response = await fetch(url);
if (!response.ok) {
throw new Error(`MemehCMS API failed with ${response.status}`);
}
return response.json();
}
const articles = await apiGet('articles', {
include: 'category,featureImage',
per_page: 6,
});
Website Builder And Web Engine
The Web Engine starter kit stores API configuration in one place. Do not scatter tenant IDs across templates.
Recommended configuration:
MEMEH_API_BASE=https://memehcms.com/api
MEMEH_TENANT_ID=<institution-uuid>
Use service classes or ViewModels to normalize API payloads before rendering HTML.
Error Handling
Developers should handle:
200: success.404: content not found, wrong slug, missing tenant, unpublished record, or invalid preview access.403: authenticated user lacks access where auth is used.422: invalid request data where applicable.429: rate limit.500: server error, log and show a graceful fallback.
Public websites should never display raw exception messages.
Security Rules For Developers
- Keep admin credentials out of public websites.
- Store tenant ID and API base in config.
- Escape rendered text.
- Sanitize or trust only server-sanitized HTML fields.
- Do not render scripts from imported WordPress content.
- Cache public API responses responsibly.
- Use HTTPS.
- Keep contact forms rate-limited and CSRF-protected.
- Do not expose private case or admin data.
Release Checklist For Public Websites
Before launch:
- Confirm the tenant ID.
- Confirm menus load.
- Confirm articles load.
- Confirm pages load.
- Confirm services and CTAs work.
- Confirm publications and media files open.
- Confirm mobile navigation.
- Confirm alerts display correctly.
- Confirm empty states do not break layout.
- Confirm HTTPS and security headers.