English
ChassidusHub

התיעוד למפתחים כתוב באנגלית.

DevelopersUsing the API

API reference

ChassidusHub API 1.0.0: 205 routes in 25 groups, read from the API's own OpenAPI document.

Base URLhttps://api.chassidushub.org
ReadingNeeds nothing: no account, no key.

For what needs a signed-in person, paste a personal token. It is sent only to the API, and forgotten when you leave the page.

About#

This API, the catalog in numbers

Redirects to /v1#

GETGET /

No account neededroot

curl
curl 'https://api.chassidushub.org/'
Try it

About this API: its version, the latest commit, where the docs are#

GETGET /v1

No account neededabout

curl 'https://api.chassidushub.org/v1'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.about();
Try it

This document#

GETGET /openapi.json

No account neededopenapi

curl 'https://api.chassidushub.org/openapi.json'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.openapi();
Try it

How many items of each type, and the latest commit#

GETGET /v1/stats

No account neededstats

curl 'https://api.chassidushub.org/v1/stats'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.stats();
Try it

The community page in numbers: the latest merges, reports and suggestions waiting, people, gaps#

GETGET /v1/community

No account neededcommunity

Parameters

  • limitintegerquery

    How many (at most 50)

curl 'https://api.chassidushub.org/v1/community'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.community();
Try it

Whether ChassidusHub is up: the last checks of the site, the API, the MCP server, the database, its daily query allowance, the Workers' load and the scheduled jobs, with 90 days of them and the latest incidents#

GETGET /v1/status

No account neededstatus

Checked every five minutes; read from storage, never from the database, so it answers when the database does not. `report` is null until the first check. When `report.checkedAt` is much older than `now`, the checks have stopped running.

curl 'https://api.chassidushub.org/v1/status'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.status();
Try it

The health of the catalog: coverage per year and set, unchecked pages, unsynced recordings, dead links, the oldest open suggestions#

GETGET /v1/health

No account neededhealth

Parameters

  • limitintegerquery

    How many (at most 500)

curl 'https://api.chassidushub.org/v1/health'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.health();
Try it

Items#

Every sefer, sicha, letter, farbrengen, printing, scan and recording: by id, path, type, set and date, with history

Every kind of item and its JSON Schema#

GETGET /v1/types

No account neededtypes

curl 'https://api.chassidushub.org/v1/types'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.types();
Try it

Items on main, by type and set, in path order, a page at a time#

GETGET /v1/entities

No account neededPaged: pass next back as cursorlistItems

Parameters

  • typestringquery

    One of set, author, work, unit, event, publication, scan, contents-map, text-layer, text-page, text, segment, recording, alignment, alignment-span, relation, person, place, topic, source, schema

  • setstringquery

    Only items in this set

  • shelfbooleanquery

    What a shelf lists: leaves out the additions to a sefer (a work's addition.to), which are listed on that sefer's page

  • officialbooleanquery

    true: only the official sefarim the tree is built of (no additions); false: only additions

  • additions-ofstringquery

    Only the additions to this sefer

  • afterstringquery

    Deprecated: the same as cursor

  • limitintegerquery

    How many (at most 500)

  • cursorstringquery

    The `next` of the page before

curl 'https://api.chassidushub.org/v1/entities'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
for await (const item of rh.all('listItems', {})) {
  console.log(item);
}
Try it

Several items at once, in the order asked (missing ones left out)#

GETGET /v1/entities/batch

No account neededgetItems

Parameters

  • idsstringqueryrequired

    The ids

curl 'https://api.chassidushub.org/v1/entities/batch?ids=%3Cids%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getItems({
  ids: "<ids>"
});
Try it

One item, on main or as of a commit#

GETGET /v1/entities/{id}

No account neededgetItem

Words whose rights forbid copies are left out, and `withheld` says why.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

  • atintegerquery

    A commit's seq: the item as it was then

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getItem({
  id: "rh-7k2m9q4d"
});
Try it

An item's children in their own order (a work's units, a text's paragraphs), a page at a time#

GETGET /v1/entities/{id}/children

No account neededPaged: pass next back as cursorlistChildren

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

  • fieldstringqueryrequired

    The children's field that points at this item (work, text, event…)

  • typestringqueryrequired

    The children's type (unit, segment, recording…)

  • afterstringquery

    Deprecated: the same as cursor

  • limitintegerquery

    How many (at most 1000)

  • cursorstringquery

    The `next` of the page before

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/children?field=%3Cfield%3E&type=%3Ctype%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
for await (const item of rh.all('listChildren', {
  id: "rh-7k2m9q4d",
  field: "<field>",
  type: "<type>"
})) {
  console.log(item);
}
Try it

What points at an item, by type and field, with how many of each#

GETGET /v1/entities/{id}/linked/counts

No account neededlinkedCounts

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/linked/counts'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.linkedCounts({
  id: "rh-7k2m9q4d"
});
Try it

One group of what points at each of several items, a few of each in the group's order: what a list needs of every row in one request (a sefer's sichos' texts, a farbrengen's sichos' words)#

GETGET /v1/entities/batch/linked

No account neededlinkedOfEach

Parameters

  • idsstringqueryrequired

    The items

  • fieldstringqueryrequired

    The field that points at them (unit, text, publication…)

  • typestringquery

    Only items of this type

  • limitintegerquery

    How many (at most 500)

curl 'https://api.chassidushub.org/v1/entities/batch/linked?ids=%3Cids%3E&field=%3Cfield%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.linkedOfEach({
  ids: "<ids>",
  field: "<field>"
});
Try it

One group of what points at an item, in its own order, a page at a time, with the total#

GETGET /v1/entities/{id}/linked

No account neededPaged: pass next back as cursorlistLinked

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

  • fieldstringqueryrequired

    The field that points here (work, event, sets…; addition.to for the additions to a sefer)

  • typestringquery

    Only items of this type

  • afterstringquery

    Deprecated: the same as cursor

  • limitintegerquery

    How many (at most 500)

  • cursorstringquery

    The `next` of the page before

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/linked?field=%3Cfield%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
for await (const item of rh.all('listLinked', {
  id: "rh-7k2m9q4d",
  field: "<field>"
})) {
  console.log(item);
}
Try it

A sefer's shaar file, the README of a sefer, in its fixed form (docs/shaar.md)#

GETGET /v1/entities/{id}/shaar

No account neededgetShaar

For a sefer no person has written one for, the one the catalog makes from its data, with `machine` true. `?format=text` gives the file itself.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

  • formatjson | textquery

    text: the file itself, as text/markdown

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/shaar'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getShaar({
  id: "rh-7k2m9q4d"
});
Try it

Every merged change to an item, newest first: who, when, and what changed field by field#

GETGET /v1/entities/{id}/history

No account neededitemHistory

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/history'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.itemHistory({
  id: "rh-7k2m9q4d"
});
Try it

An item's links both ways: cites, printed in, based on, cited by#

GETGET /v1/entities/{id}/relations

No account neededitemRelations

Each is `machine: true` while a machine found it and no person has checked it.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/relations'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.itemRelations({
  id: "rh-7k2m9q4d"
});
Try it

One stored version of an item#

GETGET /v1/revisions/{rev}

No account neededgetRevision

Parameters

  • revintegerpathrequired

    A revision id

curl 'https://api.chassidushub.org/v1/revisions/1'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getRevision({
  rev: 1
});
Try it

The item at a readable path (an old path answers with where it moved)#

GETGET /v1/resolve

No account neededresolvePath

Parameters

  • pathstringqueryrequired

    A path such as /likkutei-sichos/12/3

curl 'https://api.chassidushub.org/v1/resolve?path=%2Fevents%2F5742-05-10'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.resolvePath({
  path: "/events/5742-05-10"
});
Try it

Farbrengens and other events by Hebrew date, each with how many recordings it has#

GETGET /v1/events

No account neededlistEvents

Parameters

  • withinstringquery

    A year (5742) or a month (5742-05)

  • daystringquery

    A day of any year (05-10), or several, comma separated

  • datesstringquery

    Exact dates, comma separated (5742-05-10,5743-05-10)

  • missingrecordings | textsquery

    Only those without

  • brief1query

    With 1: each event's facts with each link's kind alone, not its label and pages, for a calendar's rows (well under half the bytes)

  • limitintegerquery

    How many (at most 2000)

curl 'https://api.chassidushub.org/v1/events'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.listEvents();
Try it

How many items point at each item through a field (field=work&type=unit: each work's units)#

GETGET /v1/refcounts

No account neededrefCounts

Parameters

  • fieldstringqueryrequired

    The field

  • typestringquery

    Only items of this type

curl 'https://api.chassidushub.org/v1/refcounts?field=%3Cfield%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.refCounts({
  field: "<field>"
});
Try it

Every sitemap there is: each kind of item with a page of its own, in pages of pageSize items (id order), with when each page last changed#

GETGET /v1/sitemap

No account neededsitemaps

What the site's /sitemap.xml is made from. Kinds: set, author, person, work, unit, event, publication, recording.

curl 'https://api.chassidushub.org/v1/sitemap'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.sitemaps();
Try it

One sitemap's items: their ids, paths and when each last changed#

GETGET /v1/sitemap/{type}/{page}

No account neededsitemapPage

Parameters

  • typeset | author | person | work | unit | event | publication | recordingpathrequired

    A kind of item with a page of its own

  • pageintegerpathrequired

    From 1

curl 'https://api.chassidushub.org/v1/sitemap/set/1'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.sitemapPage({
  type: "set",
  page: 1
});
Try it

A work's volumes (its top-level parts), with how many units each holds#

GETGET /v1/works/{id}/outline

No account neededworkOutline

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/works/rh-7k2m9q4d/outline'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.workOutline({
  id: "rh-7k2m9q4d"
});
Try it

The units of one volume of a work#

GETGET /v1/works/{id}/parts/{part}

No account neededworkPart

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

  • partstringpathrequired

    The volume, as the outline names it

  • limitintegerquery

    How many (at most 1000)

curl 'https://api.chassidushub.org/v1/works/rh-7k2m9q4d/parts/<part>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.workPart({
  id: "rh-7k2m9q4d",
  part: "<part>"
});
Try it

The units just before and after a unit in its work's order, across volumes: a sicha's previous and next#

GETGET /v1/units/{id}/neighbours

No account neededunitNeighbours

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/units/rh-7k2m9q4d/neighbours'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.unitNeighbours({
  id: "rh-7k2m9q4d"
});
Try it

Every merge to main after a given one, in order, with what each changed: the way to follow the catalog without webhooks#

GETGET /v1/commits

No account neededPaged: pass next back as cursorlistCommits

Parameters

  • sinceintegerquery

    Start after this commit's seq (0: from the start)

  • limitintegerquery

    How many (at most 100)

  • changesintegerquery

    Carry only so many of each commit's changes (an import's has thousands); `changed` and `types` still count them all

  • cursorstringquery

    The `next` of the page before

curl 'https://api.chassidushub.org/v1/commits'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
for await (const item of rh.all('listCommits', {})) {
  console.log(item);
}
Try it

Texts#

Scans' texts line by line, printings compared, translations

How many paragraphs each of several texts has, how many of them a person checked, and how many a machine made that nobody checked yet#

GETGET /v1/texts/batch/progress

No account neededtextsProgress

Parameters

  • idsstringqueryrequired

    The texts

curl 'https://api.chassidushub.org/v1/texts/batch/progress?ids=%3Cids%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.textsProgress({
  ids: "<ids>"
});
Try it

A day's learning: Chitas (Tanya, the day's portion, each chapter it touches cut to it; Chumash with Rashi; Tehillim), Hayom Yom, and the Rambam's three tracks#

GETGET /v1/daily

No account neededdailyLearning

The day is the civil day it is learned on. Tanya follows the yearly cycle from 19 Kislev (Sefaria's Tanya Yomi); Hayom Yom gives both Adars' entries in a plain year's Adar. Each Tanya chapter says where the portion starts (`from`) and the first segment after it (`to`, null to its end). Chumash (the week's parsha, an aliyah a day, outside the Land of Israel), Tehillim (the monthly cycle, with Elul's and the ten days' three more) and the Rambam (three chapters, one chapter, Sefer HaMitzvos) are named in Hebrew and by Sefaria's references.

