API Developer Guide

Base URL: https://powerdigital.sg/api/v1/  ·  All responses are JSON  ·  UTF-8

Overview

This API powers the Power Digital CMS. Read endpoints are public (no auth). Write endpoints (create / update / delete articles and categories) require HTTP Basic Auth with the seo-agent credentials. All POST/PATCH bodies must be application/json. Dates are ISO 8601. UUIDs are used as primary keys for write operations.

Authentication

Write endpoints use HTTP Basic Auth. Encode username:password in base64 and pass it in the Authorization header. The SEO agent account is pre-provisioned on the server.

Username: seo-agent  /  Password: provided separately by the project owner.
On the server, run python manage.py create_seo_agent to provision the user.
curl — Basic Auth
# -u flag encodes username:password automatically
curl -s -u "seo-agent:<password>" \
  -X POST "https://powerdigital.sg/api/v1/articles/" \
  -H "Content-Type: application/json" \
  -d '{"title": "My Article"}'
Python — requests
import requests

AUTH = ("seo-agent", "<password>")
BASE = "https://powerdigital.sg/api/v1"

r = requests.post(f"{BASE}/articles/", json={"title": "My Article"}, auth=AUTH)
r.raise_for_status()
article = r.json()
Response on failure
# 401 — missing or wrong credentials
{"error": "Invalid credentials."}

# 409 — slug conflict
{"error": "Slug 'my-slug' already exists."}
Health
GET /api/v1/health/ public

Returns service status. Use this before any write operation to confirm the API is reachable.

curl
curl -s "https://powerdigital.sg/api/v1/health/"
response
{
  "status":  "ok",
  "service": "powerdigital-api",
  "version": "1.0"
}
Articles

Blog posts. GET endpoints are public and filterable. POST/PATCH/DELETE require seo-agent auth. The UUID returned in id is used for write operations; the slug is used for public reads.

GET /api/v1/articles/ public

List published articles. Use query params to filter.

ParamTypeDescription
statusstringFilter by status: published (default), draft, archived, all
categoryslugFilter by category slug
tagslugFilter by tag slug
searchstringFull-text search on title, slug, excerpt, content
featuredbool1 or 0
limitintPage size 1–100 (default 20)
offsetintPagination offset (default 0)
include_contentbool1 to include full HTML body
curl
curl -s "https://powerdigital.sg/api/v1/articles/?status=all&limit=10&include_content=1"
GET /api/v1/articles/<slug>/ public

Fetch a single article by slug. Always includes full content.

curl
curl -s "https://powerdigital.sg/api/v1/articles/my-article-slug/"
POST /api/v1/articles/ seo-agent

Create a new article. title is the only required field. Slug is auto-generated from title if omitted. Tags are auto-created if they don't exist. Image URLs are fetched and saved locally.

