TypeScript SDK
Use the pmkin npm package, with types, from any JavaScript runtime.
pmkin is a small, typed client for the delivery API. It works anywhere fetch does: Node.js 18+, Bun, Deno, edge runtimes and serverless functions. Use it for a framework we don't have a guide for, a build script, or a static site generator.
Install
npm install pmkinCreate the client
Pass a delivery key from your project's API page. Read it from an environment variable rather than putting it in your code.
pmkin.tsimport { PmkinClient } from 'pmkin'const token = process.env.PMKIN_API_KEYif (!token) {throw new Error('PMKIN_API_KEY is not set.')}export const pmkin = new PmkinClient({ token })Fetch content
index.tsimport { pmkin } from './pmkin'const documents = await pmkin.listDocuments()console.log(documents.map((document) => document.title))const document = await pmkin.findDocumentBySlug('hello-world')if (document) {console.log(document.html)}
Methods#
Every method returns a promise. Lists return published documents only, unless you ask for drafts.
listDocuments()Promise<DocumentListing[]>- Published documents, without their content.
findDocumentBySlug(slug)Promise<Document | undefined>- One document with its html and markdown, or undefined when no published document has the slug.
findDocument(id)Promise<Document | undefined>- One document by its id, or undefined.
listCategories()Promise<CategoryListing[]>- Every category in the project.
findCategory(id)Promise<Category | undefined>- One category by its id, or undefined.
listDocumentsInCategory(categoryId, includeDrafts?)Promise<DocumentListing[]>- The documents in a category. Pass
trueas the second argument to include drafts, for previews.
The types Document, DocumentListing, Category and CategoryListing are exported too. See every field in types.
Errors#
A missing document isn't an error: the find methods resolve to undefined. Everything else throws one of these classes, all exported from pmkin:
import { GraphQLError, RateLimitError, RequestError, UnauthorizedError } from 'pmkin'import { pmkin } from './pmkin'try {const document = await pmkin.findDocumentBySlug('hello-world')} catch (error) {if (error instanceof UnauthorizedError) {// The key is wrong or revoked. Create a new one on the project's API page.} else if (error instanceof RateLimitError) {// More than 25 requests a second. Wait a moment and retry, or cache more.} else if (error instanceof GraphQLError) {// The query was refused; error.message says why.} else if (error instanceof RequestError) {// The request failed, for example a network error.}throw error}
More than 100 documents#
The list methods return the first 100 documents, the API's page size. To page through more, or to pick exactly the fields you need, call the GraphQL API with fetch:
const query = `query Documents($limit: Int, $offset: Int) {documents(limit: $limit, offset: $offset) {idslugtitlepublishedAt}}`const response = await fetch('https://content.pmkin.io/graphql', {method: 'POST',headers: {Authorization: `Bearer ${process.env.PMKIN_API_KEY}`,'Content-Type': 'application/json'},body: JSON.stringify({ query, variables: { limit: 100, offset: 100 } }),// Give up after ten seconds instead of hanging.signal: AbortSignal.timeout(10_000)})if (!response.ok) {throw new Error(`PMKIN answered ${response.status}: ${await response.text()}`)}const { data, errors } = await response.json()if (errors) {throw new Error(errors[0].message)}console.log(data.documents)
The SDK doesn't time out requests itself. In a long-running server, wrap calls with your own timeout, or use fetch with AbortSignal.timeout as above. Read more in pagination and drafts.