Parameters

  • datestringqueryrequired

    The civil day

curl 'https://api.chassidushub.org/v1/daily?date=2026-09-30'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.dailyLearning({
  date: "2026-09-30"
});
Try it

The shiurim's words, each page cut to what is learned: a day's (Chumash by aliyah with Rashi, Tehillim, Tanya, the Rambam's three tracks), or any by Sefaria's references#

GETGET /v1/shiurim

No account neededshiurim

Give `date` for a day's shiurim, or `ref` (up to ten, with `rashi=1` for a Chumash reference's Rashi too) for any. Each section names what it is (`chumash`, `tehillim`, `tanya`, `three`, `one`, `mitzvos`, or `passage`) and holds its pages, each in its Hebrew only, cut to the stretch learned (`from`, and `to` the first segment after it, null to its end); a Rashi page is marked `rashi`. A reference the catalog has no page for is left out.

Parameters

  • datestringquery

    The civil day

  • refstringquery

    A Sefaria reference; repeat for more

  • rashistringquery

    With a Chumash reference, its Rashi too

curl 'https://api.chassidushub.org/v1/shiurim'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.shiurim();
Try it

A page of a scan's text: the community page, else the seed layer's; each line with its proofread level#

GETGET /v1/scans/{id}/text

No account neededscanText

Lines nobody has checked are machine reading (`checked: false`). Withheld when the scan may not be served.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

  • pageintegerquery

    The page

curl 'https://api.chassidushub.org/v1/scans/rh-7k2m9q4d/text'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.scanText({
  id: "rh-7k2m9q4d"
});
Try it

How far each page of a scan is proofread (0, 1 or 2)#

GETGET /v1/scans/{id}/progress

No account neededscanProgress

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/scans/rh-7k2m9q4d/progress'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.scanProgress({
  id: "rh-7k2m9q4d"
});
Try it

Fix one line of a scan's text (a suggestion)#

POSTPOST /v1/scans/{id}/text/fix

A token with the write scope, or the site sessionfixScanLine

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "page": {
      "type": "integer"
    },
    "line": {
      "type": "string",
      "description": "The line's id"
    },
    "text": {
      "type": "string"
    }
  },
  "required": [
    "page",
    "line",
    "text"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/scans/rh-7k2m9q4d/text/fix' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"page":1,"line":"<line>","text":"<text>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.fixScanLine({
  id: "rh-7k2m9q4d",
  body: {
    page: 1,
    line: "<line>",
    text: "<text>"
  }
});
Try it
Needs a token (above)

This page is right: raise it a proofreading level, with any fixes (a suggestion)#

POSTPOST /v1/scans/{id}/text/confirm

A token with the write scope, or the site sessionconfirmScanPage

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "page": {
      "type": "integer"
    },
    "fixes": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "Line id to its right text"
    }
  },
  "required": [
    "page"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/scans/rh-7k2m9q4d/text/confirm' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"page":1}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.confirmScanPage({
  id: "rh-7k2m9q4d",
  body: {
    page: 1
  }
});
Try it
Needs a token (above)

Upload your own OCR of a scan (hOCR, ALTO, or plain text with form feeds between pages) as a new layer#

POSTPOST /v1/scans/{id}/ocr

A token with the write scope, or the site sessionuploadOcr

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "content": {
      "type": "string"
    },
    "format": {
      "enum": [
        "hocr",
        "alto",
        "text"
      ]
    },
    "engine": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "version": {
          "type": "string"
        }
      },
      "required": [
        "name",
        "version"
      ]
    },
    "firstPage": {
      "type": "integer",
      "minimum": 1
    },
    "language": {
      "type": "string"
    }
  },
  "required": [
    "content",
    "engine"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/scans/rh-7k2m9q4d/ocr' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"content":"<content>","engine":{"name":"<name>","version":"<version>"}}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.uploadOcr({
  id: "rh-7k2m9q4d",
  body: {
    content: "<content>",
    engine: {
      name: "<name>",
      version: "<version>"
    }
  }
});
Try it
Needs a token (above)

Keepers: seed the community text from this OCR layer (checked lines are kept)#

POSTPOST /v1/scans/{id}/text/seed

A token with the write scope, or the site sessionseedScanText

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "layer": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    }
  },
  "required": [
    "layer"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/scans/rh-7k2m9q4d/text/seed' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"layer":"rh-7k2m9q4d"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.seedScanText({
  id: "rh-7k2m9q4d",
  body: {
    layer: "rh-7k2m9q4d"
  }
});
Try it
Needs a token (above)

The printings of a unit whose text the catalog has, to compare#

GETGET /v1/units/{id}/printings

No account neededunitPrintings

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/units/rh-7k2m9q4d/printings'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.unitPrintings({
  id: "rh-7k2m9q4d"
});
Try it

Compare two printings word by word (Hebrew-aware)#

GETGET /v1/compare

No account neededcomparePrintings

Parameters

  • astringqueryrequired

    text:<id> or scan:<id>:<from>-<to>

  • bstringqueryrequired

    The other printing

curl 'https://api.chassidushub.org/v1/compare?a=%3Ca%3E&b=%3Cb%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.comparePrintings({
  a: "<a>",
  b: "<b>"
});
Try it

Suggest a translation of a unit, as its own text#

POSTPOST /v1/units/{id}/translations

A token with the write scope, or the site sessionaddTranslation

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "language": {
      "type": "string"
    },
    "credit": {
      "type": "string"
    },
    "licence": {
      "enum": [
        "public-domain",
        "cc0",
        "cc-by",
        "cc-by-nc"
      ]
    },
    "translationOf": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "content": {
      "type": "string",
      "description": "A blank line between paragraphs"
    },
    "machine": {
      "type": "string",
      "description": "The tool, when a machine translated it"
    }
  },
  "required": [
    "language",
    "credit",
    "content"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/units/rh-7k2m9q4d/translations' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"language":"<language>","credit":"<credit>","content":"<content>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.addTranslation({
  id: "rh-7k2m9q4d",
  body: {
    language: "<language>",
    credit: "<credit>",
    content: "<content>"
  }
});
Try it
Needs a token (above)

Suggest a fix to one paragraph of a translation#

POSTPOST /v1/translations/fix

A token with the write scope, or the site sessionfixTranslation

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "segment": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "content": {
      "type": "string"
    }
  },
  "required": [
    "segment",
    "content"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/translations/fix' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"segment":"rh-7k2m9q4d","content":"<content>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.fixTranslation({
  body: {
    segment: "rh-7k2m9q4d",
    content: "<content>"
  }
});
Try it
Needs a token (above)

A hanacha's words for a farbrengen or sicha (or a new farbrengen), a paragraph to a segment#

POSTPOST /v1/hanachos/text

A token with the write scope, or the site sessionaddHanachaText

Words of unsure rights are kept and not shown until a steward decides. Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "for": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "eventTitle": {
      "type": "string",
      "description": "For a farbrengen the catalog lacks: its name"
    },
    "eventDate": {
      "type": "string",
      "description": "With eventTitle: its date key"
    },
    "content": {
      "type": "string",
      "description": "A blank line between paragraphs"
    },
    "rights": {
      "enum": [
        "mine",
        "public-domain",
        "free",
        "unsure"
      ]
    },
    "language": {
      "type": "string"
    },
    "credit": {
      "type": "string"
    }
  },
  "required": [
    "content",
    "rights"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/hanachos/text' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"content":"<content>","rights":"mine"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.addHanachaText({
  body: {
    content: "<content>",
    rights: "mine"
  }
});
Try it
Needs a token (above)

A text of a sefer as its source gave it (one chapter or letter, an HTML article)#

GETGET /v1/texts/{sha256}

No account neededgetSourceText

Parameters

  • sha256stringpathrequired

    A file, named by its sha256

curl 'https://api.chassidushub.org/v1/texts/<sha256>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getSourceText({
  sha256: "<sha256>"
});
Try it

Media#

Transcripts and their sync

Every recording that has a transcript, the most checked first, then the longest#

GETGET /v1/transcripts

No account neededtranscribedRecordings

Parameters

  • limitintegerquery

    How many (at most 1000)

curl 'https://api.chassidushub.org/v1/transcripts'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.transcribedRecordings();
Try it

Every transcript fix waiting for approval, to go through together: each paragraph on the site and as the fix would make it, where it is heard, who sent it, and whether you may approve it#

GETGET /v1/transcripts/fixes

No account needed; signed in, a little moretranscriptFixes

No account needed; signed in, a little more.

Parameters

  • limitintegerquery

    How many (at most 200)

curl 'https://api.chassidushub.org/v1/transcripts/fixes'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.transcriptFixes();
Try it

Keep some transcript fixes and remove others in one go: kept ones are approved; removed ones are withdrawn if they are yours, else sent back with the note#

POSTPOST /v1/transcripts/fixes/decide

A token with the write scope, or the site sessiondecideTranscriptFixes

Signed in: an API token with the write scope, or the site's session.

Body application/json
{
  "type": "object",
  "properties": {
    "keep": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Suggestions to approve"
    },
    "remove": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Suggestions to take out"
    },
    "note": {
      "type": "string",
      "description": "Said to the people whose fixes are sent back"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/transcripts/fixes/decide' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.decideTranscriptFixes({
  body: {}
});
Try it
Needs a token (above)

A recording's transcript, with its sync by paragraph and word#

GETGET /v1/recordings/{id}/transcript

No account neededrecordingTranscript

A paragraph is machine hearing until a person checks it (`checked`).

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/recordings/rh-7k2m9q4d/transcript'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.recordingTranscript({
  id: "rh-7k2m9q4d"
});
Try it

Everything that happened to a recording's transcript, newest first#

GETGET /v1/recordings/{id}/transcript/history

No account neededtranscriptHistory

Each approved change with who made it and what it changed, paragraph by paragraph: `words` (before and after, and whether the whole paragraph was checked), `checked`, `sync` (where it is heard moved) and `made` (the machine's first hearing).

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

  • limitintegerquery
curl 'https://api.chassidushub.org/v1/recordings/rh-7k2m9q4d/transcript/history'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.transcriptHistory({
  id: "rh-7k2m9q4d"
});
Try it

Fix the words of one paragraph of a transcript (a suggestion)#

POSTPOST /v1/recordings/{id}/transcript/fix

A token with the write scope, or the site sessionfixTranscript

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "segment": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "content": {
      "type": "string"
    },
    "complete": {
      "type": "boolean",
      "description": "false: only some words were fixed; the paragraph stays machine hearing (default true)"
    }
  },
  "required": [
    "segment",
    "content"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/recordings/rh-7k2m9q4d/transcript/fix' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"segment":"rh-7k2m9q4d","content":"<content>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.fixTranscript({
  id: "rh-7k2m9q4d",
  body: {
    segment: "rh-7k2m9q4d",
    content: "<content>"
  }
});
Try it
Needs a token (above)

The Rebbe is saying this line now: set a paragraph (or word) at atMs, lock it, move what follows#

POSTPOST /v1/recordings/{id}/sync/anchor

A token with the write scope, or the site sessionanchorSync

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "segment": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "atMs": {
      "type": "integer"
    },
    "word": {
      "type": "integer"
    }
  },
  "required": [
    "segment",
    "atMs"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/recordings/rh-7k2m9q4d/sync/anchor' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"segment":"rh-7k2m9q4d","atMs":1}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.anchorSync({
  id: "rh-7k2m9q4d",
  body: {
    segment: "rh-7k2m9q4d",
    atMs: 1
  }
});
Try it
Needs a token (above)

The sync is right: mark every paragraph checked#

POSTPOST /v1/recordings/{id}/sync/confirm

A token with the write scope, or the site sessionconfirmSync

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl -X POST 'https://api.chassidushub.org/v1/recordings/rh-7k2m9q4d/sync/confirm' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.confirmSync({
  id: "rh-7k2m9q4d"
});
Try it
Needs a token (above)

