RebbeHub
עב · EN
RebbeHub

DevelopersUsing the API

API reference

RebbeHub API 1.0.0: 173 routes in 23 groups, read from the API's own OpenAPI document.

Base URLhttps://api.rebbehub.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.rebbehub.org/'
Try it

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

GETGET /v1

No account neededabout

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

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

This document#

GETGET /openapi.json

No account neededopenapi

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

const rh = new RebbeHub();
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.rebbehub.org/v1/stats'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/community'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
const answer = await rh.community();
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.rebbehub.org/v1/health'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/types'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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

  • afterstringquery

    Deprecated: the same as cursor

  • limitintegerquery

    How many (at most 500)

  • cursorstringquery

    The `next` of the page before

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

const rh = new RebbeHub();
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.rebbehub.org/v1/entities/batch?ids=%3Cids%3E'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/entities/rh-7k2m9q4d'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/entities/rh-7k2m9q4d/children?field=%3Cfield%3E&type=%3Ctype%3E'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/entities/rh-7k2m9q4d/linked/counts'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
const answer = await rh.linkedCounts({
  id: "rh-7k2m9q4d"
});
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…)

  • 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.rebbehub.org/v1/entities/rh-7k2m9q4d/linked?field=%3Cfield%3E'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
for await (const item of rh.all('listLinked', {
  id: "rh-7k2m9q4d",
  field: "<field>"
})) {
  console.log(item);
}
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.rebbehub.org/v1/entities/rh-7k2m9q4d/history'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/entities/rh-7k2m9q4d/relations'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/revisions/1'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/resolve?path=%2Fevents%2F5742-05-10'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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

  • limitintegerquery

    How many (at most 2000)

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

const rh = new RebbeHub();
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.rebbehub.org/v1/refcounts?field=%3Cfield%3E'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/sitemap'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/sitemap/set/1'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/works/rh-7k2m9q4d/outline'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/works/rh-7k2m9q4d/parts/<part>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
const answer = await rh.workPart({
  id: "rh-7k2m9q4d",
  part: "<part>"
});
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)

  • cursorstringquery

    The `next` of the page before

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

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

Texts#

Scans' texts line by line, printings compared, translations

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.rebbehub.org/v1/scans/rh-7k2m9q4d/text'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/scans/rh-7k2m9q4d/progress'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/scans/rh-7k2m9q4d/text/fix' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"page":1,"line":"<line>","text":"<text>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/scans/rh-7k2m9q4d/text/confirm' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"page":1}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/scans/rh-7k2m9q4d/ocr' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"content":"<content>","engine":{"name":"<name>","version":"<version>"}}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/scans/rh-7k2m9q4d/text/seed' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"layer":"rh-7k2m9q4d"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/units/rh-7k2m9q4d/printings'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/compare?a=%3Ca%3E&b=%3Cb%3E'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/units/rh-7k2m9q4d/translations' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"language":"<language>","credit":"<credit>","content":"<content>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/translations/fix' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"segment":"rh-7k2m9q4d","content":"<content>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/hanachos/text' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"content":"<content>","rights":"mine"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/texts/<sha256>'
import { RebbeHub } from '@rebbehub/client';

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

Media#

Transcripts and their sync

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.rebbehub.org/v1/recordings/rh-7k2m9q4d/transcript'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
const answer = await rh.recordingTranscript({
  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"
    }
  },
  "required": [
    "segment",
    "content"
  ]
}
curl -X POST 'https://api.rebbehub.org/v1/recordings/rh-7k2m9q4d/transcript/fix' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"segment":"rh-7k2m9q4d","content":"<content>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/recordings/rh-7k2m9q4d/sync/anchor' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"segment":"rh-7k2m9q4d","atMs":1}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/recordings/rh-7k2m9q4d/sync/confirm' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

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

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.rebbehub.org/v1/recordings/rh-7k2m9q4d/hanacha'
import { RebbeHub } from '@rebbehub/client';

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

Files#

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

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.rebbehub.org/v1/files/<sha256>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/files/<sha256>/similar'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/page-fixes/drive/<id>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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 RebbeHub passes on (300 MB) answer 413.

Parameters

  • idstringpathrequired

    A Google Drive file id

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

const rh = new RebbeHub();
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.rebbehub.org/objects/<sha256>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/manifests/<collection>/<name>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/scans/rh-7k2m9q4d/pages'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/uploads?what=recording&rights=mine' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/pdf' --data-binary @file
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/uploads/check' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"for":"rh-7k2m9q4d"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/uploads/propose' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"what":"hanacha"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/files/<sha256>/about'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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 RebbeHub only links to is served; the PDF is not (its file page links to the source).

Parameters

  • idsstringquery

    The sefarim

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

const rh = new RebbeHub();
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.rebbehub.org/v1/works/rh-7k2m9q4d/cover'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/entities/rh-7k2m9q4d/restore' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"rev":1}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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

  • 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.rebbehub.org/v1/suggestions'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/suggestions' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Fix the date"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/quick' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"entityId":"rh-7k2m9q4d","data":{}}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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`)#

GETGET /v1/suggestions/{id}

No account needed; signed in, a little moregetSuggestion

No account needed; signed in, a little more.

Parameters

  • idintegerpathrequired

    The suggestion

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

