# Install @monok/server Set up a content endpoint, connect it to Monok, and check your first delivery. ## Install the library For Express, use Node.js 18 or newer and Express 4.18 or newer. Open API in the Monok workspace, reveal your API key, and store it as MONOK\_API\_KEY on your server. You can use the package for content, affiliate tracking, or both. Each integration can run independently. ```bash npm install @monok/server express ``` ## Mount the Express router Implement saveToCms in your own application. Persist the Monok article ID with the CMS record or queued job so repeat deliveries update the same record. The callback receives the requested action and an optional JPEG save helper. ```typescript import express from "express"; import { createMonokRouter, type MonokArticle } from "@monok/server"; import { saveToCms } from "./cms.js"; const apiKey = process.env.MONOK_API_KEY; if (!apiKey) throw new Error("MONOK_API_KEY is required"); const app = express(); app.use("/api/monok", createMonokRouter({ apiKey, imageDir: "./uploads", async onArticle(article: MonokArticle, { action = "draft", saveThumbImage }) { const imagePath = await saveThumbImage(); await saveToCms(article, { action, imagePath }); }, })); app.listen(3000); ``` In CommonJS, load Express and the router with require. The mount and callbacks work the same way. ```javascript const express = require("express"); const { createMonokRouter } = require("@monok/server"); ``` ## Use a Fetch-based runtime Use @monok/server/web in Cloudflare Workers, Astro server routes, or another Fetch runtime. It takes a standard Request, defaults to /api/monok, and passes the original article to your callback. Store images in your CMS adapter or use decodeThumbImage to validate and decode a supplied JPEG into bytes. ```typescript import { createMonokHandler, decodeThumbImage } from "@monok/server/web"; import { saveToCms } from "./cms"; export default { fetch(request: Request, env: { MONOK_API_KEY: string }) { return createMonokHandler({ apiKey: env.MONOK_API_KEY, async onArticle(article, { action }) { const imageBytes = decodeThumbImage(article); await saveToCms(article, { action, imageBytes }); }, })(request); }, }; ``` ## Connect and test 1. Check that GET /info responds with your workspace API key before adding the API destination. An invalid key should be rejected. 2. Follow Add the API integration in Publish To on the Content API overview. Send an article as a draft and check the title, body, image, and draft status in your CMS. 3. Deliver the same Monok article ID again and check that it updates the same record. Publish it, then verify that your linkback points to the public canonical URL. ## Related guides - [Content API](https://docs.monok.com/integrations/content-api) — Receive Monok articles in a custom CMS or application with the @monok/server npm package. - [Content endpoint reference](https://docs.monok.com/integrations/content-api/reference) — Understand the requests Monok sends to your content endpoint and what it expects back. - [Rotate your API key](https://docs.monok.com/rotate-api-key) — Replace a workspace API key and verify the integrations that depend on it.