Several recordings' synced hanachos at once (a farbrengen's parts), by recording; those with none are left out#

GETGET /v1/recordings/batch/hanacha

No account neededrecordingsHanacha

Parameters

  • idsstringqueryrequired

    The recordings

curl 'https://api.chassidushub.org/v1/recordings/batch/hanacha?ids=%3Cids%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.recordingsHanacha({
  ids: "<ids>"
});
Try it

The hanacha synced to this recording, paragraph by paragraph#

GETGET /v1/recordings/{id}/hanacha

No account neededrecordingHanacha

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/recordings/rh-7k2m9q4d/hanacha'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.recordingHanacha({
  id: "rh-7k2m9q4d"
});
Try it

Machine#

Asking the machines to read a scan or transcribe a recording, and their queue

What waits for the machines (OCR, transcription), what is left for them, and what they did this week#

GETGET /v1/machine

No account neededmachineSummary

curl 'https://api.chassidushub.org/v1/machine'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.machineSummary();
Try it

The next Rebbe Whisper's training data so far: every transcript paragraph of the Rebbe speaking that a person checked or fixed, waiting fixes too, as clips#

GETGET /v1/machine/training

No account neededtrainingSummary

Hours and clips (gold: words and timing checked by a person; silver: words checked, timing by machine; review: how many are checked, fixed in part, or waiting for review), train and test hours, what was left out and why, and with since, the hours checked since then.

Parameters

  • sincestringquery

    A date: also count the hours checked since then

curl 'https://api.chassidushub.org/v1/machine/training'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.trainingSummary();
Try it

What the machines wrote that no person has checked yet: farbrengens with unchecked transcript paragraphs, scans with pages read by OCR and not yet proofread, pages whose words a machine read with segments nobody checked, the newest first#

GETGET /v1/machine/to-check

No account neededmachineToCheck

Parameters

  • limitintegerquery

    How many (at most 200)

curl 'https://api.chassidushub.org/v1/machine/to-check'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.machineToCheck();
Try it

The training clips, one JSON object a line, as the training script reads them (audio, start, end, text, split, quality, review)#

GETGET /v1/machine/training/clips

No account neededtrainingClips

Parameters

  • carried1query

    With 1: fixed paragraphs cut by the word times the fix carried over too (marked timing: carried), for a training run that aligns them again

curl 'https://api.chassidushub.org/v1/machine/training/clips'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.trainingClips();
Try it

Requests for the machines, the waiting ones in the order they are taken#

GETGET /v1/machine/requests

No account neededmachineRequests

Parameters

  • kindocr | transcriptquery
  • statuswaiting | running | done | failedquery
  • itemstringquery

    Requests for one item

  • itemsstringquery

    Ids, comma separated (up to 100)

  • limitintegerquery

    How many (at most 200)

curl 'https://api.chassidushub.org/v1/machine/requests'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.machineRequests();
Try it

Ask the machine to read a scan (ocr) or transcribe a recording (transcript)#

POSTPOST /v1/machine/requests

A token with the write scope, or the site sessionrequestMachineWork

Free CPU engines only; what they make is labelled as machine output until people check it. Asking for what already waits joins that request (200). Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "kind": {
      "enum": [
        "ocr",
        "transcript"
      ]
    },
    "item": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    }
  },
  "required": [
    "kind",
    "item"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/machine/requests' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"kind":"ocr","item":"rh-7k2m9q4d"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.requestMachineWork({
  body: {
    kind: "ocr",
    item: "rh-7k2m9q4d"
  }
});
Try it
Needs a token (above)

Files#

File bytes (while their rights allow), page images, uploads

Several files at once, in the order asked (missing ones left out)#

GETGET /v1/files/batch

No account neededgetFiles

Parameters

  • idsstringqueryrequired

    The files

curl 'https://api.chassidushub.org/v1/files/batch?ids=%3Cids%3E'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getFiles({
  ids: "<ids>"
});
Try it

A file's size, rights and address, what was made from it, and its page fix#

GETGET /v1/files/{sha256}

No account neededgetFile

Parameters

  • sha256stringpathrequired

    A file, named by its sha256

curl 'https://api.chassidushub.org/v1/files/<sha256>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getFile({
  sha256: "<sha256>"
});
Try it

Held files that look like this one (the same scan or recording in other bytes): a machine's guess#

GETGET /v1/files/{sha256}/similar

No account neededsimilarFiles

Parameters

  • sha256stringpathrequired

    A file, named by its sha256

curl 'https://api.chassidushub.org/v1/files/<sha256>/similar'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.similarFiles({
  sha256: "<sha256>"
});
Try it

What a PDF on Google Drive needs to read straight, by its Drive id, or the reading copy to open instead#

GETGET /v1/page-fixes/drive/{id}

No account neededdriveFix

Parameters

  • idstringpathrequired

    A Google Drive file id

curl 'https://api.chassidushub.org/v1/page-fixes/drive/<id>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.driveFix({
  id: "<id>"
});
Try it

A Google Drive file the catalog links to (a hanacha's PDF, an Otzros scan), read for the site's reader and player#

GETGET /v1/drive/{id}

No account neededdriveFile

Only files an item links to. Supports Range requests; the whole file is kept at the edge for a week. Files over the size ChassidusHub passes on (300 MB) answer 413.

Parameters

  • idstringpathrequired

    A Google Drive file id

curl 'https://api.chassidushub.org/v1/drive/<id>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.driveFile({
  id: "<id>"
});
Try it

A file's bytes, while its rights let it be served#

GETGET /objects/{sha256}

No account neededgetObject

Supports Range requests. `X-Credit` carries the credit the rights ask for.

Parameters

  • sha256stringpathrequired

    A file, named by its sha256

curl 'https://api.chassidushub.org/objects/<sha256>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getObject({
  sha256: "<sha256>"
});
Try it

A published manifest: reading copies, page fixes (facts about files, open like the catalog)#

GETGET /manifests/{collection}/{name}

No account neededgetManifest

Parameters

  • collectionstringpathrequired
  • namestringpathrequired

    ends in .json

curl 'https://api.chassidushub.org/manifests/<collection>/<name>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getManifest({
  collection: "<collection>",
  name: "<name>"
});
Try it

A served scan's page images and thumbnails, and its IIIF manifest#

GETGET /v1/scans/{id}/pages

No account neededscanPages

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/scans/rh-7k2m9q4d/pages'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.scanPages({
  id: "rh-7k2m9q4d"
});
Try it

Add a file: a recording of a farbrengen; a hanacha's PDF for a farbrengen or sicha; a scan (another scan of a printing, a new printing of a sefer, a teshura); or other material (a new sefer, a letter, a document)#

POSTPOST /v1/uploads

A token with the write scope, or the site sessionupload

The file is the body, with its Content-Type (audio/…, application/pdf). A recording or hanacha may name a farbrengen the catalog lacks (eventTitle and eventDate) instead of `for`. New accounts wait a day, and everyone adds so many a day. Signed in: an API token with the write scope, or the site's session.

Parameters

  • whatrecording | hanacha | scan | documentqueryrequired

    What it is

  • forstringquery

    The farbrengen, sicha, sefer, printing or Teshuros set it is added to

  • eventTitlestringquery

    For a recording or hanacha of a farbrengen the catalog lacks: its name

  • eventDatestringquery

    With eventTitle: its date key

  • kindbilti-mugah | mugah | maamar | hagahos | hosofos | english | otherquery

    For a hanacha: what kind

  • setstringquery

    For a document: the set it belongs in

  • authorstringquery

    For a new sefer: its author

  • genrestringquery

    For a new sefer: its genre

  • unitstringquery

    For a letter: the letter the catalog has that it reproduces

  • rightsmine | free | public-domain | unsurequeryrequired

    What you know of its rights

  • asscan-of | printing | teshura | sefer | letter | documentquery

    For a scan: scan-of, printing or teshura. For a document: sefer, letter or document

  • titlestringquery

    Its name

  • publicationstringquery

    For scan-of: the printing

  • publisherstringquery

    For a printing

  • yearstringquery

    For a printing: a Hebrew or civil year

  • printingintegerquery

    For a printing: 1 for the first

  • familiesstringquery

    For a teshura: its families, as printed

  • simchastringquery

    For a teshura: wedding, bar-mitzvah, and so on

  • datestringquery

    For a teshura: the simcha's date key; for a letter or document, its date

Body application/octet-streamrequired
{
  "type": "string",
  "format": "binary"
}
curl -X POST 'https://api.chassidushub.org/v1/uploads?what=recording&rights=mine' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/pdf' --data-binary @file
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.upload({
  what: "recording",
  rights: "mine",
  body: file,
  contentType: "application/pdf"
});

Before an upload: whether we have it (its sha256, a few page hashes) and what it likely is#

POSTPOST /v1/uploads/check

A token with the write scope, or the site sessioncheckUpload

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "for": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "sha256": {
      "type": "string"
    },
    "pageHashes": {
      "type": "array",
      "items": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ]
      }
    },
    "title": {
      "type": "string"
    }
  },
  "required": [
    "for"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/uploads/check' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"for":"rh-7k2m9q4d"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.checkUpload({
  body: {
    for: "rh-7k2m9q4d"
  }
});
Try it
Needs a token (above)

Before adding something new: the machine's guess of what it is and where it belongs, from its name (a date in it, words of a title), and files already held that look like it#

POSTPOST /v1/uploads/propose

A token with the write scope, or the site sessionproposeUpload

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "what": {
      "enum": [
        "hanacha",
        "recording",
        "document"
      ]
    },
    "name": {
      "type": "string",
      "description": "Its file name or title"
    },
    "sha256": {
      "type": "string",
      "description": "A file, named by its sha256",
      "pattern": "^[0-9a-f]{64}$"
    },
    "pageHashes": {
      "type": "array",
      "items": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ]
      }
    }
  },
  "required": [
    "what"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/uploads/propose' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"what":"hanacha"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.proposeUpload({
  body: {
    what: "hanacha"
  }
});
Try it
Needs a token (above)

A file's own page: its rights, where it came from, what was made from it, and what uses it#

GETGET /v1/files/{sha256}/about

No account neededfileAbout

Parameters

  • sha256stringpathrequired

    A file, named by its sha256

  • limitintegerquery

    How many (at most 500)

curl 'https://api.chassidushub.org/v1/files/<sha256>/about'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.fileAbout({
  sha256: "<sha256>"
});
Try it

Sefarim's covers, drawn from their title pages, while their PDFs are served or linked#

GETGET /v1/covers

No account neededcovers

A cover is `machine: true` until a person chose its page. A cover drawn from a PDF ChassidusHub only links to is served; the PDF is not (its file page links to the source).

Parameters

  • idsstringquery

    The sefarim

curl 'https://api.chassidushub.org/v1/covers'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.covers();
Try it

A sefer's cover, the page a person chose, and the PDFs (served, or linked) its title page may be chosen from#

GETGET /v1/works/{id}/cover

No account neededworkCover

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/works/rh-7k2m9q4d/cover'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.workCover({
  id: "rh-7k2m9q4d"
});
Try it

Suggestions#

Every change is a suggestion, checked and reviewed

Suggest restoring an earlier version of an item#

POSTPOST /v1/entities/{id}/restore

A token with the write scope, or the site sessionrestoreItem

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "rev": {
      "type": "integer",
      "description": "The revision to restore"
    }
  },
  "required": [
    "rev"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/restore' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"rev":1}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.restoreItem({
  id: "rh-7k2m9q4d",
  body: {
    rev: 1
  }
});
Try it
Needs a token (above)

Suggestions, oldest sent first, by status or author; with `state`, the list of conversations, newest first (numbers, reviewers, approvals, the issues each closes) with counts#

GETGET /v1/suggestions

No account neededPaged: pass next back as cursorlistSuggestions

