Skip to main content

PyPI version License Python versions

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


client.authors.get_by_slug(slug)

Get a single author by slug.

author = client.authors.get_by_slug("jane-doe")

Returns: Author


client.authors.create(input)

Create an author profile.

from pagekit import AuthorCreateInput

author = client.authors.create(AuthorCreateInput(name="Jane Doe", bio="Editor"))

Returns: Author


client.authors.update(author_id, input)

Update an author profile.

from pagekit import AuthorUpdateInput

author = client.authors.update("author-id", AuthorUpdateInput(bio="Senior editor"))

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


License

MIT © Arovi Labs

Metadata

Release files for pagekit-core 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pagekit-core 0.1.2
File Size Uploaded
pagekit_core-0.1.2.tar.gz 9.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pagekit-core 0.1.2
File Interpreter ABI Platform
pagekit_core-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 21.6 kB

Release files / pagekit_core-0.1.2.tar.gz

Download URL pagekit_core-0.1.2.tar.gz
Size 9.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5d8334c3540f6fc0d828d620468a0d239c511bd5b0cfb7619605b35499bc5df3
BLAKE2b-256 checksum
How to use checksums
7ffa5fe11a6402ab7e97a7df1822dd3a144a357d6a27f9d20f6c1d526a332678
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / pagekit_core-0.1.2-py3-none-any.whl

Download URL pagekit_core-0.1.2-py3-none-any.whl
Size 11.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
59ac159e79023e1f52dbbe63d1121d7b9161c9fdba03b0c16dc44746bbe056ec
BLAKE2b-256 checksum
How to use checksums
60c99839c192b84a4324fcc9fe92617f733cccba6f85dc82a866b9245f153e99
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page