API & SDK reference

Article submission, editorial review and poll embeds.

SDK v1.0.0 · Node.js 20+ · No dependencies · Server only

01 · Register your newsroom

Each publisher receives its own ID, private API key, approved article domains and generation quota. Every newsroom uses the same endpoints.

For onboarding, provide your newsroom name, canonical HTTPS domain, logo URL and a technical contact. The platform operator verifies domain ownership and issues the key privately. Public self-service registration is not available yet.

Store your integration key as TOKENSENSUS_PUBLISHER_KEY on your CMS server. Never include it in browser code or an embed.

02 · Mark only the stories you want

Add [POLL] or [VOTE] at the start of the headline, or send pollEnabled: true from your CMS. Markers are case-insensitive and removed from the displayed headline.

Explicit opt-in comes first.

pollEnabled: false always skips. Without a flag or leading marker, the response includes skipped: true and no article is created. A word such as vote elsewhere in the headline does not opt in.

Selected stories are assessed for a suitable reader question. Drafts require editorial review. Policy, culture, industry and market-price articles are supported.

03 · Send the article from your server

Download the SDK and its declaration file into the same folder. It is a downloadable module, not an npm package. Send the original article thumbnail from your CMS or its Open Graph image field.

import { Tokensensus } from './tokensensus.mjs';

const client = new Tokensensus({
  apiKey: process.env.TOKENSENSUS_PUBLISHER_KEY,
});

// Run on your CMS server, when an editor opts in.
const result = await client.submitArticle({
  articleId: article.id,
  url: article.canonicalUrl,
  title: article.title, // e.g. "[POLL] Bitcoin breaks resistance"
  body: article.plainText,
  imageUrl: article.thumbnailUrl,
  language: 'en', // 'en' or 'ko': question language
  pollEnabled: true, // explicit CMS toggle; false always skips
});

// Never publish automatically.
if (result.article?.status === 'draft') {
  // Open Publisher studio for editorial review.
}

Use a stable article ID and canonical URL. The same payload reuses its saved result. Changed content needs a new revision ID and URL; this preserves existing votes. Fetching an article URL on a reader’s visit never triggers generation.

PHP, Python and other CMS servers can use the REST API directly.

04 · Review before publishing

Review the source excerpt, question and choices in Publisher studio. Confirm your review before publishing. Published choices cannot be edited; close the poll to stop new votes.

GET /api/v1/articles Your private editorial queue GET /api/v1/articles/:id Article and question status PATCH /api/v1/articles/:id Publish, reject or close PATCH /api/v1/publisher Set your logo with { "logoUrl": "https://…" }

05 · Add one small embed

Place the embed below the article body. Use data-lang=en for English controls or data-lang=ko for Korean.

<div data-tokensensus
     data-publisher="YOUR_PUBLISHER_ID"
     data-article-id="YOUR_CMS_ARTICLE_ID"
     data-lang="en"></div>
<script src="https://tokensensus.vercel.app/embed.js" defer></script>

Set the question language with language when submitting the article. Changing data-lang does not translate existing questions or choices.

The embed uses public IDs only and stays hidden until a question is published. It resizes automatically. Add https://tokensensus.vercel.app to your existing script-src, frame-src and connect-src CSP directives.

06 · Published polls

Published polls appear on Tokensensus with your logo, article headline, thumbnail and participation count. Readers can filter by publisher and open the original article.

Each question keeps one shared total across its embed and Tokensensus. We mark a publisher-site installation only after it is verified; a source link alone does not mean the widget is installed there.

Limits & error handling

  • Articles: 200–40,000 characters, request body up to 180 KB.
  • Allow up to 90 seconds for screening and generation. The SDK has a 95-second timeout and performs no automatic paid retries.
  • Per-publisher daily quotas count attempts, including failed and rejected ones. Quotas reset at 00:00 UTC. Reused or unmarked articles do not make another AI call.
  • HTTP 202: another request is processing the story. Read its status rather than submitting a changed payload.
  • HTTP 429: quota exhausted. Wait for the next quota window. HTTP 502: retry the exact payload after checking status.
  • AI runs during article preparation, never per reader vote. The public newsroom list may be cached for 30 seconds.

Contact the operator for your newsroom’s usage allowance. Keep the integration key private and request revocation and replacement if it is exposed.