Parameters

  • statusdraft | open | merged | sent_back | withdrawnquery
  • stateopen | closed | allquery

    The conversation list: open (waiting or sent back) or closed (merged or withdrawn)

  • authorstringquery

    An account id, or (with state) a handle

  • reviewerstringquery

    With state: asked to review, or reviewed (a handle)

  • qstringquery

    With state: words in the title, or #number

  • aboutstringquery

    With state: only suggestions that change these items, or what is in them (a sefer's sichos and their texts, a sicha's paragraphs, a farbrengen's sichos)

  • postReviewtrue | falsequery

    true: live changes waiting to be reviewed after

  • limitintegerquery

    How many (at most 500)

  • cursorstringquery

    The `next` of the page before

curl 'https://api.chassidushub.org/v1/suggestions'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
for await (const item of rh.all('listSuggestions', {})) {
  console.log(item);
}
Try it

Start a suggestion (a draft): add items to it, then submit it#

POSTPOST /v1/suggestions

A token with the write scope, or the site sessioncreateSuggestion

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "project": {
      "type": "integer"
    }
  },
  "required": [
    "title"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Fix the date"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.createSuggestion({
  body: {
    title: "Fix the date"
  }
});
Try it
Needs a token (above)

Suggest a fix in one step: a new version of one item, with a few words on why, sent for review#

POSTPOST /v1/suggestions/quick

A token with the write scope, or the site sessionsuggestFix

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "entityId": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "data": {
      "type": "object",
      "additionalProperties": true,
      "description": "The item's whole new data"
    },
    "title": {
      "type": "string",
      "maxLength": 200
    },
    "note": {
      "type": "string",
      "maxLength": 2000
    }
  },
  "required": [
    "entityId",
    "data"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/quick' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"entityId":"rh-7k2m9q4d","data":{}}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.suggestFix({
  body: {
    entityId: "rh-7k2m9q4d",
    data: {}
  }
});
Try it
Needs a token (above)

The review view: each item before and after, clashes with main, and the reviewer's advice (machine-written, `machine: true`). A page of items at a time (`entries`, from `offset`), with `total`, `next` (the offset of the next page, or null) and, with summary=1, `summary`: the items grouped by how they change ("500 units: links on the media proxy became links on Drive"), with a few examples of each#

GETGET /v1/suggestions/{id}

No account needed; signed in, a little moregetSuggestion

No account needed; signed in, a little more.

Parameters

  • idintegerpathrequired

    The suggestion

  • offsetintegerquery

    Items to skip: the `next` of the page before

  • limitintegerquery

    How many (at most 200)

  • summary1query

    With 1: also `summary`, every item grouped by how it changes (all of them are read and compared for it)

  • brief1query

    With 1: each item's facts, not its words (`before` and `after` without `body`; what changed is whole in `changes`), for a feed

curl 'https://api.chassidushub.org/v1/suggestions/1'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getSuggestion({
  id: 1
});
Try it

Change the title or description of your suggestion (@mentions and "Fixes #12" are read again)#

PATCHPATCH /v1/suggestions/{id}

A token with the write scope, or the site sessioneditSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 200
    },
    "description": {
      "type": "string"
    }
  }
}
curl -X PATCH 'https://api.chassidushub.org/v1/suggestions/1' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.editSuggestion({
  id: 1,
  body: {}
});
Try it
Needs a token (above)

A suggestion's timeline (comments, reviews, events), the reviewers asked, and the issues it closes#

GETGET /v1/suggestions/{id}/conversation

No account needed; signed in, a little moresuggestionConversation

No account needed; signed in, a little more.

Parameters

  • idintegerpathrequired

    The suggestion

curl 'https://api.chassidushub.org/v1/suggestions/1/conversation'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.suggestionConversation({
  id: 1
});
Try it

Comment on a suggestion, answer a comment, or comment on one field of one item#

POSTPOST /v1/suggestions/{id}/comments

A token with the write scope, or the site sessioncommentOnSuggestion

@handles are told (their inbox), and #12 links to that suggestion or issue. Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10000
    },
    "parent": {
      "type": "integer",
      "description": "The comment this answers"
    },
    "anchor": {
      "type": "object",
      "properties": {
        "entity": {
          "type": "string",
          "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
          "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
          "examples": [
            "rh-7k2m9q4d"
          ]
        },
        "field": {
          "type": "string"
        }
      },
      "required": [
        "entity",
        "field"
      ]
    }
  },
  "required": [
    "body"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/comments' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.commentOnSuggestion({
  id: 1,
  body: {
    body: "<body>"
  }
});
Try it
Needs a token (above)

Review: approve (it goes into the catalog, where you may merge it), request changes (sent back), or comment; with comments on fields#

POSTPOST /v1/suggestions/{id}/reviews

A token with the write scope, or the site sessionreviewSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "verdict": {
      "enum": [
        "approve",
        "request_changes",
        "comment"
      ]
    },
    "body": {
      "type": "string"
    },
    "comments": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "entity": {
            "type": "string",
            "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
            "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
            "examples": [
              "rh-7k2m9q4d"
            ]
          },
          "field": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "entity",
          "field",
          "body"
        ]
      }
    },
    "resolutions": {
      "type": "object",
      "additionalProperties": true,
      "description": "For each item, how each clashing field is settled: {item: {field: {take: \"ours\" (the site) | \"theirs\" (the suggestion)}}}; `*` stands for every item or every field not named"
    }
  },
  "required": [
    "verdict"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/reviews' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"verdict":"approve"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.reviewSuggestion({
  id: 1,
  body: {
    verdict: "approve"
  }
});
Try it
Needs a token (above)

Ask people to review (asking again asks again)#

POSTPOST /v1/suggestions/{id}/review-requests

A token with the write scope, or the site sessionrequestReview

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "reviewers": {
      "type": "array",
      "items": {
        "type": "string",
        "description": "A handle"
      },
      "description": "Handles"
    }
  },
  "required": [
    "reviewers"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/review-requests' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"reviewers":["<reviewers>"]}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.requestReview({
  id: 1,
  body: {
    reviewers: [
      "<reviewers>"
    ]
  }
});
Try it
Needs a token (above)

Stop asking someone to review#

DELETEDELETE /v1/suggestions/{id}/review-requests/{username}

A token with the write scope, or the site sessionremoveReviewRequest

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

  • usernamestringpathrequired

    A handle, without the @

curl -X DELETE 'https://api.chassidushub.org/v1/suggestions/1/review-requests/<username>' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.removeReviewRequest({
  id: 1,
  username: "<username>"
});
Try it
Needs a token (above)

Add or change one item in a draft suggestion (data null deletes it)#

PUTPUT /v1/suggestions/{id}/items

A token with the write scope, or the site sessionputSuggestionItem

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "type": {
      "type": "string"
    },
    "data": {
      "type": [
        "object",
        "null"
      ]
    },
    "path": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "type",
    "data"
  ]
}
curl -X PUT 'https://api.chassidushub.org/v1/suggestions/1/items' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"type":"<type>","data":{}}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.putSuggestionItem({
  id: 1,
  body: {
    type: "<type>",
    data: {}
  }
});
Try it
Needs a token (above)

Send for review (runs the automatic checks)#

POSTPOST /v1/suggestions/{id}/submit

A token with the write scope, or the site sessionsubmitSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/submit' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.submitSuggestion({
  id: 1
});
Try it
Needs a token (above)

Approve and merge (keepers of its sets, stewards)#

POSTPOST /v1/suggestions/{id}/approve

A token with the write scope, or the site sessionapproveSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/json
{
  "type": "object",
  "properties": {
    "resolutions": {
      "type": "object",
      "additionalProperties": true,
      "description": "For each item, how each clashing field is settled: {item: {field: {take: \"ours\" (the site) | \"theirs\" (the suggestion)}}}; `*` stands for every item or every field not named"
    },
    "note": {
      "type": "string"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/approve' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.approveSuggestion({
  id: 1,
  body: {}
});
Try it
Needs a token (above)

Send back with a note#

POSTPOST /v1/suggestions/{id}/send-back

A token with the write scope, or the site sessionsendBackSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/json
{
  "type": "object",
  "properties": {
    "note": {
      "type": "string"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/send-back' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.sendBackSuggestion({
  id: 1,
  body: {}
});
Try it
Needs a token (above)

Review a live change after it went live: keep it (approve) or undo it (revert)#

POSTPOST /v1/suggestions/{id}/review-live

A token with the write scope, or the site sessionreviewLive

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "verdict": {
      "enum": [
        "approve",
        "revert"
      ]
    },
    "note": {
      "type": "string"
    }
  },
  "required": [
    "verdict"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/review-live' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"verdict":"approve"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.reviewLive({
  id: 1,
  body: {
    verdict: "approve"
  }
});
Try it
Needs a token (above)

Withdraw your suggestion#

POSTPOST /v1/suggestions/{id}/withdraw

A token with the write scope, or the site sessionwithdrawSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/withdraw' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.withdrawSuggestion({
  id: 1
});
Try it
Needs a token (above)

Undo a withdrawal: your suggestion is open for review again (its checks run again)#

POSTPOST /v1/suggestions/{id}/reopen

A token with the write scope, or the site sessionreopenSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/reopen' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.reopenSuggestion({
  id: 1
});
Try it
Needs a token (above)

Undo a merged suggestion (a new suggestion that reverses it)#

POSTPOST /v1/suggestions/{id}/revert

A token with the write scope, or the site sessionrevertSuggestion

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The suggestion

Body application/json
{
  "type": "object",
  "properties": {
    "reason": {
      "type": "string"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/1/revert' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.revertSuggestion({
  id: 1,
  body: {}
});
Try it
Needs a token (above)

A sefer's shaar, the whole file, sent for review; a file the catalog cannot read is refused with each line that is wrong (`detail.problems`)#

POSTPOST /v1/suggestions/shaar

A token with the write scope, or the site sessionsuggestShaar

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "entityId": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "text": {
      "type": "string",
      "description": "The whole shaar file"
    },
    "before": {
      "type": "string",
      "description": "The file as the person opened it; a change since answers 409"
    },
    "title": {
      "type": "string"
    },
    "note": {
      "type": "string"
    }
  },
  "required": [
    "entityId",
    "text"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/shaar' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"entityId":"rh-7k2m9q4d","text":"<text>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.suggestShaar({
  body: {
    entityId: "rh-7k2m9q4d",
    text: "<text>"
  }
});
Try it
Needs a token (above)

A page's words fixed segment by segment: one segment's new words, a segment added after it or taken out, a page's first words, or a machine's segment checked as right (`check`), sent for review#

POSTPOST /v1/suggestions/words

A token with the write scope, or the site sessionsuggestWords

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "entityId": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "change": {
      "enum": [
        "edit",
        "add",
        "remove",
        "start",
        "check"
      ]
    },
    "version": {
      "type": "string"
    },
    "segment": {
      "type": "string"
    },
    "text": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": true
      },
      "description": "Runs: { text, marks?, href? }, { note }, { marker }, { br: true }, { eol, split?, page?, box? }"
    },
    "before": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": true
      },
      "description": "The segment as the person saw it; a change since answers 409"
    },
    "kind": {
      "enum": [
        "paragraph",
        "heading",
        "verse",
        "item"
      ]
    },
    "language": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "note": {
      "type": "string"
    }
  },
  "required": [
    "entityId",
    "change"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/words' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"entityId":"rh-7k2m9q4d","change":"edit"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.suggestWords({
  body: {
    entityId: "rh-7k2m9q4d",
    change: "edit"
  }
});
Try it
Needs a token (above)

Combine several of your own suggestions into one, as a pull request holds many commits#

POSTPOST /v1/suggestions/combine

A token with the write scope, or the site sessioncombineSuggestions

Their changes are applied in the order they were made; changes to different words of one text are all kept, and where a later change rewrites an earlier one the later one stands. The suggestions combined are withdrawn. Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "suggestions": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "Their ids (2 to 100), all yours and not yet approved"
    },
    "title": {
      "type": "string",
      "maxLength": 200
    }
  },
  "required": [
    "suggestions"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/combine' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"suggestions":[1]}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.combineSuggestions({
  body: {
    suggestions: [
      1
    ]
  }
});
Try it
Needs a token (above)

Map pages of a publication to the unit they hold (an existing unit, a new one, or words)#

POSTPOST /v1/suggestions/contents-map