⚠ content field must be HTML — not Markdown.
The CMS renders content directly as HTML. Sending Markdown (e.g. # Heading, **bold**, - list) will appear as raw text on the page. Always convert to HTML before posting: use <h2>, <strong>, <ul><li>, <p>, etc.
request body
{
  "title":               "How to rank on Google in Singapore",  // required
  "slug":                "rank-on-google-singapore",            // optional — auto from title
  "content":             "<h2>Section Heading</h2><p>Body paragraph.</p>",  // HTML only — no Markdown
  "excerpt":             "Short summary shown in listings.",
  "status":              "published",                           // draft | published | archived
  "is_featured":         false,
  "published_at":        "2026-06-21T00:00:00Z",               // ISO 8601 — defaults to now if published
  "categories":          ["seo", "digital-marketing"],            // category slugs (must exist)
  "tags":                ["seo", "google-ranking", "singapore"],   // tag slugs — auto-created
  "meta_title":          "Rank on Google Singapore | Power Digital",
  "meta_description":    "Learn how to rank #1 on Google...",
  "meta_keywords":       ["seo singapore", "google ranking"],
  "og_title":            "Rank on Google Singapore",
  "og_description":      "Our proven SEO framework...",
  "featured_image_url":  "https://example.com/image.jpg",      // fetched + saved locally
  "long_image_url":      "https://example.com/long.jpg",
  "og_image_url":        "https://example.com/og.jpg"
}
curl
curl -s -u "seo-agent:<password>" \
  -X POST "https://powerdigital.sg/api/v1/articles/" \
  -H "Content-Type: application/json" \
  -d '{"title":"My Article","status":"published","tags":["seo"]}'

Returns 201 with the full article object including its id (UUID). Save this for PATCH/DELETE.

PATCH /api/v1/articles/<uuid>/ seo-agent

Partial update — only send the fields you want to change. Use the id UUID from the create response.

curl
ARTICLE_ID="839fd4bd-36d3-4b5a-aee8-a389998f787f"

curl -s -u "seo-agent:<password>" \
  -X PATCH "https://powerdigital.sg/api/v1/articles/${ARTICLE_ID}/" \
  -H "Content-Type: application/json" \
  -d '{"status":"published","is_featured":true}'
DELETE /api/v1/articles/<uuid>/ seo-agent

Permanently delete an article. Returns {"deleted": true, "id": "..."}.

curl
curl -s -u "seo-agent:<password>" \
  -X DELETE "https://powerdigital.sg/api/v1/articles/${ARTICLE_ID}/"
Categories

Article categories with optional parent/child hierarchy and featured image.

GET /api/v1/categories/ public
ParamDescription
parent=rootOnly top-level categories (no parent)
parent=<slug>Children of a specific category
searchSearch name, slug, description
include_content=1Include full content field
curl -s "https://powerdigital.sg/api/v1/categories/?parent=root"
GET /api/v1/categories/<slug>/ public

Returns the category plus its children and a list of articles in that category.

curl -s "https://powerdigital.sg/api/v1/categories/seo/?article_limit=5"
POST /api/v1/categories/ seo-agent
request body
{
  "name":                "SEO",                              // required
  "slug":                "seo",                              // optional — auto from name
  "description":         "Search engine optimisation articles.",
  "excerpt":             "Short listing summary.",
  "content":             "<p>Long HTML description.</p>",
  "parent":              "digital-marketing",               // parent category slug
  "featured_image_url":  "https://example.com/seo.jpg",     // fetched + saved locally
  "meta_title":          "SEO Articles | Power Digital",
  "meta_description":    "Expert SEO tips and strategies.",
  "meta_keywords":       ["seo", "search engine optimisation"]
}
curl
curl -s -u "seo-agent:<password>" \
  -X POST "https://powerdigital.sg/api/v1/categories/" \
  -H "Content-Type: application/json" \
  -d '{"name":"SEO","description":"SEO articles"}'
PATCH /api/v1/categories/<uuid>/ seo-agent

Partial update. Same fields as POST, all optional. Use UUID from create response.

DELETE /api/v1/categories/<uuid>/ seo-agent

Delete a category. Articles in this category lose the category association (M2M).

Bookings
GET /api/v1/bookings/available-slots/ public

Returns available time slots for a given date.

curl -s "https://powerdigital.sg/api/v1/bookings/available-slots/?date=2026-07-01"
POST /api/v1/bookings/ public
{
  "full_name":  "Jane Smith",
  "email":      "jane@example.com",
  "phone":      "+65 9123 4567",
  "date":       "2026-07-01",
  "start_time": "10:00",
  "message":    "Looking for SEO services."
}
Pages
GET /api/v1/pages/ public

CMS pages. Params: status, search, limit, offset, include_content.

GET /api/v1/pages/<slug>/ public

Single page with full block data.

Blocks
GET /api/v1/blocks/ public

CMS content blocks. Params: type, active, include_data=1.

curl -s "https://powerdigital.sg/api/v1/blocks/?type=home_hero&include_data=1"
SEO
POST /api/v1/seo/generate/ public

Generate SEO suggestions for a given content snippet.

{
  "content": "Your page content here..."
}
Article Fields Reference
FieldTypeRequiredNotes
titlestringrequiredMax 255 chars
slugstringoptionalAuto-generated from title. Must be unique.
contentHTML stringoptionalHTML only. Rendered directly — Markdown is not parsed. Use <h2>/<p>/<ul> etc.
excerptstringoptionalPlain-text summary for listings (no HTML needed).
statusenumoptionaldraft (default) · published · archived
typeenumoptionalpost (default) · page
is_featuredbooloptionalPinned to top of blog listing.
published_atISO 8601optionalDefaults to now when status = published.
categoriesslug[]optionalArray of existing category slugs.
tagsslug[]optionalArray of tag slugs. Auto-created if not found.
meta_titlestringoptionalOverride <title> tag.
meta_descriptionstringoptional<meta name="description">
meta_keywordsstring[]optionalArray of keyword strings.
og_titlestringoptionalOpen Graph title override.
og_descriptionstringoptionalOpen Graph description override.
featured_image_urlURLoptionalRemote image — fetched and saved locally (10 MB cap).
long_image_urlURLoptionalTall format image for listings.
og_image_urlURLoptionalSocial share image.
Category Fields Reference
FieldTypeRequiredNotes
namestringrequiredMax 100 chars
slugstringoptionalAuto-generated from name. Must be unique.
descriptionstringoptionalPlain text description.
excerptstringoptionalShort listing text.
contentHTML stringoptionalLong-form HTML description.
parentslugoptionalParent category slug. Omit for top-level.
featured_image_urlURLoptionalRemote image — fetched and saved locally.
meta_titlestringoptional
meta_descriptionstringoptional
meta_keywordsstring[]optional
Service Cluster Tags

Each service page automatically shows articles whose tags match its cluster list. Tag your articles with these slugs to have them appear on the relevant service page.

ServiceURLTags to use on articles
Web Development /services/web-development-singapore/ web-development · web-design · website-design-singapore · performance-optimisation · ecommerce · cms
Web Applications /services/web-application-development/ web-application · saas · platform-development · custom-software · django · nodejs
Mobile Apps /services/mobile-application-development/ mobile-app · flutter · ios-development · android-development · react-native · mobile-development
3D Development /services/3d-development/ 3d-development · webgl · unity · virtual-reality · augmented-reality · immersive
Game Development /services/game-development/ game-development · mobile-games · unity-game · gamification · educational-games
SEO /services/seo/ seo · digital-marketing · search-engine-optimisation · content-strategy · keyword-research · link-building
Example — create article that clusters on the SEO service page
curl -s -u "seo-agent:<password>" \
  -X POST "https://powerdigital.sg/api/v1/articles/" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "10 SEO Tips for Singapore Businesses",
    "status": "published",
    "tags": ["seo", "digital-marketing", "keyword-research"],
    "categories": ["seo"],
    "meta_description": "Proven SEO strategies for Singapore SMEs."
  }'

This article will automatically appear in the "Further Resources" section at the bottom of /services/seo/ once it is published.