const rh = new RebbeHub();
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.rebbehub.org/v1/suggestions/1' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/conversation'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/suggestions/1/comments' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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"
    }
  },
  "required": [
    "verdict"
  ]
}
curl -X POST 'https://api.rebbehub.org/v1/suggestions/1/reviews' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"verdict":"approve"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/review-requests' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"reviewers":["<reviewers>"]}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/review-requests/<username>' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/items' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"type":"<type>","data":{}}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/submit' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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"
    },
    "note": {
      "type": "string"
    }
  }
}
curl -X POST 'https://api.rebbehub.org/v1/suggestions/1/approve' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/send-back' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/review-live' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"verdict":"approve"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/suggestions/1/withdraw' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_TOKEN });
const answer = await rh.withdrawSuggestion({
  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.rebbehub.org/v1/suggestions/1/revert' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_TOKEN });
const answer = await rh.revertSuggestion({
  id: 1,
  body: {}
});
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, or a page's first words, 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"
      ]
    },
    "version": {
      "type": "string"
    },
    "segment": {
      "type": "string"
    },
    "text": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": true
      },
      "description": "Runs: { text, marks?, href? }, { note }, { marker }, { br: true }"
    },
    "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.rebbehub.org/v1/suggestions/words' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"entityId":"rh-7k2m9q4d","change":"edit"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_TOKEN });
const answer = await rh.suggestWords({
  body: {
    entityId: "rh-7k2m9q4d",
    change: "edit"
  }
});
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.rebbehub.org/v1/suggestions/contents-map' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"publication":"rh-7k2m9q4d","pages":{"from":1,"to":1}}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/comments/1/resolve' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/tree'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/organize/preview' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"operations":[{"op":null}]}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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. 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.rebbehub.org/v1/organize' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"operations":[{"op":null}]}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/entities/rh-7k2m9q4d/talk'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/entities/rh-7k2m9q4d/talk' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/comments/1/hide' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/comments/1' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/reports' \
  -H 'Content-Type: application/json' \
  -d '{"reason":"wrong-fact"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/reports' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/reports/1/close' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"outcome":"resolved"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/takedowns' \
  -H 'Content-Type: application/json' \
  -d '{"target":"<target>","name":"<name>","email":"<email>","relation":"rights-holder","statement":"<statement>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/teshuros/rh-7k2m9q4d/family-request' \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/issues'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/issues' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Fix the date"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/issues/templates'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/issues/1'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/issues/1' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/issues/1/state' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"state":"open"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/issues/1/labels' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"labels":["<labels>"]}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/issues/1/assignees' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"assignees":["<assignees>"]}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/issues/1/visibility' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"private":true}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/issues/1/comments' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"<body>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/labels'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/labels' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"<name>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/people'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/people/<username>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/threads'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/threads/1'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/inbox' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/inbox/count' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/inbox/read' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/missing?kind=recordings'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/projects'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/projects' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"slug":"<slug>","name":"<name>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/projects/<slug>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/projects/<slug>/next' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/projects/<slug>/release' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"item":"<item>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/projects/<slug>/close' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/follows' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/follows' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"kind":"entity","id":"<id>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/places' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/places' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"kind":"read","key":"<key>","title":"Fix the date","href":"<href>","place":{}}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/places?kind=read&key=%3Ckey%3E' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/webhooks' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/webhooks' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"url":"<url>"}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.org/v1/webhooks/1' \
  -H "Authorization: Bearer $REBBEHUB_TOKEN"
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub({ token: process.env.REBBEHUB_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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.org/.well-known/oauth-protected-resource'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/.well-known/oauth-protected-resource/mcp'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/.well-known/oauth-authorization-server'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/oauth/register' \
  -H 'Content-Type: application/json' \
  -d '{"redirect_uris":["<redirect_uris>"]}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/mcp (the MCP server) or https://api.rebbehub.org (the whole API)

  • ui_localesstringquery

    en for the consent page in English

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

const rh = new RebbeHub();
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.rebbehub.org/oauth/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' --data-binary @file
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/oauth/revoke' \
  -H 'Content-Type: application/x-www-form-urlencoded' --data-binary @file
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.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.rebbehub.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.rebbehub.org/v1/mirrors'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/editions'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/editions/2026.40/manifest.json'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/v1/editions/<tag>/SHA256SUMS'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/dumps/<tag>/<name>'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
const answer = await rh.getDump({
  tag: "<tag>",
  name: "<name>"
});
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.rebbehub.org/manifests/iiif/rh-7k2m9q4d'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/oai?verb=Identify'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/oai' \
  -H 'Content-Type: application/x-www-form-urlencoded' --data-binary @file
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/llms.txt'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
const answer = await rh.llmsTxt();
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.rebbehub.org/mcp' \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.org/mcp'
Try it

Not offered: there are no sessions to end#

DELETEDELETE /mcp

No account neededmcpEnd

curl
curl -X DELETE 'https://api.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.org/v1/auth/email/unsubscribe' \
  -H 'Content-Type: application/json' \
  -d '{}'
import { RebbeHub } from '@rebbehub/client';

const rh = new RebbeHub();
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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.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.rebbehub.org/v1/admin/files/<sha256>/takedown' \
  -H 'Content-Type: application/json' \
  -d '{}'