A token with the write scope, or the site sessionmapContents

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "publication": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "pages": {
      "type": "object",
      "properties": {
        "from": {
          "type": "integer"
        },
        "to": {
          "type": "integer"
        },
        "scheme": {
          "enum": [
            "printed",
            "pdf"
          ]
        }
      },
      "required": [
        "from",
        "to"
      ]
    },
    "unit": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "newUnit": {
      "type": "object",
      "properties": {
        "work": {
          "type": "string",
          "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
          "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
          "examples": [
            "rh-7k2m9q4d"
          ]
        },
        "label": {
          "type": "object",
          "additionalProperties": true
        },
        "date": {
          "type": "string"
        }
      }
    },
    "label": {
      "type": "object",
      "additionalProperties": true
    }
  },
  "required": [
    "publication",
    "pages"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/suggestions/contents-map' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"publication":"rh-7k2m9q4d","pages":{"from":1,"to":1}}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.mapContents({
  body: {
    publication: "rh-7k2m9q4d",
    pages: {
      from: 1,
      to: 1
    }
  }
});
Try it
Needs a token (above)

Resolve (or unresolve) a comment on a suggestion's field#

POSTPOST /v1/comments/{id}/resolve

A token with the write scope, or the site sessionresolveComment

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The comment

Body application/json
{
  "type": "object",
  "properties": {
    "resolved": {
      "type": "boolean",
      "description": "false to unresolve"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/comments/1/resolve' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.resolveComment({
  id: 1,
  body: {}
});
Try it
Needs a token (above)

Organize#

Moving, renaming, ordering, merging and splitting: the catalog's tree put in order, as suggestions

The catalog as a tree: the top sets (or one set or sefer), the sets and items under them, and how much each holds#

GETGET /v1/tree

No account neededcatalogTree

Parameters

  • rootstringquery

    A set or a sefer (work); left out, the top sets

  • depthintegerquery

    How many levels down

  • limitintegerquery

    How many (at most 500)

curl 'https://api.chassidushub.org/v1/tree'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.catalogTree();
Try it

What a plan of moves, renames, orderings, new sets and merges would change, item by item, saved nowhere#

POSTPOST /v1/organize/preview

A token with the write scope, or the site sessionpreviewOrganize

Signed in: an API token with the write scope, or the site's session.

Body application/json
{
  "$ref": "#/components/schemas/OrganizePlan"
}
curl -X POST 'https://api.chassidushub.org/v1/organize/preview' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"operations":[{"op":null}]}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.previewOrganize({
  body: {
    operations: [
      {
        op: null
      }
    ]
  }
});
Try it
Needs a token (above)

Organize the catalog: a plan becomes one suggestion, sent for review (apply: true approves it at once where you may approve it yourself)#

POSTPOST /v1/organize

A token with the write scope, or the site sessionorganize

Operations: move, move-up, rename, reorder, create-set, delete-set, merge, split, addition, official. Every old path redirects once it is approved; a merged item's paths lead to the item it was merged into. Signed in: an API token with the write scope, or the site's session.

Body application/json
{
  "$ref": "#/components/schemas/OrganizePlan"
}
curl -X POST 'https://api.chassidushub.org/v1/organize' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"operations":[{"op":null}]}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.organize({
  body: {
    operations: [
      {
        op: null
      }
    ]
  }
});
Try it
Needs a token (above)

Talk#

The conversation on each page

An item's talk page: the conversation about it#

GETGET /v1/entities/{id}/talk

No account neededitemTalk

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

curl 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/talk'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.itemTalk({
  id: "rh-7k2m9q4d"
});
Try it

Comment on an item's talk page#

POSTPOST /v1/entities/{id}/talk

A token with the write scope, or the site sessioncommentOnItem

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10000
    },
    "parent": {
      "type": "integer",
      "description": "The comment this answers"
    }
  },
  "required": [
    "body"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/entities/rh-7k2m9q4d/talk' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.commentOnItem({
  id: "rh-7k2m9q4d",
  body: {
    body: "<body>"
  }
});
Try it
Needs a token (above)

Hide a comment (its author, or a steward)#

POSTPOST /v1/comments/{id}/hide

A token with the write scope, or the site sessionhideComment

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The comment

curl -X POST 'https://api.chassidushub.org/v1/comments/1/hide' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.hideComment({
  id: 1
});
Try it
Needs a token (above)

Change your own comment (on a talk page, a suggestion or an issue)#

PATCHPATCH /v1/comments/{id}

A token with the write scope, or the site sessioneditComment

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The comment

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10000
    }
  },
  "required": [
    "body"
  ]
}
curl -X PATCH 'https://api.chassidushub.org/v1/comments/1' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.editComment({
  id: 1,
  body: {
    body: "<body>"
  }
});
Try it
Needs a token (above)

Reports#

Reporting a problem, takedowns, families' requests

Report a problem (no account needed: a captcha and an hourly limit instead)#

POSTPOST /v1/reports

No account needed; signed in, a little morereport

No account needed; signed in, a little more.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "entityId": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "reason": {
      "enum": [
        "wrong-fact",
        "missing-page",
        "bad-scan",
        "audio-problem",
        "wrong-text",
        "duplicate",
        "rights",
        "offensive",
        "other"
      ]
    },
    "note": {
      "type": "string",
      "maxLength": 10000
    },
    "title": {
      "type": "string",
      "description": "A title of its own, as an issue",
      "maxLength": 200
    },
    "captcha": {
      "type": "string",
      "description": "A Turnstile token, when not signed in"
    }
  },
  "required": [
    "reason"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/reports' \
  -H 'Content-Type: application/json' \
  -d '{"reason":"wrong-fact"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.report({
  body: {
    reason: "wrong-fact"
  }
});
Try it

A set's inbox of reports (stewards, and the set's keepers)#

GETGET /v1/reports

A token (read scope) or the site sessionlistReports

Signed in: an API token (read scope is enough), or the site's session.

Parameters

  • setstringquery

    A set

  • statusopen | resolved | dismissedquery
curl 'https://api.chassidushub.org/v1/reports' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.listReports();
Try it
Needs a token (above)

Resolve or dismiss a report (keepers)#

POSTPOST /v1/reports/{id}/close

A token with the write scope, or the site sessioncloseReport

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The report

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "outcome": {
      "enum": [
        "resolved",
        "dismissed"
      ]
    },
    "changeset": {
      "type": "integer",
      "description": "The suggestion that fixed it"
    },
    "note": {
      "type": "string"
    }
  },
  "required": [
    "outcome"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/reports/1/close' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"outcome":"resolved"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.closeReport({
  id: 1,
  body: {
    outcome: "resolved"
  }
});
Try it
Needs a token (above)

Ask for a file to stop being served (no account needed); stewards answer within two weeks#

POSTPOST /v1/takedowns

No account neededrequestTakedown

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "target": {
      "type": "string",
      "description": "The address of its page, an id, or the file address"
    },
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "relation": {
      "enum": [
        "rights-holder",
        "family",
        "representative",
        "other"
      ]
    },
    "statement": {
      "type": "string",
      "minLength": 10,
      "maxLength": 4000
    },
    "captcha": {
      "type": "string"
    }
  },
  "required": [
    "target",
    "name",
    "email",
    "relation",
    "statement"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/takedowns' \
  -H 'Content-Type: application/json' \
  -d '{"target":"<target>","name":"<name>","email":"<email>","relation":"rights-holder","statement":"<statement>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.requestTakedown({
  body: {
    target: "<target>",
    name: "<name>",
    email: "<email>",
    relation: "rights-holder",
    statement: "<statement>"
  }
});
Try it

A family's request that a teshura not be shown (no account needed): its scans stop being served at once, and stewards review it#

POSTPOST /v1/teshuros/{id}/family-request

No account needed; signed in, a little morefamilyRequest

No account needed; signed in, a little more.

Parameters

  • idstringpathrequired

    A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)

Body application/json
{
  "type": "object",
  "properties": {
    "relation": {
      "type": "string"
    },
    "note": {
      "type": "string"
    },
    "contact": {
      "type": "string"
    },
    "captcha": {
      "type": "string"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/teshuros/rh-7k2m9q4d/family-request' \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.familyRequest({
  id: "rh-7k2m9q4d",
  body: {}
});
Try it

Issues#

Reports kept like issues: titles, labels, assignees, comments, closing

Issues, newest first, with open and closed counts; private ones only for those who may read them#

GETGET /v1/issues

No account needed; signed in, a little morePaged: pass next back as cursorlistIssues

No account needed; signed in, a little more.

Parameters

  • stateopen | closed | allquery

    open (the default), closed or all

  • labelstringquery

    Label names, comma separated

  • typewrong-fact | missing-page | bad-scan | audio-problem | wrong-text | duplicate | rights | offensive | otherquery

    The kind of report

  • setstringquery

    Only about items in this set

  • entitystringquery

    Only about this item

  • assigneestringquery

    A handle, or none

  • authorstringquery

    A handle

  • qstringquery

    Words, or #number

  • beforeintegerquery

    Deprecated: the same as a cursor, as a number

  • limitintegerquery

    How many (at most 100)

  • cursorstringquery

    The `next` of the page before

curl 'https://api.chassidushub.org/v1/issues'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
for await (const item of rh.all('listIssues', {})) {
  console.log(item);
}
Try it

Open an issue (about an item, or the catalog at large)#

POSTPOST /v1/issues

A token with the write scope, or the site sessionopenIssue

Reports of rights or of something offensive are private: stewards and the set's keepers read them. Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "body": {
      "type": "string",
      "maxLength": 10000
    },
    "type": {
      "enum": [
        "wrong-fact",
        "missing-page",
        "bad-scan",
        "audio-problem",
        "wrong-text",
        "duplicate",
        "rights",
        "offensive",
        "other"
      ]
    },
    "entityId": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "labels": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "private": {
      "type": "boolean",
      "description": "Keep it for stewards and keepers"
    }
  },
  "required": [
    "title"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/issues' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Fix the date"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.openIssue({
  body: {
    title: "Fix the date"
  }
});
Try it
Needs a token (above)

The kinds of issue and the words each starts with#

GETGET /v1/issues/templates

No account neededissueTemplates

curl 'https://api.chassidushub.org/v1/issues/templates'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.issueTemplates();
Try it

An issue, its timeline, what the reader may do, and the suggestions that close it#

GETGET /v1/issues/{number}

No account needed; signed in, a little moregetIssue

No account needed; signed in, a little more.

Parameters

  • numberintegerpathrequired

    The issue

curl 'https://api.chassidushub.org/v1/issues/1'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getIssue({
  number: 1
});
Try it

Change its title or words (its author, keepers, stewards)#

PATCHPATCH /v1/issues/{number}

A token with the write scope, or the site sessioneditIssue

Signed in: an API token with the write scope, or the site's session.

Parameters

  • numberintegerpathrequired

    The issue

Body application/json
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 200
    },
    "body": {
      "type": "string"
    }
  }
}
curl -X PATCH 'https://api.chassidushub.org/v1/issues/1' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.editIssue({
  number: 1,
  body: {}
});
Try it
Needs a token (above)

Close as completed or not planned, or reopen#

POSTPOST /v1/issues/{number}/state

A token with the write scope, or the site sessionsetIssueState

Signed in: an API token with the write scope, or the site's session.

Parameters

  • numberintegerpathrequired

    The issue

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "state": {
      "enum": [
        "open",
        "completed",
        "not_planned"
      ]
    },
    "note": {
      "type": "string",
      "maxLength": 2000
    }
  },
  "required": [
    "state"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/issues/1/state' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"state":"open"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.setIssueState({
  number: 1,
  body: {
    state: "open"
  }
});
Try it
Needs a token (above)

Set its labels (keepers, stewards, trusted people)#

PUTPUT /v1/issues/{number}/labels

A token with the write scope, or the site sessionsetIssueLabels

Signed in: an API token with the write scope, or the site's session.

Parameters

  • numberintegerpathrequired

    The issue

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "labels": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "labels"
  ]
}
curl -X PUT 'https://api.chassidushub.org/v1/issues/1/labels' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"labels":["<labels>"]}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.setIssueLabels({
  number: 1,
  body: {
    labels: [
      "<labels>"
    ]
  }
});
Try it
Needs a token (above)

