Python
Query the delivery API from Python with requests.
The delivery API is plain GraphQL over HTTPS, so all Python needs is requests. This guide builds a tiny client you can drop into a script, a Flask app or a data pipeline. Using Django? There's a Django guide too.
Install requests
bashpip install requestsAdd your key
Create a delivery key on your project's API page in PMKIN and export it, or put it in your
.env.bashexport PMKIN_API_KEY=your_delivery_keyWrite the client
One function that sends a query, gives up after 10 seconds and turns every failure into an exception with a clear message.
pmkin.pyimport osimport requestsENDPOINT = "https://content.pmkin.io/graphql"API_KEY = os.environ["PMKIN_API_KEY"]session = requests.Session()session.headers.update({"Authorization": f"Bearer {API_KEY}"})class PmkinError(Exception):passdef query(document: str, variables: dict | None = None) -> dict:"""Runs a GraphQL query and returns its data."""response = session.post(ENDPOINT,json={"query": document, "variables": variables or {}},timeout=10,)if response.status_code == 401:raise PmkinError("The delivery key is wrong or revoked. Check PMKIN_API_KEY.")if response.status_code == 429:raise PmkinError("Rate limited. Wait a moment and try again.")response.raise_for_status()body = response.json()if body.get("errors"):raise PmkinError(body["errors"][0]["message"])return body["data"]List documents
list_documents.pyfrom pmkin import queryDOCUMENTS = """query Documents {documents {idslugtitleexcerptpublishedAt}}"""for document in query(DOCUMENTS)["documents"]:print(f"{document['title']} → /blog/{document['slug']}")Fetch a document by slug
documentBySlugisnullwhen the slug doesn't exist or the document isn't published. That's your cue for a 404.find_document.pyfrom pmkin import queryDOCUMENT_BY_SLUG = """query DocumentBySlug($slug: String!) {documentBySlug(slug: $slug) {titlehtmlmetaTitlemetaDescription}}"""def find_document(slug: str) -> dict | None:# None when no published document has the slug.return query(DOCUMENT_BY_SLUG, {"slug": slug})["documentBySlug"]document = find_document("hello-world")if document is None:print("Not found")else:print(document["html"])
Every document, page by page#
Lists return at most 100 documents at a time. A generator walks through all of them:
from collections.abc import Iteratorfrom pmkin import queryPAGE = """query Page($limit: Int, $offset: Int) {documents(limit: $limit, offset: $offset) {idslugtitle}}"""def all_documents(page_size: int = 100) -> Iterator[dict]:offset = 0while True:documents = query(PAGE, {"limit": page_size, "offset": offset})["documents"]yield from documentsif len(documents) < page_size:returnoffset += page_size
html comes sanitized, ready to put in a page. Prefer markdown if you want to render it yourself, for example with markdown-it-py.