Framework guides

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.

  1. Install

    npm install pmkin
  2. Create 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.ts
    import { PmkinClient } from 'pmkin'
    const token = process.env.PMKIN_API_KEY
    if (!token) {
    throw new Error('PMKIN_API_KEY is not set.')
    }
    export const pmkin = new PmkinClient({ token })
  3. Fetch content

    index.ts
    import { 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[]>
findDocumentBySlug(slug)Promise<Document | undefined>
findDocument(id)Promise<Document | undefined>
listCategories()Promise<CategoryListing[]>
findCategory(id)Promise<Category | undefined>
listDocumentsInCategory(categoryId, includeDrafts?)Promise<DocumentListing[]>

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:

typescript
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:

typescript
const query = `
query Documents($limit: Int, $offset: Int) {
documents(limit: $limit, offset: $offset) {
id
slug
title
publishedAt
}
}
`
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.