Set who it is assigned to (yourself; others when you may triage)#

PUTPUT /v1/issues/{number}/assignees

A token with the write scope, or the site sessionsetIssueAssignees

Signed in: an API token with the write scope, or the site's session.

Parameters

  • numberintegerpathrequired

    The issue

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "assignees": {
      "type": "array",
      "items": {
        "type": "string",
        "description": "A handle"
      }
    }
  },
  "required": [
    "assignees"
  ]
}
curl -X PUT 'https://api.chassidushub.org/v1/issues/1/assignees' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"assignees":["<assignees>"]}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.setIssueAssignees({
  number: 1,
  body: {
    assignees: [
      "<assignees>"
    ]
  }
});
Try it
Needs a token (above)

Make it private or public (stewards and keepers)#

POSTPOST /v1/issues/{number}/visibility

A token with the write scope, or the site sessionsetIssueVisibility

Signed in: an API token with the write scope, or the site's session.

Parameters

  • numberintegerpathrequired

    The issue

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "private": {
      "type": "boolean"
    }
  },
  "required": [
    "private"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/issues/1/visibility' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"private":true}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.setIssueVisibility({
  number: 1,
  body: {
    private: true
  }
});
Try it
Needs a token (above)

Comment on an issue, or answer a comment#

POSTPOST /v1/issues/{number}/comments

A token with the write scope, or the site sessioncommentOnIssue

@handles are told (their inbox), and #12 links to that suggestion or issue. Signed in: an API token with the write scope, or the site's session.

Parameters

  • numberintegerpathrequired

    The issue

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10000
    },
    "parent": {
      "type": "integer",
      "description": "The comment this answers"
    }
  },
  "required": [
    "body"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/issues/1/comments' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.commentOnIssue({
  number: 1,
  body: {
    body: "<body>"
  }
});
Try it
Needs a token (above)

Every label and how many open issues carry it#

GETGET /v1/labels

No account neededlistLabels

curl 'https://api.chassidushub.org/v1/labels'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.listLabels();
Try it

Make a label (stewards)#

POSTPOST /v1/labels

A token with the write scope, or the site sessioncreateLabel

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9 -]{0,38}[a-z0-9]$"
    },
    "description": {
      "type": "string"
    },
    "color": {
      "type": "string",
      "description": "Six hex digits",
      "pattern": "^[0-9a-f]{6}$"
    }
  },
  "required": [
    "name"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/labels' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"<name>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.createLabel({
  body: {
    name: "<name>"
  }
});
Try it
Needs a token (above)

People#

Handles and profiles; people and conversations to @mention and #mention

People to @mention: handles that start with, or names that contain, what is typed; those in the conversation first#

GETGET /v1/people

No account neededsearchPeople

Parameters

  • qstringquery

    What follows the @

  • idsstringquery

    Account ids, comma separated (at most 100): who each is, instead of a search

  • threadstringquery

    changeset:<id> or report:<id>

  • limitintegerquery

    How many (at most 20)

curl 'https://api.chassidushub.org/v1/people'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.searchPeople();
Try it

A person's public page: who they are, their counts and recent activity (an old handle finds them too, with `movedFrom`)#

GETGET /v1/people/{username}

No account neededgetProfile

Parameters

  • usernamestringpathrequired

    A handle, without the @

  • limitintegerquery

    How many (at most 100)

curl 'https://api.chassidushub.org/v1/people/<username>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getProfile({
  username: "<username>"
});
Try it

Suggestions and issues to #mention, by number or words#

GETGET /v1/threads

No account needed; signed in, a little moresearchThreads

No account needed; signed in, a little more.

Parameters

  • qstringquery

    What follows the #

  • limitintegerquery

    How many (at most 20)

curl 'https://api.chassidushub.org/v1/threads'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.searchThreads();
Try it

Which of the two #12 is: a suggestion or an issue, and its id#

GETGET /v1/threads/{number}

No account needed; signed in, a little morethreadByNumber

No account needed; signed in, a little more.

Parameters

  • numberintegerpathrequired

    The number after #

curl 'https://api.chassidushub.org/v1/threads/1'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.threadByNumber({
  number: 1
});
Try it

Inbox#

What concerns you: mentions, review requests, assignments, what you follow

Your inbox, newest first: mentions, review requests, assignments and what you follow#

GETGET /v1/inbox

A token (read scope) or the site sessionPaged: pass next back as cursorinbox

Signed in: an API token (read scope is enough), or the site's session.

Parameters

  • filterunread | all | mention | review_requested | assigned | author | comment | review | state | followedquery

    unread, all, or one reason

  • beforestringquery

    Deprecated: lines older than this time; use cursor

  • limitintegerquery

    How many (at most 100)

  • cursorstringquery

    The `next` of the page before

curl 'https://api.chassidushub.org/v1/inbox' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
for await (const item of rh.all('inbox', {})) {
  console.log(item);
}
Try it
Needs a token (above)

How many inbox lines are unread#

GETGET /v1/inbox/count

A token (read scope) or the site sessioninboxCount

Signed in: an API token (read scope is enough), or the site's session.

curl 'https://api.chassidushub.org/v1/inbox/count' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.inboxCount();
Try it
Needs a token (above)

Mark inbox lines read (or unread): by id, by conversation, or all#

POSTPOST /v1/inbox/read

A token with the write scope, or the site sessionmarkInboxRead

Signed in: an API token with the write scope, or the site's session.

Body application/json
{
  "type": "object",
  "properties": {
    "ids": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    },
    "subject": {
      "type": "object",
      "properties": {
        "kind": {
          "enum": [
            "changeset",
            "report",
            "entity",
            "project"
          ]
        },
        "id": {
          "type": "string"
        }
      },
      "required": [
        "kind",
        "id"
      ]
    },
    "all": {
      "type": "boolean"
    },
    "unread": {
      "type": "boolean",
      "description": "true: mark them unread"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/inbox/read' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.markInboxRead({
  body: {}
});
Try it
Needs a token (above)

Projects#

Group efforts through a gap, the Missing board

The Missing board: farbrengens without a recording or a text, sefarim without a scan, files lost upstream#

GETGET /v1/missing

No account neededmissing

Parameters

  • kindrecordings | texts | scans | filesqueryrequired

    What is missing

  • withinstringquery

    For recordings and texts: a year or a month

  • limitintegerquery

    How many (at most 500)

curl 'https://api.chassidushub.org/v1/missing?kind=recordings'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.missing({
  kind: "recordings"
});
Try it

Projects working through a gap, with their progress#

GETGET /v1/projects

No account neededlistProjects

Parameters

  • statusopen | merged | closedquery
curl 'https://api.chassidushub.org/v1/projects'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.listProjects();
Try it

Open a project on a gap (farbrengens without recordings or texts, recordings to sync, pages to proofread)#

POSTPOST /v1/projects

A token with the write scope, or the site sessioncreateProject

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "slug": {
      "type": "string",
      "pattern": "^[a-z0-9-]+$"
    },
    "name": {
      "type": "string"
    },
    "goal": {
      "type": "string"
    },
    "set": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "missing": {
      "enum": [
        "recordings",
        "texts",
        "sync",
        "proofreading"
      ]
    },
    "within": {
      "type": "string"
    },
    "scan": {
      "type": "string",
      "description": "A permanent id: rh- and letters and digits (read forgivingly: RH-7K2M-9Q4D works)",
      "pattern": "^[rR][hH]-[0-9A-Za-z-]+$",
      "examples": [
        "rh-7k2m9q4d"
      ]
    },
    "level": {
      "enum": [
        1,
        2
      ]
    }
  },
  "required": [
    "slug",
    "name"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/projects' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"slug":"<slug>","name":"<name>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.createProject({
  body: {
    slug: "<slug>",
    name: "<name>"
  }
});
Try it
Needs a token (above)

A project, its progress and what is left to do#

GETGET /v1/projects/{slug}

No account neededgetProject

Parameters

  • slugstringpathrequired

    A project's short name

curl 'https://api.chassidushub.org/v1/projects/<slug>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getProject({
  slug: "<slug>"
});
Try it

Hand me the next item nobody holds (held for you for a few hours)#

POSTPOST /v1/projects/{slug}/next

A token with the write scope, or the site sessionclaimNext

Signed in: an API token with the write scope, or the site's session.

Parameters

  • slugstringpathrequired

    A project's short name

curl -X POST 'https://api.chassidushub.org/v1/projects/<slug>/next' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.claimNext({
  slug: "<slug>"
});
Try it
Needs a token (above)

Let go of an item you held#

POSTPOST /v1/projects/{slug}/release

A token with the write scope, or the site sessionreleaseClaim

Signed in: an API token with the write scope, or the site's session.

Parameters

  • slugstringpathrequired

    A project's short name

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "item": {
      "type": "string"
    }
  },
  "required": [
    "item"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/projects/<slug>/release' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"item":"<item>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.releaseClaim({
  slug: "<slug>",
  body: {
    item: "<item>"
  }
});
Try it
Needs a token (above)

Close a project (its keepers, stewards)#

POSTPOST /v1/projects/{slug}/close

A token with the write scope, or the site sessioncloseProject

Signed in: an API token with the write scope, or the site's session.

Parameters

  • slugstringpathrequired

    A project's short name

curl -X POST 'https://api.chassidushub.org/v1/projects/<slug>/close' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.closeProject({
  slug: "<slug>"
});
Try it
Needs a token (above)

Personal#

What you follow, where you stopped

What you follow, the items themselves, and what changed in them lately#

GETGET /v1/follows

A token (read scope) or the site sessionlistFollows

Signed in: an API token (read scope is enough), or the site's session.

Parameters

  • limitintegerquery

    How many (at most 100)

curl 'https://api.chassidushub.org/v1/follows' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.listFollows();
Try it
Needs a token (above)

Follow or unfollow an item, set, project, suggestion or issue#

POSTPOST /v1/follows

A token with the write scope, or the site sessionfollow

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "kind": {
      "enum": [
        "entity",
        "set",
        "project",
        "changeset",
        "report"
      ]
    },
    "id": {
      "type": "string"
    },
    "on": {
      "type": "boolean",
      "description": "false to unfollow"
    }
  },
  "required": [
    "kind",
    "id"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/follows' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"kind":"entity","id":"<id>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.follow({
  body: {
    kind: "entity",
    id: "<id>"
  }
});
Try it
Needs a token (above)

Where you stopped reading and listening lately (never cached)#

GETGET /v1/places

A token (read scope) or the site sessionlistPlaces

Signed in: an API token (read scope is enough), or the site's session.

Parameters

  • kindread | listenquery
  • keystringquery

    One thing only

  • limitintegerquery

    How many (at most 60)

curl 'https://api.chassidushub.org/v1/places' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.listPlaces();
Try it
Needs a token (above)

Keep where you stopped in one thing#

PUTPUT /v1/places

A token with the write scope, or the site sessionsavePlace

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "kind": {
      "enum": [
        "read",
        "listen"
      ]
    },
    "key": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "sub": {
      "type": "string"
    },
    "href": {
      "type": "string"
    },
    "place": {
      "type": "object",
      "additionalProperties": true
    }
  },
  "required": [
    "kind",
    "key",
    "title",
    "href",
    "place"
  ]
}
curl -X PUT 'https://api.chassidushub.org/v1/places' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"kind":"read","key":"<key>","title":"Fix the date","href":"<href>","place":{}}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.savePlace({
  body: {
    kind: "read",
    key: "<key>",
    title: "Fix the date",
    href: "<href>",
    place: {}
  }
});
Try it
Needs a token (above)

Forget one place#

DELETEDELETE /v1/places

A token with the write scope, or the site sessionforgetPlace

Signed in: an API token with the write scope, or the site's session.

Parameters

  • kindread | listenqueryrequired
  • keystringqueryrequired

    The thing

curl -X DELETE 'https://api.chassidushub.org/v1/places?kind=read&key=%3Ckey%3E' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.forgetPlace({
  kind: "read",
  key: "<key>"
});
Try it
Needs a token (above)

