Dit artikel verzamelt kant-en-klare Notiondesk API-scripts voor de taken die teams het meest automatiseren: Notion-bewerkingen publiceren vanuit een CI-pipeline, van elk artikel een Markdown-back-up maken, negatieve feedback naar Slack sturen, zoekopdrachten rapporteren die uw helpcentrum niet kan beantwoorden, mislukte synchronisaties vinden en één merk toepassen op meerdere helpcentra. Kopieer een recept, stel twee omgevingsvariabelen in en voer het uit.
Voordat je begint
- Maak een API-sleutel aan met alleen de scopes die het recept nodig heeft. Elk recept benoemt deze scopes. Zie Authentiseren met de Notiondesk API met behulp van API-sleutels .
- Vind de helpcenters van uw
idmetGET /sites. Zie Uw helpcenters lezen met de Notiondesk API .
- Stel beide in als omgevingsvariabelen:
export NOTIONDESK_API_KEY="nd_wsk_..."
export NOTIONDESK_SITE_ID="c74781f6-1aea-4e17-ab23-bbb8b4d174b6"Voor de JavaScript-recepten is Node.js versie 18 of hoger vereist.
Een kleine, gedeelde helper
Sla dit bestand op als notiondesk.mjs naast je scripts. Het verstuurt de headers, wacht tot de API antwoordt met 429 rate_limited en leest vervolgens elke pagina van een lijst.
Synchroniseer je helpcentrum vanuit GitHub Actions.
Omvang: __GERESERVEERD_30__
Publiceer je Notion-bewerkingen vanuit een GitHub Actions-workflow, bijvoorbeeld direct na een release. Sla de sleutel op als het repositorygeheim NOTIONDESK_API_KEY en de helpcentrum-ID als de repositoryvariabele NOTIONDESK_SITE_ID.
export const SITE_ID = process.env.NOTIONDESK_SITE_ID;
export async function api(path, options = {}) {
for (let attempt = 0; attempt < 5; attempt++) {
const response = await fetch(`https://api.notiondesk.so${path}`, {
...options,
headers: {
Authorization: `Bearer ${process.env.NOTIONDESK_API_KEY}`,
"nd-version": "2026-10-16",
...options.headers,
},
});
if (response.status === 429) {
const seconds = Number(response.headers.get("Retry-After")) || 5;
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
continue;
}
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`);
}
return response.status === 204 ? null : response.json();
}
throw new Error(`Still rate limited on ${path}`);
}
export async function listAll(path) {
const items = [];
let cursor = null;
do {
const url = new URL(`https://api.notiondesk.so${path}`);
url.searchParams.set("page_size", "100");
if (cursor) {
url.searchParams.set("cursor", cursor);
}
const page = await api(`${url.pathname}${url.search}`);
items.push(...page.data);
cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
return items;
}name: Sync help center
on:
workflow_dispatch:
release:
types: [published]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Trigger a Notiondesk sync
run: |
status=$(curl -s -o response.json -w "%{http_code}" -X POST \
"https://api.notiondesk.so/sites/${{ vars.NOTIONDESK_SITE_ID }}/sync" \
-H "Authorization: Bearer ${{ secrets.NOTIONDESK_API_KEY }}" \
-H "nd-version: 2026-10-16" \
-H "Idempotency-Key: github-${{ github.run_id }}-${{ github.run_attempt }}")
if [ "$status" = "409" ]; then echo "A sync is already running."; exit 0; fi
if [ "$status" != "204" ]; then cat response.json; exit 1; fi
echo "Sync queued."204betekent dat de synchronisatie in de wachtrij staat. Deze wordt op de achtergrond uitgevoerd.
409 conflict_errorbetekent dat er al een synchronisatie van het helpcentrum in de wachtrij staat of bezig is, waardoor de stap succesvol is en er geen nieuwe hoeft te worden gestart.
- De
Idempotency-Keyzorgt ervoor dat een verzoek in de wachtrij twee keer wordt herhaald.
Maak van elk artikel een back-up als markdown.
Bereik: __GEVESTIGD_24__
Sla elk artikel, in elke taal die uw helpcentrum ondersteunt, op als een Markdown-bestand:
De back-up bevat concepten en gearchiveerde artikelen. Het aantal leesverzoeken is beperkt tot 120 per minuut, dus een helpcentrum met 500 artikelen duurt ongeveer vijf minuten per taal; de helpdesk wacht automatisch wanneer de limiet is bereikt.
Stuur elke dag negatieve feedback naar Slack.
Bereik: alleen __GERESERVEERD_23__
Plaats de negatieve feedback van de afgelopen 24 uur in een Slack-kanaal via een inkomende webhook . Stel SLACK_WEBHOOK_URL in en voer het script vervolgens eenmaal per dag uit.
De feedbacklijst is gesorteerd op nieuwste, dus het script stopt met pagineren bij de eerste vermelding die ouder is dan 24 uur.
import { mkdir, writeFile } from "node:fs/promises";
import { api, listAll, SITE_ID } from "./notiondesk.mjs";
const site = await api(`/sites/${SITE_ID}`);
for (const locale of site.supported_locales) {
await mkdir(`backup/${locale}`, { recursive: true });
const articles = await listAll(`/sites/${SITE_ID}/articles?locale=${locale}`);
for (const article of articles) {
const full = await api(`/sites/${SITE_ID}/articles/${encodeURIComponent(article.id)}?locale=${locale}`);
const frontMatter = `---\ntitle: ${JSON.stringify(full.title ?? "")}\nstatus: ${full.status}\nurl: ${full.url ?? ""}\n---\n\n`;
await writeFile(`backup/${locale}/${encodeURIComponent(article.id)}.md`, frontMatter + full.text);
if (full.truncated) {
console.warn(`${locale}/${article.id} is longer than 200,000 bytes and was truncated`);
}
}
console.log(`${locale}: ${articles.length} articles saved`);
}import { api, SITE_ID } from "./notiondesk.mjs";
const since = Date.now() - 24 * 60 * 60 * 1000;
const escapeSlack = (text) => (text ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
async function feedbackSince(timestamp) {
const entries = [];
let cursor = null;
do {
const query = new URLSearchParams({ page_size: "100" });
if (cursor) {
query.set("cursor", cursor);
}
const page = await api(`/sites/${SITE_ID}/feedback?${query}`);
const recent = page.data.filter((entry) => Date.parse(entry.submitted_at) >= timestamp);
entries.push(...recent);
cursor = page.has_more && recent.length === page.data.length ? page.next_cursor : null;
} while (cursor);
return entries;
}
const negative = (await feedbackSince(since)).filter(
(entry) => entry.reaction_group === "negative" || entry.reaction_group === "not_helpful",
);
if (negative.length > 0) {
const lines = negative.map(
(entry) => `• *${escapeSlack(entry.article_title)}* (${entry.article_locale}): ${escapeSlack(entry.message) || "_no message_"}`,
);
await fetch(process.env.SLACK_WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: `${negative.length} negative feedback in the last 24 hours\n${lines.join("\n")}` }),
});
}readRapporteer zoekopdrachten zonder resultaten elke week
Omvang: __GERESERVEERD_20__
Maak een lijst van de zoektermen die lezers vorige week gebruikten zonder een artikel te vinden. Elke zoekterm komt in aanmerking voor een nieuw artikel of een betere titel.
Elke querylijst kan maximaal 50 rijen bevatten. Analyserapporten delen ook een budget van 30 aanvragen per minuut per helpcentrum. Zie Helpcentrumanalyses verkrijgen met de Notiondesk API .
Zoek naar artikelen waarvan de laatste synchronisatie is mislukt.
Bereik: read, plus sync om opnieuw te proberen
Corrigeer elk artikel eerst in Notion en synchroniseer het vervolgens opnieuw met POST /sites/{site_id}/articles/{article_id}/sync.
Gebruik één merk voor elk helpcentrum.
Bereik: __GERESERVEERD_16__ en __GERESERVEERD_15__
Kopieer de kleuren en lettertypen van één helpcentrum naar alle andere helpcentra in uw werkruimte. Stel SOURCE_SITE_ID in op het helpcentrum waarvan u wilt kopiëren.
Elke brandingupdate vernieuwt het volledige doelhelpcentrum, dus het script verstuurt één verzoek per helpcentrum. Een kleur die is opgeslagen in een verkorte vorm zoals #fff wordt afgewezen: corrigeer dit eerst in het dashboard van het bronhelpcentrum. Zie Branding en thema's van helpcentra aanpassen met de Notiondesk API .
Importeer omleidingen na een migratie
Bereik: read en write
Stapt u over van een andere helpcentrumtool? Het importscript voor redirects leest een CSV-bestand met oude paden en maakt één redirect per regel aan. Zie Pagina-redirects beheren met de Notiondesk API .
import { api, SITE_ID } from "./notiondesk.mjs";
const end = new Date();
end.setUTCHours(0, 0, 0, 0);
const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000);
const toApiDate = (date) => `${date.toISOString().slice(0, 19)}Z`;
const query = new URLSearchParams({
start_date: toApiDate(start),
end_date: toApiDate(end),
date_scale: "day",
});
const report = await api(`/sites/${SITE_ID}/analytics/search?${query}`);
console.log(`Searches: ${report.searches.total} (${report.searches.percentage_difference}% vs previous week)`);
console.log(`Without results: ${report.searches_without_results.total}`);
console.log(`Click-through rate: ${report.click_through_rate.current.toFixed(1)}%`);
for (const { query: text, searches } of report.searches_without_results.queries) {
console.log(`${searches}\t${text}`);
}import { api, listAll, SITE_ID } from "./notiondesk.mjs";
const articles = await listAll(`/sites/${SITE_ID}/articles`);
const failed = articles.filter((article) => article.sync_failed || article.sync_timeout);
for (const article of failed) {
const reason = article.sync_timeout ? "timed out" : article.sync_error_code ?? "failed";
console.log(`${article.title}: ${reason} ${article.notion_article_page_url ?? ""}`);
}import { createHash } from "node:crypto";
import { api, listAll } from "./notiondesk.mjs";
const sourceId = process.env.SOURCE_SITE_ID;
const { colors, primary_font, secondary_font } = await api(`/sites/${sourceId}/settings/customize`);
const body = JSON.stringify({ colors, primary_font, secondary_font });
const bodyHash = createHash("sha256").update(body).digest("hex");
const sites = await listAll("/sites");
for (const site of sites.filter((candidate) => candidate.id !== sourceId)) {
await api(`/sites/${site.id}/settings/customize`, {
method: "PATCH",
headers: { "Content-Type": "application/json", "Idempotency-Key": `brand-${site.id}-${bodyHash}` },
body,
});
console.log(`Updated ${site.full_domain}`);
}Veelgestelde vragen
Welke taal kan ik gebruiken met de Notiondesk API?
Elke programmeertaal die HTTPS-verzoeken kan verzenden, is geschikt. De API is een eenvoudige REST-applicatie met JSON, dus JavaScript, Python, PHP, Go en Ruby werken allemaal.
Waar moet ik deze scripts uitvoeren?
Voer ze uit op een server, in een geplande taak of in een CI-pipeline, waarbij de sleutel als geheim is opgeslagen. Voer ze nooit uit in een browser.
Kan ik deze scripts gebruiken met OAuth in plaats van een API-sleutel?
Ja. Vervang de API-sleutel door een OAuth-toegangstoken in de Authorization-header en vernieuw deze voordat deze verloopt. Zie Uw app verbinden met Notiondesk met OAuth .