pagekit-core
Python client for the PageKit content API.
Sync and async support, fully typed, and production-ready.
Installation
pip install pagekit-core
# or
poetry add pagekit-core
# or
uv pip install pagekit-core
Requires: Python >= 3.10
Quick Start
from pagekit import Pagekit
client = Pagekit(api_key="pk_live_...")
# List posts
page = client.posts.list(status="published", limit=10)
for post in page.data:
print(post.title)
# Get a post by slug
post = client.posts.get_by_slug("hello-world")
# Create a post
post = client.posts.create(
title="Hello world",
content="<p>First post</p>",
status="published",
)
# Update a post
updated = client.posts.update("post-id", title="Updated title")
# Delete a post
client.posts.delete("post-id")
Async Support
The client provides full async support with AsyncPagekit:
from pagekit import AsyncPagekit
client = AsyncPagekit(api_key="pk_live_...")
# List posts
page = await client.posts.list(status="published")
# Get by slug
post = await client.posts.get_by_slug("hello-world")
# Create a post
post = await client.posts.create(
title="Hello world",
content="<p>First post</p>",
)
# Update
updated = await client.posts.update("post-id", title="Updated")
# Delete
await client.posts.delete("post-id")
Configuration
from pagekit import Pagekit
client = Pagekit(
api_key="pk_live_...", # Required
base_url="https://api.pagekit.cc/v1", # Optional, default shown
timeout=30, # Optional, seconds
headers={"X-Custom-Header": "value"}, # Optional
)
Configuration Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
api_key |
str |
Yes | — | Your PageKit API key |
base_url |
str |
No | https://api.pagekit.cc/v1 |
API base URL |
timeout |
float |
No | 30 |
Request timeout in seconds |
headers |
dict |
No | {} |
Additional headers for all requests |
API Reference
Posts
client.posts.list(params?)
List posts with pagination and filtering.
page = client.posts.list(
status="published", # "published" | "draft"
sort="-published_at", # Sort by field, prefix with "-" for descending
page=1, # Page number
limit=20, # Items per page
author="author-id", # Filter by author
tag="engineering", # Filter by tag
category="tutorials", # Filter by category
search="nextjs", # Full-text search
)
for post in page.data:
print(post.title)
Returns: Paginated[Post]
client.posts.get(post_id)
Get a single post by ID.
post = client.posts.get("post-id")
print(post.title, post.content)
Returns: Post
client.posts.get_by_slug(slug)
Get a single post by slug.
post = client.posts.get_by_slug("my-first-post")
Returns: Post
client.posts.create(input)
Create a new post.
post = client.posts.create(
title="My Post",
content="# Title\n\nContent...",
status="published",
excerpt="A short summary",
slug="my-post",
author="author-id",
tags=["tag-id-1", "tag-id-2"],
categories=["category-id"],
seo={
"title": "Custom SEO Title",
"description": "Custom description",
},
)
Returns: Post
client.posts.update(post_id, input)
Update an existing post. Only include fields you want to change.
updated = client.posts.update(
"post-id",
title="Updated Title",
status="draft",
)
Returns: Post
client.posts.delete(post_id)
Delete a post permanently.
client.posts.delete("post-id")
Returns: None
Authors
client.authors.list(params?)
List all authors.
page = client.authors.list()
for author in page.data:
print(author.name)
Returns: Paginated[Author]
client.authors.get(author_id)
Get a single author by ID.
author = client.authors.get("author-id")
Returns: Author
Categories
client.categories.list(params?)
List all categories.
page = client.categories.list()
for category in page.data:
print(category.name)
Returns: Paginated[Category]
client.categories.get_by_slug(slug)
Get a single category by slug.
category = client.categories.get_by_slug("engineering")
Returns: Category
Tags
client.tags.list(params?)
List all tags.
page = client.tags.list()
for tag in page.data:
print(tag.name)
Returns: Paginated[Tag]
Media
client.media.list(params?)
List all media assets.
page = client.media.list()
for asset in page.data:
print(asset.filename, asset.url)
Returns: Paginated[Media]
client.media.create(input)
Register a new media asset.
media = client.media.create(
url="https://example.com/image.png",
filename="image.png",
mime_type="image/png",
size=1024,
alt="Descriptive alt text",
)
Returns: Media
client.media.delete(media_id)
Delete a media asset.
client.media.delete("media-id")
Returns: None
Types
The client uses Pydantic models for all data types:
from pagekit import Post, Author, Category, Tag, Media
# All models are accessible for type hints
def process_post(post: Post) -> None:
print(post.title, post.status)
Error Handling
from pagekit import Pagekit, PagekitError
client = Pagekit(api_key="pk_live_...")
try:
post = client.posts.get("nonexistent-id")
except PagekitError as e:
print(e.status) # 404
print(e.code) # "not_found"
print(e.message) # Human-readable message
# Convenience properties
if e.is_auth_error:
print("Invalid API key (401/403)")
if e.is_rate_limited:
print("Rate limited — retry after delay (429)")
if e.is_server_error:
print("Server error — safe to retry (5xx)")
Error Properties
| Property | Type | Description |
|---|---|---|
status |
int |
HTTP status code |
code |
str |
Machine-readable error code |
message |
str |
Human-readable error message |
is_auth_error |
bool |
True for 401/403 errors |
is_rate_limited |
bool |
True for 429 errors |
is_server_error |
bool |
True for 5xx errors |
Framework Integrations
FastAPI
from fastapi import FastAPI, Depends
from pagekit import Pagekit, AsyncPagekit
app = FastAPI()
def get_pagekit():
return AsyncPagekit(api_key="pk_live_...")
@app.get("/posts")
async def list_posts(pagekit: AsyncPagekit = Depends(get_pagekit)):
posts = await pagekit.posts.list(status="published")
return posts.data
@app.get("/posts/{slug}")
async def get_post(slug: str, pagekit: AsyncPagekit = Depends(get_pagekit)):
post = await pagekit.posts.get_by_slug(slug)
return post
Django
# views.py
from django.http import JsonResponse
from pagekit import Pagekit
client = Pagekit(api_key="pk_live_...")
def blog_list(request):
page = client.posts.list(status="published")
return JsonResponse({"posts": [p.model_dump() for p in page.data]})
Flask
from flask import Flask, jsonify
from pagekit import Pagekit
app = Flask(__name__)
client = Pagekit(api_key="pk_live_...")
@app.route("/api/posts")
def posts():
page = client.posts.list(status="published")
return jsonify([p.model_dump() for p in page.data])
Development
# Create virtual environment
python -m venv .venv
source .venv/bin/activate
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=src/pagekit
# Type check (requires mypy)
mypy src
# Format code (requires black)
black src tests
Supported Python Versions
- Python 3.10
- Python 3.11
- Python 3.12
- Python 3.13
Related Packages
- @arovi/pagekit-core — TypeScript SDK
- @arovi/pagekit-mcp — MCP server for AI agents
- @arovi/pagekit-next — Next.js integration
- @arovi/pagekit-cli — CLI tooling
License
MIT © Arovi Labs
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pagekit_core-0.1.1.tar.gz.
File metadata
- Download URL: pagekit_core-0.1.1.tar.gz
- Upload date:
- Size: 9.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3cde92c7101bf485d32c0373ee12e342c9268b57c3b79d75c79e9a5b6dadac67
|
|
| MD5 |
909f849bb5fee3cc3925a60db4a42685
|
|
| BLAKE2b-256 |
fa847659fed1df977fba59ba0451cb5bd11c752650b57c4ac2ba3ebd8c79afcd
|
File details
Details for the file pagekit_core-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pagekit_core-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0daad762f599121411e50b923046053d2aeb401b44e64060bdb66185161b9892
|
|
| MD5 |
53d450d251d6099a93f074b1f6494a58
|
|
| BLAKE2b-256 |
c6dd7a99d67307761884cc7d54bda7ad379fc47e423629f506a1f646efbf9ff9
|