Webhooks#

Every merge posted to your address, signed

Your webhooks: addresses every merge is posted to#

GETGET /v1/webhooks

A token (read scope) or the site sessionlistWebhooks

Signed in: an API token (read scope is enough), or the site's session.

curl 'https://api.chassidushub.org/v1/webhooks' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.listWebhooks();
Try it
Needs a token (above)

Add a webhook (up to five); its signing secret is shown this once#

POSTPOST /v1/webhooks

A token with the write scope, or the site sessioncreateWebhook

Signed in: an API token with the write scope, or the site's session.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "https://…",
      "format": "uri"
    }
  },
  "required": [
    "url"
  ]
}
curl -X POST 'https://api.chassidushub.org/v1/webhooks' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"url":"<url>"}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.createWebhook({
  body: {
    url: "<url>"
  }
});
Try it
Needs a token (above)

Remove a webhook#

DELETEDELETE /v1/webhooks/{id}

A token with the write scope, or the site sessiondeleteWebhook

Signed in: an API token with the write scope, or the site's session.

Parameters

  • idintegerpathrequired

    The webhook

curl -X DELETE 'https://api.chassidushub.org/v1/webhooks/1' \
  -H "Authorization: Bearer $CHASSIDUSHUB_TOKEN"
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub({ token: process.env.CHASSIDUSHUB_TOKEN });
const answer = await rh.deleteWebhook({
  id: 1
});
Try it
Needs a token (above)

Tokens#

Personal API tokens, made on the account page, and apps connected with OAuth

Your API tokens (their prefixes only), revoked ones marked#

GETGET /v1/tokens

The site's own pages only; not for tokenslistTokens

Only from the site's own pages, signed in; an API token cannot do this.

curl
curl 'https://api.chassidushub.org/v1/tokens'

Make an API token; the token itself is shown this once#

POSTPOST /v1/tokens

The site's own pages only; not for tokenscreateToken

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "What uses it",
      "minLength": 1,
      "maxLength": 80
    },
    "scopes": {
      "type": "array",
      "items": {
        "enum": [
          "read",
          "write"
        ]
      },
      "description": "Default: read"
    },
    "expiresInDays": {
      "type": "integer",
      "minimum": 1,
      "maximum": 3650
    }
  },
  "required": [
    "name"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/tokens' \
  -H 'Content-Type: application/json' \
  -d '{"name":"<name>"}'

Revoke a token, or end a connected app; it stops working at once#

DELETEDELETE /v1/tokens/{id}

The site's own pages only; not for tokensrevokeToken

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • idstringpathrequired

    tok-… for a token, oac-… for a connected app

curl
curl -X DELETE 'https://api.chassidushub.org/v1/tokens/<id>'

OAuth#

Connecting an app (Claude, other MCP clients) as a person: OAuth 2.1 with PKCE, registration and metadata

The API's Protected Resource Metadata (RFC 9728): which authorization server gives its tokens#

GETGET /.well-known/oauth-protected-resource

No account neededprotectedResource

curl 'https://api.chassidushub.org/.well-known/oauth-protected-resource'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.protectedResource();
Try it

The MCP server's Protected Resource Metadata (RFC 9728), named in its 401's WWW-Authenticate#

GETGET /.well-known/oauth-protected-resource/mcp

No account neededmcpProtectedResource

curl 'https://api.chassidushub.org/.well-known/oauth-protected-resource/mcp'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.mcpProtectedResource();
Try it

Authorization Server Metadata (RFC 8414): the endpoints, scopes read and write, PKCE S256, registration and Client ID Metadata Documents#

GETGET /.well-known/oauth-authorization-server

No account neededauthorizationServer

curl 'https://api.chassidushub.org/.well-known/oauth-authorization-server'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.authorizationServer();
Try it

Register an app (RFC 7591): its name and redirect addresses; a secret only if it asks for one#

POSTPOST /oauth/register

No account neededoauthRegister

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "client_name": {
      "type": "string"
    },
    "client_uri": {
      "type": "string"
    },
    "redirect_uris": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "https, http://localhost, or an app's own scheme"
    },
    "token_endpoint_auth_method": {
      "enum": [
        "none",
        "client_secret_post",
        "client_secret_basic"
      ]
    },
    "grant_types": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "response_types": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "redirect_uris"
  ]
}
curl -X POST 'https://api.chassidushub.org/oauth/register' \
  -H 'Content-Type: application/json' \
  -d '{"redirect_uris":["<redirect_uris>"]}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.oauthRegister({
  body: {
    redirect_uris: [
      "<redirect_uris>"
    ]
  }
});
Try it

Start connecting (authorization code with PKCE): the person is sent to the site's consent page, then back to the app#

GETGET /oauth/authorize

No account neededoauthAuthorize

Parameters

  • response_typecodequeryrequired
  • client_idstringqueryrequired

    A registered client_id, or the https address of the app's Client ID Metadata Document

  • redirect_uristringquery
  • scopestringquery

    read, write or both, space separated (default both; the person may allow reading only)

  • statestringquery
  • code_challengestringqueryrequired

    base64url sha256 of the verifier

  • code_challenge_methodS256queryrequired
  • resourcestringquery

    RFC 8707: https://api.chassidushub.org/mcp (the MCP server) or https://api.chassidushub.org (the whole API)

  • ui_localesstringquery

    he for the consent page in Hebrew (English otherwise)

curl 'https://api.chassidushub.org/oauth/authorize?response_type=code&client_id=%3Cclient_id%3E&code_challenge=%3Ccode_challenge%3E&code_challenge_method=S256'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.oauthAuthorize({
  response_type: "code",
  client_id: "<client_id>",
  code_challenge: "<code_challenge>",
  code_challenge_method: "S256"
});
Try it

Trade a code (with its PKCE verifier) or a refresh token for an access token (an hour) and a new refresh token#

POSTPOST /oauth/token

No account neededoauthToken

Body application/x-www-form-urlencodedrequired
{
  "type": "string",
  "format": "binary"
}
curl -X POST 'https://api.chassidushub.org/oauth/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' --data-binary @file
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.oauthToken({
  body: file,
  contentType: "application/pdf"
});

Revoke an access or refresh token (RFC 7009): the whole connection ends#

POSTPOST /oauth/revoke

No account neededoauthRevoke

Body application/x-www-form-urlencodedrequired
{
  "type": "string",
  "format": "binary"
}
curl -X POST 'https://api.chassidushub.org/oauth/revoke' \
  -H 'Content-Type: application/x-www-form-urlencoded' --data-binary @file
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.oauthRevoke({
  body: file,
  contentType: "application/pdf"
});

An app's request to connect, for the consent page: the app, where it sends the person back, the scopes#

GETGET /v1/oauth/requests/{id}

The site's own pages only; not for tokensoauthRequest

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • idstringpathrequired
curl
curl 'https://api.chassidushub.org/v1/oauth/requests/<id>'

The person's answer to an app's request to connect; answers where to send the browser#

POSTPOST /v1/oauth/requests/{id}

The site's own pages only; not for tokensoauthDecide

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • idstringpathrequired
Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "approve": {
      "type": "boolean"
    },
    "scopes": {
      "type": "array",
      "items": {
        "enum": [
          "read",
          "write"
        ]
      },
      "description": "Allowed; never more than asked"
    }
  },
  "required": [
    "approve"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/oauth/requests/<id>' \
  -H 'Content-Type: application/json' \
  -d '{"approve":true}'

Mirrors#

Editions and their signed dumps

Everything a mirror needs: the git mirror, the release keys, every edition and its dumps#

GETGET /v1/mirrors

No account neededmirrors

curl 'https://api.chassidushub.org/v1/mirrors'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.mirrors();
Try it

Catalog editions (dated snapshots) and their dumps, each with its size, sha256 and address#

GETGET /v1/editions

No account needededitions

curl 'https://api.chassidushub.org/v1/editions'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.editions();
Try it

An edition's signed manifest (Ed25519), exactly as signed#

GETGET /v1/editions/{tag}/manifest.json

No account needededitionManifest

Parameters

  • tagstringpathrequired
curl 'https://api.chassidushub.org/v1/editions/2026.40/manifest.json'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.editionManifest({
  tag: "2026.40"
});
Try it

An edition's checksums, for sha256sum -c#

GETGET /v1/editions/{tag}/SHA256SUMS

No account needededitionChecksums

Parameters

  • tagstringpathrequired
curl 'https://api.chassidushub.org/v1/editions/<tag>/SHA256SUMS'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.editionChecksums({
  tag: "<tag>"
});
Try it

One of an edition's dumps (SQLite, JSON Lines, Parquet)#

GETGET /dumps/{tag}/{name}

No account neededgetDump

Parameters

  • tagstringpathrequired
  • namestringpathrequired
curl 'https://api.chassidushub.org/dumps/<tag>/<name>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.getDump({
  tag: "<tag>",
  name: "<name>"
});
Try it

Apps#

The Sichos Kodesh apps' catalog, at the paths and in the shapes they read

The Sichos Kodesh apps' catalog manifest: the served release's version, size, sha256 and address#

GETGET /v1/app/{schema}/catalog/manifest.json

No account neededappCatalogManifest

The same fields as Sichos-Kodesh's own catalog API (its `CatalogManifest`). The version is `2.<commit>.0`; a release missing a part the app needs (listed in `missing`) is numbered `0.<commit>.0`, so no app takes it.

Parameters

  • schemav1 | v2 | v3pathrequired

    The catalog schema: v1 the farbrengens (the web app), v2 with the library, v3 with the works (the phone)

curl 'https://api.chassidushub.org/v1/app/v1/catalog/manifest.json'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appCatalogManifest({
  schema: "v1"
});
Try it

The apps' catalog changelog alone#

GETGET /v1/app/{schema}/catalog/changelog.json

No account neededappCatalogChangelog

Parameters

  • schemav1 | v2 | v3pathrequired

    The catalog schema: v1 the farbrengens (the web app), v2 with the library, v3 with the works (the phone)

curl 'https://api.chassidushub.org/v1/app/v1/catalog/changelog.json'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appCatalogChangelog({
  schema: "v1"
});
Try it

Redirects to the served release's catalog.json#

GETGET /v1/app/{schema}/catalog/latest/catalog.json

No account neededappCatalogLatest

Parameters

  • schemav1 | v2 | v3pathrequired

    The catalog schema: v1 the farbrengens (the web app), v2 with the library, v3 with the works (the phone)

curl 'https://api.chassidushub.org/v1/app/v1/catalog/latest/catalog.json'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appCatalogLatest({
  schema: "v1"
});
Try it

The apps' catalog: the farbrengens by year (v1), with the library (v2) and the works (v3)#

GETGET /v1/app/{schema}/catalog/{version}/catalog.json

No account neededappCatalogRelease

Byte for byte what the manifest's sha256 describes (also the ETag). Only the served version is found.

Parameters

  • schemav1 | v2 | v3pathrequired

    The catalog schema: v1 the farbrengens (the web app), v2 with the library, v3 with the works (the phone)

  • versionstringpathrequired

    The version the manifest names

curl 'https://api.chassidushub.org/v1/app/v1/catalog/<version>/catalog.json'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appCatalogRelease({
  schema: "v1",
  version: "<version>"
});
Try it

A text of a sefer, where the apps look for it (the same as /v1/texts/{sha256})#

GETGET /v1/app/v3/texts/{sha256}

No account neededappSourceText

Parameters

  • sha256stringpathrequired

    A file, named by its sha256

curl 'https://api.chassidushub.org/v1/app/v3/texts/<sha256>'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appSourceText({
  sha256: "<sha256>"
});
Try it

The item an app's fix or report link is about, by the app's own ids#

GETGET /v1/app/item

No account neededappItem

A farbrengen by `farbrengen` (its mafteiach number), a sefer by `work`, a page of it by `work` and `unit`; a page not found gives its sefer.

Parameters

  • farbrengenstringquery
  • workstringquery
  • unitstringquery
curl 'https://api.chassidushub.org/v1/app/item'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appItem();
Try it

