Server technologies

Python

Read release-pinned content from Python with the standard library.

PeopleTide Content · HTTP integration guides

1. Prepare your project.

Use Python 3.11+. Export CONTENT_ORIGIN, CONTENT_ORGANIZATION_ID, and CONTENT_SITE_ID in your process environment. No pip package is needed. Save this self-contained example as content_delivery.py.

Connect and render.

Publish an article of type article with slug welcome and a body field before running the example. Split the labelled files into the paths shown.

Python
# content_delivery.py — Python 3.11+, standard library only
import json, os
from urllib.request import urlopen
from urllib.parse import urljoin, urlsplit
from http.server import BaseHTTPRequestHandler, HTTPServer

ORIGIN = os.environ.get('CONTENT_ORIGIN', 'https://content.peopletide.com')
PREFIX = '/delivery/v1/' + os.environ['CONTENT_ORGANIZATION_ID'] + '/' + os.environ['CONTENT_SITE_ID'] + '/'

def read(path):
    url = urljoin(ORIGIN, path)
    parsed, base = urlsplit(url), urlsplit(ORIGIN)
    if (parsed.scheme, parsed.netloc) != (base.scheme, base.netloc) or not parsed.path.startswith(PREFIX):
        raise ValueError('Unexpected delivery URL')
    with urlopen(url, timeout=8) as response:
        return json.load(response)

def article(slug):
    current = read(PREFIX + 'current.json')
    manifest = read(current['url'])
    entry = next((e for e in manifest['entries'] if e['type'] == 'article' and e['slug'] == slug), None)
    return {'releaseId': current['releaseId'], 'document': read(entry['url'])} if entry else None

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            result = article('welcome')
            status = 200 if result else 404
            body = result or {'error': 'Article not published'}
        except Exception:
            status, body = 503, {'error': 'Content temporarily unavailable'}
        self.send_response(status)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(body).encode())

if __name__ == '__main__':
    HTTPServer(('127.0.0.1', 3000), Handler).serve_forever()

Choose when content refreshes.

The demonstration server fetches per request and returns JSON. Use a production WSGI/ASGI server for a deployed application. Cache immutable URLs separately from a discovery pointer with at most a 30-second freshness window.

Verify success and failure.

Run python3 content_delivery.py and open http://127.0.0.1:3000. Check the releaseId and title. Change the welcome slug in the handler to an unknown slug to exercise 404; stop delivery to exercise 503. Use an escaping template engine when rendering HTML.