The phone app's newest release: redirects to the reader's packs Worker#

GETGET /v1/app/v1/app/android/latest.json

No account neededappAndroidLatest

curl 'https://api.chassidushub.org/v1/app/v1/app/android/latest.json'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appAndroidLatest();
Try it

The phone app's APK: redirects to the reader's packs Worker#

GETGET /v1/app/v1/app/android/download/{abi}

No account neededappAndroidDownload

Parameters

  • abiarm64-v8a | armeabi-v7a | universalpathrequired
curl 'https://api.chassidushub.org/v1/app/v1/app/android/download/arm64-v8a'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.appAndroidDownload({
  abi: "arm64-v8a"
});
Try it

Libraries#

OAI-PMH and IIIF

A served scan as a IIIF Presentation 3 manifest, for any IIIF viewer#

GETGET /manifests/iiif/{file}

No account needediiifManifest

Parameters

  • filestringpathrequired

    The scan's id and .json

curl 'https://api.chassidushub.org/manifests/iiif/rh-7k2m9q4d'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.iiifManifest({
  file: "rh-7k2m9q4d"
});
Try it

OAI-PMH 2.0 for libraries (oai_dc records), when switched on#

GETGET /oai

No account neededoai

Parameters

  • verbIdentify | ListMetadataFormats | ListSets | ListIdentifiers | ListRecords | GetRecordqueryrequired
  • metadataPrefixstringquery
  • identifierstringquery
  • fromstringquery
  • untilstringquery
  • setstringquery
  • resumptionTokenstringquery
curl 'https://api.chassidushub.org/oai?verb=Identify'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.oai({
  verb: "Identify"
});
Try it

OAI-PMH, the same arguments sent as a form#

POSTPOST /oai

No account neededoaiPost

Body application/x-www-form-urlencodedrequired
{
  "type": "string",
  "format": "binary"
}
curl -X POST 'https://api.chassidushub.org/oai' \
  -H 'Content-Type: application/x-www-form-urlencoded' --data-binary @file
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.oaiPost({
  body: file,
  contentType: "application/pdf"
});

Agents#

llms.txt and the MCP server

A short guide for AI agents (llms.txt)#

GETGET /llms.txt

No account neededllmsTxt

curl 'https://api.chassidushub.org/llms.txt'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.llmsTxt();
Try it

What crawlers may read on the API: the guides and the files, not the routes#

GETGET /robots.txt

No account neededrobotsTxt

curl 'https://api.chassidushub.org/robots.txt'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.robotsTxt();
Try it

The Model Context Protocol server (Streamable HTTP, JSON answers, no sessions)#

POSTPOST /mcp

No account needed; signed in, a little moremcp

Tools: search, get_item, list_children, get_text, suggest_fix, list_issues, open_issue. Send JSON-RPC 2.0. Reading needs no account. A writing tool without a token answers 401 with WWW-Authenticate naming the Protected Resource Metadata (so MCP clients such as claude.ai ask the person to connect with OAuth), and with a read-only token 403 insufficient_scope. See docs/developers/agents.md. No account needed; signed in, a little more.

Body application/json
{
  "type": "object",
  "additionalProperties": true,
  "description": "A JSON-RPC 2.0 message, or a batch"
}
curl -X POST 'https://api.chassidushub.org/mcp' \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.mcp({
  body: {}
});
Try it

Not offered: this server opens no event stream#

GETGET /mcp

No account neededmcpStream

curl
curl 'https://api.chassidushub.org/mcp'
Try it

Not offered: there are no sessions to end#

DELETEDELETE /mcp

No account neededmcpEnd

curl
curl -X DELETE 'https://api.chassidushub.org/mcp'
Try it

Sign-in#

The site's own sign-in; listed for completeness, not for other clients

Who is signed in, with their passkeys, Google accounts, emails and notifications#

GETGET /v1/auth/me

The site's own pages only; not for tokensme

Only from the site's own pages, signed in; an API token cannot do this.

curl
curl 'https://api.chassidushub.org/v1/auth/me'

A new account: the options for making a passkey#

POSTPOST /v1/auth/passkey/register/options

The site's own pages only; not for tokenspasskeyRegisterOptions

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "username": {
      "type": "string",
      "description": "A handle; else one is made from the name"
    }
  },
  "required": [
    "name"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/passkey/register/options' \
  -H 'Content-Type: application/json' \
  -d '{"name":"<name>"}'

A new account: the passkey made, checked; signs in#

POSTPOST /v1/auth/passkey/register/verify

The site's own pages only; not for tokenspasskeyRegisterVerify

Only from the site's own pages, signed in; an API token cannot do this.

Body application/json
{
  "type": "object",
  "additionalProperties": true
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/passkey/register/verify' \
  -H 'Content-Type: application/json' \
  -d '{}'

Another passkey for this account: its options#

POSTPOST /v1/auth/passkey/add/options

The site's own pages only; not for tokenspasskeyAddOptions

Only from the site's own pages, signed in; an API token cannot do this.

curl
curl -X POST 'https://api.chassidushub.org/v1/auth/passkey/add/options'

Another passkey for this account, checked and kept#

POSTPOST /v1/auth/passkey/add/verify

The site's own pages only; not for tokenspasskeyAddVerify

Only from the site's own pages, signed in; an API token cannot do this.

Body application/json
{
  "type": "object",
  "additionalProperties": true
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/passkey/add/verify' \
  -H 'Content-Type: application/json' \
  -d '{}'

Whether a handle can be had, and a free one suggested from a name#

GETGET /v1/auth/username

The site's own pages only; not for tokenscheckUsername

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • namestringquery

    The handle wanted

  • fromstringquery

    A name to suggest one from

curl
curl 'https://api.chassidushub.org/v1/auth/username'

Choose a new handle; the old one keeps leading to you (never with a token)#

POSTPOST /v1/auth/username

The site's own pages only; not for tokenssetUsername

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "username": {
      "type": "string"
    }
  },
  "required": [
    "username"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/username' \
  -H 'Content-Type: application/json' \
  -d '{"username":"<username>"}'

Change the name you go by#

POSTPOST /v1/auth/name

The site's own pages only; not for tokensrename

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    }
  },
  "required": [
    "name"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/name' \
  -H 'Content-Type: application/json' \
  -d '{"name":"<name>"}'

Signing in with a passkey: its options#

POSTPOST /v1/auth/passkey/sign-in/options

The site's own pages only; not for tokenspasskeySignInOptions

Only from the site's own pages, signed in; an API token cannot do this.

curl
curl -X POST 'https://api.chassidushub.org/v1/auth/passkey/sign-in/options'

Signing in with a passkey: checked; signs in#

POSTPOST /v1/auth/passkey/sign-in/verify

The site's own pages only; not for tokenspasskeySignInVerify

Only from the site's own pages, signed in; an API token cannot do this.

Body application/json
{
  "type": "object",
  "additionalProperties": true
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/passkey/sign-in/verify' \
  -H 'Content-Type: application/json' \
  -d '{}'

Signing in with Google: off to Google#

GETGET /v1/auth/google/start

The site's own pages only; not for tokensgoogleStart

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • returnstringquery

    Where on the site to come back to

curl
curl 'https://api.chassidushub.org/v1/auth/google/start'

Signing in with Google: back from Google#

GETGET /v1/auth/google/callback

The site's own pages only; not for tokensgoogleCallback

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • statestringquery
  • codestringquery
curl
curl 'https://api.chassidushub.org/v1/auth/google/callback'

Signing in by email: send a link#

POSTPOST /v1/auth/email/start

The site's own pages only; not for tokensemailStart

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string"
    },
    "return": {
      "type": "string"
    },
    "lang": {
      "type": "string"
    }
  },
  "required": [
    "email"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/email/start' \
  -H 'Content-Type: application/json' \
  -d '{"email":"<email>"}'

Signing in by email: what a link is for, before using it#

POSTPOST /v1/auth/email/check

The site's own pages only; not for tokensemailCheck

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "token": {
      "type": "string"
    }
  },
  "required": [
    "token"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/email/check' \
  -H 'Content-Type: application/json' \
  -d '{"token":"<token>"}'

Signing in by email: use the link; signs in#

POSTPOST /v1/auth/email/verify

The site's own pages only; not for tokensemailVerify

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "token": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "username": {
      "type": "string",
      "description": "For a new account: a handle"
    }
  },
  "required": [
    "token"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/email/verify' \
  -H 'Content-Type: application/json' \
  -d '{"token":"<token>"}'

Email about what you follow: off, a daily digest, or at once#

POSTPOST /v1/auth/notifications

The site's own pages only; not for tokenssetNotifications

Only from the site's own pages, signed in; an API token cannot do this.

Body application/jsonrequired
{
  "type": "object",
  "properties": {
    "mode": {
      "enum": [
        "off",
        "daily",
        "immediate"
      ]
    },
    "email": {
      "type": "string"
    },
    "lang": {
      "type": "string"
    }
  },
  "required": [
    "mode"
  ]
}
curl
curl -X POST 'https://api.chassidushub.org/v1/auth/notifications' \
  -H 'Content-Type: application/json' \
  -d '{"mode":"off"}'

Stop email updates, from the link in any of them (no sign-in)#

POSTPOST /v1/auth/email/unsubscribe

No account neededunsubscribe

Parameters

  • tokenstringquery
Body application/json
{
  "type": "object",
  "properties": {
    "token": {
      "type": "string"
    }
  }
}
curl -X POST 'https://api.chassidushub.org/v1/auth/email/unsubscribe' \
  -H 'Content-Type: application/json' \
  -d '{}'
import { ChassidusHub } from '@chassidushub/client';

const rh = new ChassidusHub();
const answer = await rh.unsubscribe({
  body: {}
});
Try it

Sign out this browser#

POSTPOST /v1/auth/sign-out

The site's own pages only; not for tokenssignOut

Only from the site's own pages, signed in; an API token cannot do this.

curl
curl -X POST 'https://api.chassidushub.org/v1/auth/sign-out'

Stewards#

The stewards' tools on the site; listed for completeness

Everyone with an account (stewards)#

GETGET /v1/admin/people

The site's own pages only; not for tokenslistPeople

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • qstringquery

    A name or id

curl
curl 'https://api.chassidushub.org/v1/admin/people'

Appoint or remove a steward or admin (admins)#

POSTPOST /v1/admin/people/{id}/role

The site's own pages only; not for tokenssetRole

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • idstringpathrequired
Body application/json
{
  "type": "object",
  "properties": {
    "steward": {
      "type": "boolean"
    },
    "admin": {
      "type": "boolean"
    }
  }
}
curl
curl -X POST 'https://api.chassidushub.org/v1/admin/people/<id>/role' \
  -H 'Content-Type: application/json' \
  -d '{}'

Suspend or restore an account (its API tokens are revoked)#

POSTPOST /v1/admin/people/{id}/suspend

The site's own pages only; not for tokenssuspend

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • idstringpathrequired
Body application/json
{
  "type": "object",
  "properties": {
    "on": {
      "type": "boolean"
    },
    "reason": {
      "type": "string"
    }
  }
}
curl
curl -X POST 'https://api.chassidushub.org/v1/admin/people/<id>/suspend' \
  -H 'Content-Type: application/json' \
  -d '{}'

Takedown requests, with the files each points at#

GETGET /v1/admin/takedowns

The site's own pages only; not for tokenslistTakedowns

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • statusopen | resolved | dismissedquery
curl
curl 'https://api.chassidushub.org/v1/admin/takedowns'

Take a file down: kept privately, no longer served#

POSTPOST /v1/admin/files/{sha256}/takedown

The site's own pages only; not for tokenstakeDown

Only from the site's own pages, signed in; an API token cannot do this.

Parameters

  • sha256stringpathrequired

    A file, named by its sha256

Body application/json
{
  "type": "object",
  "properties": {
    "report": {
      "type": "integer"
    }
  }
}
curl
curl -X POST 'https://api.chassidushub.org/v1/admin/files/<sha256>/takedown' \
  -H 'Content-Type: application/json' \
  -d '{}'