Skip to content

Created/edited by GitHub Copilot; pending human review.

Corrections to Sefaria's API description ​

The toolkit generates the client from Sefaria's published API description, an OpenAPI file. Where that file doesn't match what Sefaria's server code accepts or returns, the toolkit corrects it first. This page lists each correction and the endpoints it affects. It also lists the source checks that must pass before the correction runs, and the changes it makes.

Which release this describes ​

This page documents the code on the main branch. The source stamp is not an npm release or a development snapshot. This copy was built from commit 6fde603.

Install an exact npm version or use a version-pinned npm CDN module. The npm alpha tag moves between reviewed prereleases. It is not a main-build snapshot. Older pinned releases keep their own behavior and can lack APIs added since. Install and status lists package commands and jsDelivr/UNPKG files.

The pinned source ​

The corrections apply to docs/openAPI.json in Sefaria/Sefaria-Project at commit 898feda78d1bd6b24f66305081a54c8cf36406be. The downloaded file must have the SHA-256 digest 3a6057ad40ca8e7874d6be97ed2491926818e3a6939c61cca67c9878da9aa4ab.

Each correction has source checks. The checks inspect the parts of Sefaria's file that the correction uses. They require each part to be absent or unchanged since the correction was written. The checks don't prove that the correction is still needed. If a check fails, client generation stops.

There are 12 corrections, with 83 changes in total. They affect 19 of the client's 60 endpoints.

Corrections by endpoint ​

Each endpoint shows its client function. It then lists the corrections that change the endpoint or a schema it uses.

GET /api/async/{task_id} ​

Client function: misc.getAsyncTaskStatus

GET /api/calendars/topics/parasha ​

Client function: calendars.getCalendarParashaTopic

POST /api/find-refs ​

Client function: misc.postFindRefs

GET /api/index/{title} ​

Client function: index.getIndexByTitle

Client function: related.getLinks

GET /api/manuscripts/{tref} ​

Client function: text.getManuscripts

GET /api/ref/{tref} ​

Client function: ref.getRef

Client function: related.getRelated

GET /api/shape/{title} ​

Client function: index.getShape

GET /api/sheets/all-sheets/{limiter}/{offset} ​

Client function: sheets.getAllSheets

GET /api/sheets/ref/{ref} ​

Client function: sheets.getSheetsByRef

GET /api/sheets/tag-list/user/{user_id} ​

Client function: sheets.getUserSheetTags

GET /api/sheets/user/{user_id} ​

Client function: sheets.getUserSheets

GET /api/sheets/user/{user_id}/{sort_by}/{limiter}/{offset} ​

Client function: sheets.getUserSheetsPaginated

GET /api/texts/random ​

Client function: text.getTextsRandom

GET /api/texts/versions/{tref} ​

Client function: text.getTextVersions

GET /api/texts/{tref} ​

Client function: text.getV1Texts

GET /api/v2/index/{title} ​

Client function: index.getIndexV2

GET /api/v3/texts/{tref} ​

Client function: text.getV3Texts

Corrections ​

Shared version metadata ​

Correction ID: shared-version-metadata

The pinned description defines version metadata twice, in VersionJSON and versionData. The correction points both at one shared CoreVersionMetadata schema. The v3 text schemas extend that schema with extra fields and requirements.

Endpoints: GET /api/texts/random, GET /api/texts/versions/{tref}, GET /api/texts/{tref}, GET /api/v3/texts/{tref}.

Evidence: Sefaria source.

Source checks:

  • $.components.schemas.CoreVersionMetadata is absent.
  • $.components.schemas.versionData is unchanged (SHA-256 starting 30674c1ce884).
ChangeActionTargetDescription
shared-version-metadata-seedUpdate$.components.schemas—
shared-version-metadata-copyCopy from $.components.schemas.VersionJSON$.components.schemas.CoreVersionMetadata—
version-json-properties-removeRemove$.components.schemas.VersionJSON.properties—
version-json-type-removeRemove$.components.schemas.VersionJSON.type—
version-json-baseUpdate$.components.schemas.VersionJSON—
version-data-properties-removeRemove$.components.schemas.versionData.properties—
version-data-type-removeRemove$.components.schemas.versionData.type—
version-data-baseUpdate$.components.schemas.versionData—
Values this correction sets

shared-version-metadata-seed:

json
{
  "CoreVersionMetadata": {}
}

version-json-base:

json
{
  "allOf": [
    {
      "$ref": "#/components/schemas/CoreVersionMetadata"
    }
  ]
}

version-data-base:

json
{
  "allOf": [
    {
      "$ref": "#/components/schemas/CoreVersionMetadata"
    }
  ]
}

Shared sheet topic shape ​

Correction ID: shared-sheet-topic

The pinned description defines sheet topics and user sheet tags as separate schemas, SheetTopicJSON and UserSheetTagJSON. The correction points both at one shared CoreSheetTopic schema. User sheet tags also keep an optional integer count.

Endpoints: GET /api/related/{tref}, GET /api/sheets/ref/{ref}, GET /api/sheets/tag-list/user/{user_id}, GET /api/sheets/user/{user_id}, GET /api/sheets/user/{user_id}/{sort_by}/{limiter}/{offset}.

Evidence: Sefaria source.

Source checks:

  • $.components.schemas.CoreSheetTopic is absent.
  • $.components.schemas.SheetTopicJSON is unchanged (SHA-256 starting 5db2a7972cc0).
  • $.components.schemas.UserSheetTagJSON is unchanged (SHA-256 starting c57345df7247).
ChangeActionTargetDescription
shared-sheet-topic-seedUpdate$.components.schemas—
shared-sheet-topic-copyCopy from $.components.schemas.SheetTopicJSON$.components.schemas.CoreSheetTopic—
sheet-topic-properties-removeRemove$.components.schemas.SheetTopicJSON.properties—
sheet-topic-type-removeRemove$.components.schemas.SheetTopicJSON.type—
sheet-topic-baseUpdate$.components.schemas.SheetTopicJSON—
user-sheet-tag-properties-removeRemove$.components.schemas.UserSheetTagJSON.properties—
user-sheet-tag-type-removeRemove$.components.schemas.UserSheetTagJSON.type—
user-sheet-tag-baseUpdate$.components.schemas.UserSheetTagJSON—
Values this correction sets

shared-sheet-topic-seed:

json
{
  "CoreSheetTopic": {}
}

sheet-topic-base:

json
{
  "allOf": [
    {
      "$ref": "#/components/schemas/CoreSheetTopic"
    }
  ]
}

user-sheet-tag-base:

json
{
  "allOf": [
    {
      "$ref": "#/components/schemas/CoreSheetTopic"
    },
    {
      "type": "object",
      "properties": {
        "count": {
          "type": "integer"
        }
      }
    }
  ]
}

Sheet summary fields ​

Correction ID: sheet-summary-contract

The pinned description already gave the sheet id a string type and via a nullable string. It also gave the display options and date-time formats. The correction changes id to an integer or a string. It changes via to a nullable integer and revises the option value types. It also allows an empty array for options. It removes the date-time formats from created and published.

Endpoints: GET /api/related/{tref}, GET /api/sheets/all-sheets/{limiter}/{offset}, GET /api/sheets/ref/{ref}, GET /api/sheets/user/{user_id}, GET /api/sheets/user/{user_id}/{sort_by}/{limiter}/{offset}.

Evidence: Sefaria source.

Source checks:

  • $.components.schemas.SheetsJSON.properties.id is unchanged (SHA-256 starting b531327ce6cd).
  • $.components.schemas.SheetsJSON.properties.via is unchanged (SHA-256 starting 1e9bcf42f672).
  • $.components.schemas.SheetsJSON.properties.options is unchanged (SHA-256 starting 31b71a178e1e).
  • $.components.schemas.AllSheetsJSON.properties.sheets.items.properties.created is unchanged (SHA-256 starting d39ee056c680).
  • $.components.schemas.AllSheetsJSON.properties.sheets.items.properties.published is unchanged (SHA-256 starting 5d0406f84838).
ChangeActionTargetDescription
sheet-summary-id-type-removeRemove$.components.schemas.SheetsJSON.properties.id.type—
sheet-summary-idUpdate$.components.schemas.SheetsJSON.properties.id—
sheet-summary-viaUpdate$.components.schemas.SheetsJSON.properties.via—
sheet-summary-options-type-removeRemove$.components.schemas.SheetsJSON.properties.options.type—
sheet-summary-options-properties-removeRemove$.components.schemas.SheetsJSON.properties.options.properties—
sheet-summary-options-example-removeRemove$.components.schemas.SheetsJSON.properties.options.example—
sheet-summary-optionsUpdate$.components.schemas.SheetsJSON.properties.options—
all-sheets-created-format-removeRemove$.components.schemas.AllSheetsJSON.properties.sheets.items.properties.created.format—
all-sheets-published-format-removeRemove$.components.schemas.AllSheetsJSON.properties.sheets.items.properties.published.format—
Values this correction sets

sheet-summary-id:

json
{
  "oneOf": [
    {
      "type": "integer"
    },
    {
      "type": "string"
    }
  ]
}

sheet-summary-via:

json
{
  "type": "integer"
}

sheet-summary-options:

json
{
  "type": "object",
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "numbered": {
          "oneOf": [
            {
              "type": "boolean"
            },
            {
              "type": "integer"
            }
          ],
          "description": "Should the sources be automatically numbered in the Sefaria editor view"
        },
        "boxed": {
          "description": "Should the sources be boxed on the page in the Sefaria editor view",
          "oneOf": [
            {
              "type": "boolean"
            },
            {
              "type": "number"
            }
          ]
        },
        "assignable": {
          "description": "Is this source sheet an assignment for students in the Sefaria editor view",
          "oneOf": [
            {
              "type": "boolean"
            },
            {
              "type": "number"
            }
          ]
        },
        "bsd": {
          "description": "Should the source sheet include בס\"ד at the top of the page in the Sefaria editor view",
          "oneOf": [
            {
              "type": "boolean"
            },
            {
              "type": "number"
            }
          ]
        },
        "language": {
          "description": "Default display language of the source sheet in the Sefaria editor view",
          "enum": ["bilingual", "hebrew", "english"],
          "type": "string"
        },
        "layout": {
          "description": "Default display layout of the source sheet in the Sefaria editor view",
          "type": "string"
        },
        "langLayout": {
          "description": "Default display side of the language in a bilingual side-by-side view in the Sefaria editor view",
          "type": "string"
        },
        "divineNames": {
          "description": "Should divine names be replaced, and if so in what form?",
          "type": "string"
        },
        "highlightMode": {
          "oneOf": [
            {
              "type": "boolean"
            },
            {
              "type": "integer"
            }
          ]
        },
        "collaboration": {
          "type": "string"
        }
      }
    },
    {
      "type": "array",
      "maxItems": 0,
      "description": "Legacy sheets encode an empty options object as an empty array."
    }
  ]
}

Manuscripts response media type ​

Correction ID: manuscripts-content-type

For GET /api/manuscripts/{tref}, the published description files the 200 response under a media-type key named Manuscript JSON. The correction moves that schema under application/json. It treats that as the type the route serves.

Endpoints: GET /api/manuscripts/{tref}.

Evidence: Sefaria source.

Source checks:

  • $.paths['/api/manuscripts/{tref}'].get.responses['200'].content['Manuscript JSON'] is unchanged (SHA-256 starting 434d5e06ff93).
  • $.paths['/api/manuscripts/{tref}'].get.responses['200'].content['application/json'] is absent.
ChangeActionTargetDescription
manuscripts-content-seedUpdate$.paths['/api/manuscripts/{tref}'].get.responses['200'].content—
manuscripts-content-copyCopy from $.paths['/api/manuscripts/{tref}'].get.responses['200'].content['Manuscript JSON']$.paths['/api/manuscripts/{tref}'].get.responses['200'].content['application/json']—
manuscripts-content-removeRemove$.paths['/api/manuscripts/{tref}'].get.responses['200'].content['Manuscript JSON']—
Values this correction sets

manuscripts-content-seed:

json
{
  "application/json": {}
}

Text versions endpoint ​

Correction ID: versions-contract

The published description names the path /api/texts/versions/{index}. Source review shows the pinned route and handler take a reference. The correction renames the path to GET /api/texts/versions/{tref}. The 200 response is a version list or a JSON error. Stored versions can have a null versionSource or status.

Endpoints: GET /api/texts/random, GET /api/texts/versions/{tref}, GET /api/texts/{tref}, GET /api/v3/texts/{tref}.

Evidence: Sefaria source.

Source checks:

  • $.paths['/api/texts/versions/{index}'] is unchanged (SHA-256 starting 7d3a1ad0fbf2).
  • $.paths['/api/texts/versions/{tref}'] is absent.
  • $.paths['/api/texts/versions/{index}'].parameters[0].name equals "index".
  • $.paths['/api/texts/versions/{index}'].parameters[0] is unchanged (SHA-256 starting 1e3ec10dc573).
  • $.paths['/api/texts/versions/{index}'].get.responses['200'].content['VersionJSON'] is unchanged (SHA-256 starting faed8c019245).
  • $.paths['/api/texts/versions/{index}'].get.responses['200'].content['application/json'] is absent.
  • $.components.schemas.VersionJSON.properties.versionSource.type equals "string".
  • $.components.schemas.VersionJSON.properties.versionSource is unchanged (SHA-256 starting 60ad2aadf746).
  • $.components.schemas.VersionJSON.properties.versionSource.nullable is absent.
  • $.components.schemas.VersionJSON.properties.status.type equals "string".
  • $.components.schemas.VersionJSON.properties.status is unchanged (SHA-256 starting 56639d0f6f82).
  • $.components.schemas.VersionJSON.properties.status.nullable is absent.
ChangeActionTargetDescription
versions-path-seedUpdate$.pathsCreate the corrected tref path before copying the upstream operation.
versions-path-copyCopy from $.paths['/api/texts/versions/{index}']$.paths['/api/texts/versions/{tref}']Copy the complete versions operation to the corrected tref path.
versions-path-removeRemove$.paths['/api/texts/versions/{index}']Remove the incorrectly named index path.
versions-parameterUpdate$.paths['/api/texts/versions/{tref}'].parameters[0]Match the path parameter to the route and handler.
versions-content-seedUpdate$.paths['/api/texts/versions/{tref}'].get.responses['200'].contentCreate the JSON media-type key before copying its schema.
versions-content-copyCopy from $.paths['/api/texts/versions/{tref}'].get.responses['200'].content['VersionJSON']$.paths['/api/texts/versions/{tref}'].get.responses['200'].content['application/json']Copy the version-list schema under the correct JSON media type.
versions-response-schema-removeRemove$.paths['/api/texts/versions/{tref}'].get.responses['200'].content['application/json'].schemaRemove the array-only schema before adding the source error branch.
versions-response-schemaUpdate$.paths['/api/texts/versions/{tref}'].get.responses['200'].content['application/json']Model successful version metadata arrays and HTTP 200 JSON errors.
versions-content-removeRemove$.paths['/api/texts/versions/{tref}'].get.responses['200'].content['VersionJSON']Remove the schema name that was incorrectly used as a media type.
versions-version-source-nullableUpdate$.components.schemas.VersionJSON.properties.versionSourcePermit stored version metadata whose required source value is null.
versions-status-nullableUpdate$.components.schemas.VersionJSON.properties.statusPermit stored version metadata whose optional status value is null.
Values this correction sets

versions-path-seed:

json
{
  "/api/texts/versions/{tref}": {}
}

versions-parameter:

json
{
  "name": "tref",
  "description": "A valid Sefaria reference."
}

versions-content-seed:

json
{
  "application/json": {}
}

versions-response-schema:

json
{
  "schema": {
    "oneOf": [
      {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/VersionJSON"
        }
      },
      {
        "$ref": "#/components/schemas/CoreErrorResponse"
      }
    ]
  }
}

versions-version-source-nullable:

json
{
  "nullable": true
}

versions-status-nullable:

json
{
  "nullable": true
}

Text (v3) response ​

Correction ID: v3-text-contract

The published description for GET /api/v3/texts/{tref} already had a warnings array with unconstrained items. The correction adds a repeatable version selector and nested nullable text values. It also types and constrains warnings. It documents two error responses with the Core JSON error schema:

  • 400: an invalid return format or a text adapter failure.
  • 404: an invalid, empty, or unavailable reference.

Endpoints: GET /api/calendars/topics/parasha, GET /api/links/{tref}, GET /api/ref/{tref}, GET /api/shape/{title}, GET /api/texts/versions/{tref}, GET /api/v2/index/{title}, GET /api/v3/texts/{tref}.

Evidence: Sefaria source.

Source checks:

  • $.components.schemas.CoreErrorResponse is absent.
  • $.components.schemas.CoreStringArrayOrNull is absent.
  • $.components.schemas.CoreV3TextValue is absent.
  • $.components.schemas.CoreV3WarningDetail is absent.
  • $.components.schemas.CoreV3Warning is absent.
  • $.components.schemas.CoreV3AvailableVersion is absent.
  • $.components.schemas.CoreV3VersionMetadata is absent.
  • $.components.schemas.CoreV3Version is absent.
  • $.components.schemas.CoreV3TextsResponse is absent.
  • $.paths['/api/v3/texts/{tref}'].parameters[0].name equals "version".
  • $.paths['/api/v3/texts/{tref}'].parameters[0] is unchanged (SHA-256 starting b3ba871f7846).
  • $.paths['/api/v3/texts/{tref}'].parameters[0].schema equals {"type":"string"}.
  • $.paths['/api/v3/texts/{tref}'].get.responses['200'].content['application/json'].schema['$ref'] equals "#/components/schemas/v3TextsJson".
  • $.paths['/api/v3/texts/{tref}'].get.responses['400'] is absent.
  • $.paths['/api/v3/texts/{tref}'].get.responses['404'] is absent.
ChangeActionTargetDescription
v3-version-parameterUpdate$.paths['/api/v3/texts/{tref}'].parameters[0]Model the repeatable version selector read through request.GET.getlist.
v3-schemasUpdate$.components.schemasAdd the source-backed v3 response, warning, error, and recursive value schemas.
v3-responsesUpdate$.paths['/api/v3/texts/{tref}'].get.responsesCorrect the success schema and document the handler's JSON error statuses.
Values this correction sets

v3-version-parameter:

json
{
  "schema": {
    "type": "array",
    "items": {
      "type": "string"
    }
  },
  "style": "form",
  "explode": true
}

v3-schemas:

json
{
  "CoreErrorResponse": {
    "type": "object",
    "required": ["error"],
    "properties": {
      "error": {
        "type": "string"
      }
    }
  },
  "CoreStringArrayOrNull": {
    "description": "A string, null, or recursively nested list of the same values.",
    "oneOf": [
      {
        "type": "string"
      },
      {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreStringArrayOrNull"
        }
      },
      {
        "type": "string",
        "nullable": true,
        "enum": [null]
      }
    ]
  },
  "CoreV3TextValue": {
    "description": "A nullable text segment or recursively nested text segments.",
    "oneOf": [
      {
        "type": "string"
      },
      {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreV3TextValue"
        }
      },
      {
        "type": "string",
        "nullable": true,
        "enum": [null]
      }
    ]
  },
  "CoreV3WarningDetail": {
    "type": "object",
    "required": ["warning_code", "message"],
    "properties": {
      "warning_code": {
        "type": "integer"
      },
      "message": {
        "type": "string"
      }
    }
  },
  "CoreV3Warning": {
    "type": "object",
    "minProperties": 1,
    "additionalProperties": {
      "$ref": "#/components/schemas/CoreV3WarningDetail"
    }
  },
  "CoreV3VersionMetadata": {
    "allOf": [
      {
        "$ref": "#/components/schemas/VersionJSON"
      },
      {
        "type": "object",
        "required": [
          "versionTitle",
          "versionSource",
          "language",
          "actualLanguage",
          "languageFamilyName",
          "isSource",
          "isPrimary",
          "direction"
        ],
        "properties": {
          "versionTitle": {
            "type": "string"
          },
          "versionSource": {
            "type": "string",
            "nullable": true
          },
          "language": {
            "$ref": "#/components/schemas/LanguageCode"
          },
          "actualLanguage": {
            "type": "string"
          },
          "languageFamilyName": {
            "type": "string"
          },
          "isSource": {
            "type": "boolean"
          },
          "isPrimary": {
            "type": "boolean"
          },
          "direction": {
            "type": "string",
            "enum": ["ltr", "rtl"]
          },
          "formatAsPoetry": {
            "oneOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ]
          },
          "hasManuallyWrappedRefs": {
            "oneOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ]
          }
        }
      }
    ]
  },
  "CoreV3AvailableVersion": {
    "allOf": [
      {
        "$ref": "#/components/schemas/CoreV3VersionMetadata"
      },
      {
        "type": "object",
        "required": ["title"],
        "properties": {
          "title": {
            "type": "string"
          }
        }
      }
    ]
  },
  "CoreV3Version": {
    "allOf": [
      {
        "$ref": "#/components/schemas/CoreV3VersionMetadata"
      },
      {
        "type": "object",
        "required": ["text"],
        "properties": {
          "text": {
            "$ref": "#/components/schemas/CoreV3TextValue"
          },
          "firstSectionRef": {
            "type": "string"
          },
          "sources": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          }
        }
      }
    ]
  },
  "CoreV3TextsResponse": {
    "type": "object",
    "required": [
      "versions",
      "available_versions",
      "ref",
      "heRef",
      "sections",
      "toSections",
      "sectionRef",
      "heSectionRef",
      "firstAvailableSectionRef",
      "isSpanning",
      "next",
      "prev",
      "title",
      "book",
      "heTitle",
      "primary_category",
      "type",
      "indexTitle",
      "categories",
      "heIndexTitle",
      "isComplex",
      "isDependant",
      "order",
      "collectiveTitle",
      "heCollectiveTitle",
      "alts",
      "textDepth",
      "sectionNames",
      "addressTypes",
      "titleVariants",
      "heTitleVariants",
      "warnings"
    ],
    "properties": {
      "versions": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreV3Version"
        }
      },
      "available_versions": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreV3AvailableVersion"
        }
      },
      "ref": {
        "$ref": "#/components/schemas/ref"
      },
      "heRef": {
        "type": "string"
      },
      "sections": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "toSections": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "sectionRef": {
        "$ref": "#/components/schemas/ref"
      },
      "heSectionRef": {
        "type": "string"
      },
      "firstAvailableSectionRef": {
        "type": "string"
      },
      "isSpanning": {
        "type": "boolean"
      },
      "spanningRefs": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/ref"
        }
      },
      "next": {
        "type": "string",
        "nullable": true
      },
      "prev": {
        "type": "string",
        "nullable": true
      },
      "title": {
        "type": "string"
      },
      "book": {
        "type": "string"
      },
      "heTitle": {
        "type": "string"
      },
      "primary_category": {
        "type": "string"
      },
      "type": {
        "type": "string"
      },
      "indexTitle": {
        "type": "string"
      },
      "categories": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "heIndexTitle": {
        "type": "string"
      },
      "isComplex": {
        "type": "boolean"
      },
      "isDependant": {
        "type": "boolean"
      },
      "order": {
        "oneOf": [
          {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          {
            "type": "string"
          }
        ]
      },
      "collectiveTitle": {
        "type": "string"
      },
      "heCollectiveTitle": {
        "type": "string"
      },
      "alts": {
        "type": "array"
      },
      "lengths": {
        "type": "array",
        "items": {
          "type": "integer"
        }
      },
      "length": {
        "type": "integer"
      },
      "textDepth": {
        "type": "integer",
        "nullable": true
      },
      "sectionNames": {
        "type": "array",
        "nullable": true,
        "items": {
          "type": "string"
        }
      },
      "addressTypes": {
        "type": "array",
        "nullable": true,
        "items": {
          "type": "string"
        }
      },
      "titleVariants": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "heTitleVariants": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "index_offsets_by_depth": {
        "type": "object"
      },
      "linker_output": {
        "type": "array",
        "items": {
          "type": "object"
        }
      },
      "warnings": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreV3Warning"
        }
      }
    }
  }
}

v3-responses:

json
{
  "200": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CoreV3TextsResponse"
        }
      }
    }
  },
  "400": {
    "description": "Invalid return format or text adapter failure.",
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CoreErrorResponse"
        }
      }
    }
  },
  "404": {
    "description": "Invalid, empty, or unavailable reference.",
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CoreErrorResponse"
        }
      }
    }
  }
}

Reference lookup response ​

Correction ID: ref-contract

The published description for GET /api/ref/{tref} does not fully cover the fields that depend on the node type. Its 404 has an incomplete inline error schema. The correction rewrites the description of those fields. It makes the 200 response a union of success and expected parse failure. It points the 404 at the Core JSON error schema.

Endpoints: GET /api/ref/{tref}.

Evidence: Sefaria source.

Source checks:

  • $.paths['/api/ref/{tref}'].get.description equals "Validates a text reference (`tref`) and returns structured metadata about it.\n\nThe response varies based on the `node_type` of the referenced text:\n\n- **JaggedArrayNode**: Standard text nodes (e.g. biblical chapters/verses, Talmud pages). Returns `depth`, `address_types`, `section_names`, and positional indexes/labels.\n- **SchemaNode**: Nodes with named children (e.g. a commentary with an introduction and main text). Returns `children` list.\n- **DictionaryEntryNode**: Individual dictionary entries. Returns `lexicon_name` and `headword`, plus the JaggedArrayNode fields.\n- **DictionaryNode**: Dictionary root nodes. Returns `lexicon_name`.\n- **SheetNode**: User-created source sheets. Returns `sheet_id`.\n\nIf the node has a default child (a child node that represents the primary content), the response includes a `default_child_node` object with the child's `node_type`, `node_index`, and optionally `depth`, `address_types` and `sectionNames` (for JaggedArrayNode children) or `lexicon_name` (for DictionaryNode parents).\n\nAll types include `navigation_refs` with `shortest_path_to_root` (array of ancestor refs from immediate parent to book level) and `first_available_section_ref`. Segment-level refs also get `prev_segment_ref`/`next_segment_ref`, and section-level refs get `prev_section_ref`/`next_section_ref`.".
  • $.components.schemas.CoreRefNavigation is absent.
  • $.components.schemas.CoreRefSuccess is absent.
  • $.components.schemas.CoreRefResponse is absent.
  • $.paths['/api/ref/{tref}'].get.responses['200'].content['application/json'].schema['$ref'] equals "#/components/schemas/RefJSON".
  • $.paths['/api/ref/{tref}'].get.responses['404'].content['application/json'].schema equals {"type":"object","properties":{"error":{"type":"string"}}}.
ChangeActionTargetDescription
ref-descriptionUpdate$.paths['/api/ref/{tref}'].get.descriptionCorrect the conditional navigation-field documentation.
ref-schemasUpdate$.components.schemasAdd the parse-failure and node-dependent reference response union.
ref-successUpdate$.paths['/api/ref/{tref}'].get.responses['200'].content['application/json'].schema['$ref']Use the success-or-expected-parse-failure union for HTTP 200.
ref-error-removeRemove$.paths['/api/ref/{tref}'].get.responses['404'].content['application/json'].schemaRemove the incomplete inline error schema.
ref-errorUpdate$.paths['/api/ref/{tref}'].get.responses['404'].content['application/json']Reference the required Core JSON error schema.
Values this correction sets

ref-description:

json
"Validates a text reference (`tref`) and returns structured metadata about it.\n\nThe response varies based on the `node_type` of the referenced text:\n\n- **JaggedArrayNode**: Standard text nodes (e.g. biblical chapters/verses, Talmud pages). Returns `depth`, `address_types`, `section_names`, and positional indexes/labels.\n- **SchemaNode**: Nodes with named children (e.g. a commentary with an introduction and main text). Returns `children` list.\n- **DictionaryEntryNode**: Individual dictionary entries. Returns `lexicon_name` and `headword`, plus the JaggedArrayNode fields.\n- **DictionaryNode**: Dictionary root nodes. Returns `lexicon_name`.\n- **SheetNode**: User-created source sheets. Returns `sheet_id`.\n\nIf the node has a default child (a child node that represents the primary content), the response includes a `default_child_node` object with the child's `node_type`, `node_index`, and optionally `depth`, `address_types` and `sectionNames` (for JaggedArrayNode children) or `lexicon_name` (for DictionaryNode parents).\n\nNavigation fields depend on node type and reference depth. `navigation_refs.shortest_path_to_root` is always present. Non-`SheetNode` responses also include `first_available_section_ref`. Segment-level refs include `prev_segment_ref` and `next_segment_ref`; section-level refs include `prev_section_ref` and `next_section_ref`. Refs with a node depth that are neither ranges nor segment-level include `first_subref` and `last_subref`. `SheetNode` responses omit `first_available_section_ref` and previous/next navigation, but can include `first_subref` and `last_subref`."

ref-schemas:

json
{
  "CoreRefNavigation": {
    "type": "object",
    "required": ["shortest_path_to_root"],
    "properties": {
      "shortest_path_to_root": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "first_available_section_ref": {
        "type": "string",
        "nullable": true
      },
      "prev_segment_ref": {
        "type": "string",
        "nullable": true
      },
      "next_segment_ref": {
        "type": "string",
        "nullable": true
      },
      "prev_section_ref": {
        "type": "string",
        "nullable": true
      },
      "next_section_ref": {
        "type": "string",
        "nullable": true
      },
      "first_subref": {
        "type": "string"
      },
      "last_subref": {
        "type": "string"
      }
    }
  },
  "CoreRefSuccess": {
    "type": "object",
    "required": [
      "is_ref",
      "normalized",
      "hebrew",
      "url_ref",
      "index_title",
      "node_type",
      "navigation_refs"
    ],
    "properties": {
      "is_ref": {
        "type": "boolean",
        "enum": [true]
      },
      "normalized": {
        "type": "string"
      },
      "hebrew": {
        "type": "string"
      },
      "url_ref": {
        "type": "string"
      },
      "index_title": {
        "type": "string"
      },
      "node_type": {
        "type": "string"
      },
      "navigation_refs": {
        "$ref": "#/components/schemas/CoreRefNavigation"
      },
      "depth": {
        "type": "integer"
      },
      "address_types": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "section_names": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "start_indexes": {
        "type": "array",
        "items": {
          "type": "integer"
        }
      },
      "start_labels": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "end_indexes": {
        "type": "array",
        "items": {
          "type": "integer"
        }
      },
      "end_labels": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "children": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "lexicon_name": {
        "type": "string"
      },
      "headword": {
        "type": "string"
      },
      "sheet_id": {
        "type": "integer"
      },
      "default_child_node": {
        "type": "object",
        "required": ["node_type", "node_index"],
        "properties": {
          "node_type": {
            "type": "string"
          },
          "node_index": {
            "type": "integer"
          },
          "depth": {
            "type": "integer"
          },
          "address_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sectionNames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "lexicon_name": {
            "type": "string"
          }
        }
      }
    }
  },
  "CoreRefResponse": {
    "oneOf": [
      {
        "type": "object",
        "required": ["is_ref"],
        "properties": {
          "is_ref": {
            "type": "boolean",
            "enum": [false]
          }
        },
        "additionalProperties": false
      },
      {
        "$ref": "#/components/schemas/CoreRefSuccess"
      }
    ]
  }
}

ref-success:

json
"#/components/schemas/CoreRefResponse"

ref-error:

json
{
  "schema": {
    "$ref": "#/components/schemas/CoreErrorResponse"
  }
}

Calendar parasha response ​

Correction ID: calendar-parasha-error-contract

The published description for GET /api/calendars/topics/parasha models every HTTP 200 response as successful calendar data. The correction requires the ref field on successful responses and makes the 200 response a union of successful calendar data and the Core JSON error schema.

Endpoints: GET /api/calendars/topics/parasha.

Evidence: Sefaria source.

Source checks:

  • $.components.schemas.CalendarParashaTopicJSON.required is absent.
  • $.components.schemas.CoreCalendarParashaTopicResponse is absent.
  • $.paths['/api/calendars/topics/parasha'].get.responses['200'].content['application/json'].schema['$ref'] equals "#/components/schemas/CalendarParashaTopicJSON".
ChangeActionTargetDescription
calendar-parasha-success-refUpdate$.components.schemas.CalendarParashaTopicJSONRequire the ref always provided by the successful calendar response builder.
calendar-parasha-response-schemaUpdate$.components.schemasDistinguish successful calendar data from HTTP 200 JSON errors.
calendar-parasha-response-refUpdate$.paths['/api/calendars/topics/parasha'].get.responses['200'].content['application/json'].schema['$ref']Use the calendar success-or-error response schema.
Values this correction sets

calendar-parasha-success-ref:

json
{
  "required": ["ref"]
}

calendar-parasha-response-schema:

json
{
  "CoreCalendarParashaTopicResponse": {
    "oneOf": [
      {
        "$ref": "#/components/schemas/CalendarParashaTopicJSON"
      },
      {
        "$ref": "#/components/schemas/CoreErrorResponse"
      }
    ]
  }
}

calendar-parasha-response-ref:

json
"#/components/schemas/CoreCalendarParashaTopicResponse"

Index response ​

Correction ID: index-contract

The published description for GET /api/v2/index/{title} doesn't list the conditional query parameters, such as content_counts. The correction adds those parameters and the firstSectionRef and relatedTopics properties. It models the HTTP 200 response as a union of success and error.

Endpoints: GET /api/index/{title}, GET /api/v2/index/{title}.

Evidence: Sefaria source.

Source checks:

  • $.paths['/api/v2/index/{title}'].get.parameters is unchanged (SHA-256 starting 25c871bb3cf9).
  • $.components.schemas.CoreIndexResponse is absent.
  • $.components.schemas.IndexJSON is unchanged (SHA-256 starting 5e033d42164a).
  • $.paths['/api/v2/index/{title}'].get.responses['200'].content['application/json'].schema['$ref'] equals "#/components/schemas/IndexJSON".
ChangeActionTargetDescription
index-queryUpdate$.paths['/api/v2/index/{title}'].get.parametersAdd the source-backed conditional response query parameters.
index-base-schemaUpdate$.components.schemas.IndexJSONRequire the source-owned success fields and add conditional query fields.
index-schemaUpdate$.components.schemasAdd the HTTP 200 success-or-error response union.
index-responseUpdate$.paths['/api/v2/index/{title}'].get.responses['200'].content['application/json'].schema['$ref']Use the query-aware index response schema.
Values this correction sets

index-query:

json
[
  {
    "name": "with_content_counts",
    "description": "Annotate schema leaves with content_counts and add firstSectionRef.",
    "schema": {
      "type": "string",
      "enum": ["0", "1"],
      "default": "0"
    },
    "in": "query"
  },
  {
    "name": "with_related_topics",
    "description": "Add relatedTopics for the requested index.",
    "schema": {
      "type": "string",
      "enum": ["0", "1"],
      "default": "0"
    },
    "in": "query"
  }
]

index-base-schema:

json
{
  "required": ["title", "categories", "schema"],
  "properties": {
    "firstSectionRef": {
      "type": "string"
    },
    "relatedTopics": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  }
}

index-schema:

json
{
  "CoreIndexResponse": {
    "oneOf": [
      {
        "$ref": "#/components/schemas/IndexJSON"
      },
      {
        "$ref": "#/components/schemas/CoreErrorResponse"
      }
    ]
  }
}

index-response:

json
"#/components/schemas/CoreIndexResponse"

Shape endpoint ​

Correction ID: shape-contract

For GET /api/shape/{title}, the published description gives a single-object schema with mixed property casing. It documents depth without deprecating it. Source review shows the handler does not use depth, so the correction removes it. The dependent-texts flag becomes the string values "0" and "1". The response becomes a list-based union with an error variant. The examples become arrays.

Endpoints: GET /api/shape/{title}.

Evidence: Sefaria source.

Source checks:

  • $.components.schemas.CoreShapeMetadata is absent.
  • $.components.schemas.CoreShapeChapter is absent.
  • $.components.schemas.CoreShapeLeafRecord is absent.
  • $.components.schemas.CoreShapeCollapsedRecord is absent.
  • $.components.schemas.CoreShapeRecord is absent.
  • $.components.schemas.CoreShapeResponse is absent.
  • $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].schema['$ref'] equals "#/components/schemas/ShapeJSON".
  • $.paths['/api/shape/{title}'].parameters[1] is unchanged (SHA-256 starting f209270e5490).
  • $.paths['/api/shape/{title}'].parameters[2] is unchanged (SHA-256 starting ec346ea97c63).
  • $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples is unchanged (SHA-256 starting 5f15e9aad060).
  • $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text'].value is unchanged (SHA-256 starting 77d1a5ac670e).
  • $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text'].value is unchanged (SHA-256 starting 98e56c88b6fb).
  • $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text']['x-sefaria-original-value'] is absent.
  • $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text']['x-sefaria-original-value'] is absent.
ChangeActionTargetDescription
shape-dependents-parameterUpdate$.paths['/api/shape/{title}'].parameters[2]Match the integer flag consumed by bool(int(...)).
shape-depth-removeRemove$.paths['/api/shape/{title}'].parameters[1]Remove the deprecated depth parameter because the handler does not use it.
shape-schemasUpdate$.components.schemasAdd the lower-case list, recursive chapter, and HTTP 200 error variants.
shape-responseUpdate$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].schema['$ref']Replace the upper-case single-object schema with the source response union.
shape-simple-example-temp-seedUpdate$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text']Create a temporary copy target for the original simple-text example.
shape-simple-example-temp-copyCopy from $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text'].value$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text']['x-sefaria-original-value']Preserve the original simple-text example while changing its root type.
shape-simple-example-value-removeRemove$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text'].valueRemove the bare simple-text object.
shape-simple-example-array-seedUpdate$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text']Create the corrected simple-text array root.
shape-simple-example-array-copyCopy from $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text']['x-sefaria-original-value']$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text'].valueAppend the preserved simple-text object to the corrected array.
shape-simple-example-temp-removeRemove$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Simple Text']['x-sefaria-original-value']Remove the temporary simple-text overlay value.
shape-complex-example-temp-seedUpdate$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text']Create a temporary copy target for the original complex-text example.
shape-complex-example-temp-copyCopy from $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text'].value$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text']['x-sefaria-original-value']Preserve the original complex-text example while changing its root type.
shape-complex-example-value-removeRemove$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text'].valueRemove the bare complex-text object.
shape-complex-example-array-seedUpdate$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text']Create the corrected complex-text array root.
shape-complex-example-array-copyCopy from $.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text']['x-sefaria-original-value']$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text'].valueAppend the preserved complex-text object to the corrected array.
shape-complex-example-temp-removeRemove$.paths['/api/shape/{title}'].get.responses['200'].content['application/json'].examples['Complex Text']['x-sefaria-original-value']Remove the temporary complex-text overlay value.
Values this correction sets

shape-dependents-parameter:

json
{
  "description": "Include dependent texts when set to 1.",
  "schema": {
    "type": "string",
    "enum": ["0", "1"]
  }
}

shape-schemas:

json
{
  "CoreShapeMetadata": {
    "type": "object",
    "required": ["section", "length", "book", "heBook"],
    "properties": {
      "section": {
        "type": "string"
      },
      "length": {
        "type": "integer"
      },
      "book": {
        "type": "string"
      },
      "heBook": {
        "type": "string"
      }
    }
  },
  "CoreShapeChapter": {
    "description": "A segment count, nested shape list, or collapsed complex-text leaf record.",
    "oneOf": [
      {
        "type": "integer"
      },
      {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreShapeChapter"
        }
      },
      {
        "$ref": "#/components/schemas/CoreShapeLeafRecord"
      }
    ]
  },
  "CoreShapeLeafRecord": {
    "allOf": [
      {
        "$ref": "#/components/schemas/CoreShapeMetadata"
      },
      {
        "type": "object",
        "required": ["heTitle", "title", "chapters"],
        "properties": {
          "heTitle": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "chapters": {
            "$ref": "#/components/schemas/CoreShapeChapter"
          },
          "isComplex": {
            "type": "boolean"
          }
        }
      }
    ]
  },
  "CoreShapeCollapsedRecord": {
    "allOf": [
      {
        "$ref": "#/components/schemas/CoreShapeMetadata"
      },
      {
        "type": "object",
        "required": ["isComplex", "chapters"],
        "properties": {
          "isComplex": {
            "type": "boolean",
            "enum": [true]
          },
          "chapters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CoreShapeLeafRecord"
            }
          }
        }
      }
    ]
  },
  "CoreShapeRecord": {
    "oneOf": [
      {
        "$ref": "#/components/schemas/CoreShapeLeafRecord"
      },
      {
        "$ref": "#/components/schemas/CoreShapeCollapsedRecord"
      }
    ]
  },
  "CoreShapeResponse": {
    "oneOf": [
      {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreShapeRecord"
        }
      },
      {
        "$ref": "#/components/schemas/CoreErrorResponse"
      }
    ]
  }
}

shape-response:

json
"#/components/schemas/CoreShapeResponse"

shape-simple-example-temp-seed:

json
{
  "x-sefaria-original-value": {}
}

shape-simple-example-array-seed:

json
{
  "value": []
}

shape-complex-example-temp-seed:

json
{
  "x-sefaria-original-value": {}
}

shape-complex-example-array-seed:

json
{
  "value": []
}

Correction ID: links-contract

The published description for GET /api/links/{tref} omits fields from the array items in the 200 response. It also omits the repeatable category filter. The correction adds link and sheet-link schemas and allows repeated category filters. It also documents an HTTP 400 error for whole-book references that request text.

Endpoints: GET /api/links/{tref}.

Evidence: Sefaria source.

Source checks:

  • $.components.schemas.CoreBilingualText is absent.
  • $.components.schemas.CoreLinkDisplayMetadata is absent.
  • $.components.schemas.CoreLinkVersion is absent.
  • $.components.schemas.CoreLinkObject is absent.
  • $.components.schemas.CoreSheetLinkObject is absent.
  • $.components.schemas.CoreLinkResponse is absent.
  • $.components.schemas.CoreLinksErrorResponse is absent.
  • $.paths['/api/links/{tref}'].get.parameters[2] is unchanged (SHA-256 starting 202a934c4f87).
  • $.paths['/api/links/{tref}'].get.responses['200'].content['application/json'].schema is unchanged (SHA-256 starting cf4a94c306c4).
  • $.paths['/api/links/{tref}'].get.responses['400'] is absent.
ChangeActionTargetDescription
links-schemasUpdate$.components.schemasAdd source-backed link, sheet-link, version, and whole-book error schemas.
links-category-parameterUpdate$.paths['/api/links/{tref}'].get.parameters[2]Model the repeatable category filter read through request.GET.getlist.
links-response-removeRemove$.paths['/api/links/{tref}'].get.responses['200'].content['application/json'].schemaRemove the incomplete array item schema before replacing it.
links-responseUpdate$.paths['/api/links/{tref}'].get.responses['200'].content['application/json']Use the link and optional sheet-link response union.
links-errorUpdate$.paths['/api/links/{tref}'].get.responsesDocument the whole-book request error.
Values this correction sets

links-schemas:

json
{
  "CoreBilingualText": {
    "type": "object",
    "required": ["en", "he"],
    "properties": {
      "en": {
        "type": "string"
      },
      "he": {
        "type": "string"
      }
    }
  },
  "CoreLinkDisplayMetadata": {
    "type": "object",
    "required": ["index_title", "category", "collectiveTitle"],
    "properties": {
      "index_title": {
        "type": "string"
      },
      "category": {
        "type": "string"
      },
      "collectiveTitle": {
        "$ref": "#/components/schemas/CoreBilingualText"
      }
    }
  },
  "CoreLinkVersion": {
    "type": "object",
    "required": ["title"],
    "properties": {
      "title": {
        "type": "string"
      },
      "language": {
        "type": "string",
        "nullable": true
      }
    }
  },
  "CoreLinkObject": {
    "allOf": [
      {
        "$ref": "#/components/schemas/CoreLinkDisplayMetadata"
      },
      {
        "type": "object",
        "required": [
          "_id",
          "type",
          "ref",
          "anchorRef",
          "anchorRefExpanded",
          "sourceRef",
          "sourceHeRef",
          "anchorVerse",
          "sourceHasEn",
          "commentaryNum"
        ],
        "properties": {
          "_id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "ref": {
            "$ref": "#/components/schemas/ref"
          },
          "anchorRef": {
            "$ref": "#/components/schemas/ref"
          },
          "anchorRefExpanded": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ref"
            }
          },
          "sourceRef": {
            "$ref": "#/components/schemas/ref"
          },
          "sourceHeRef": {
            "type": "string"
          },
          "anchorVerse": {
            "type": "integer"
          },
          "sourceHasEn": {
            "type": "boolean"
          },
          "compDate": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "commentaryNum": {
            "type": "number"
          },
          "he": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "text": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "heVersionTitle": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "versionTitle": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "heLicense": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "license": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "heVersionTitleInHebrew": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "versionTitleInHebrew": {
            "$ref": "#/components/schemas/CoreStringArrayOrNull"
          },
          "inline_reference": {
            "type": "object"
          },
          "highlightedWords": {},
          "anchorVersion": {
            "$ref": "#/components/schemas/CoreLinkVersion"
          },
          "sourceVersion": {
            "$ref": "#/components/schemas/CoreLinkVersion"
          },
          "displayedText": {
            "$ref": "#/components/schemas/CoreBilingualText"
          },
          "heTitle": {
            "type": "string"
          }
        }
      }
    ]
  },
  "CoreSheetLinkObject": {
    "allOf": [
      {
        "$ref": "#/components/schemas/CoreLinkDisplayMetadata"
      },
      {
        "type": "object",
        "required": ["isSheet", "sourceRef", "sourceHeRef"],
        "properties": {
          "isSheet": {
            "type": "boolean",
            "enum": [true]
          },
          "sourceRef": {
            "type": "string"
          },
          "sourceHeRef": {
            "type": "string"
          }
        }
      }
    ]
  },
  "CoreLinkResponse": {
    "oneOf": [
      {
        "type": "array",
        "items": {
          "oneOf": [
            {
              "$ref": "#/components/schemas/CoreLinkObject"
            },
            {
              "$ref": "#/components/schemas/CoreSheetLinkObject"
            }
          ]
        }
      },
      {
        "$ref": "#/components/schemas/CoreErrorResponse"
      }
    ]
  },
  "CoreLinksErrorResponse": {
    "allOf": [
      {
        "$ref": "#/components/schemas/CoreErrorResponse"
      },
      {
        "type": "object",
        "required": ["ref"],
        "properties": {
          "ref": {
            "$ref": "#/components/schemas/ref"
          }
        }
      }
    ]
  }
}

links-category-parameter:

json
{
  "schema": {
    "type": "array",
    "items": {
      "type": "string"
    }
  },
  "style": "form",
  "explode": true
}

links-response:

json
{
  "schema": {
    "$ref": "#/components/schemas/CoreLinkResponse"
  }
}

links-error:

json
{
  "400": {
    "description": "Whole-book references cannot include text.",
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CoreLinksErrorResponse"
        }
      }
    }
  }
}

Citation detection (find-refs) ​

Correction ID: linker-detection-contract

The published description for POST /api/find-refs already defined the request body, the 202 response, and the task states. The correction replaces the body schema, adds query options, and constrains ready. It removes the POST 200 entry, because the correction's notes say the pinned handler does not return one. It makes result an open JSON object with unknown-valued properties. Callers must validate the result for the specific task.

Endpoints: GET /api/async/{task_id}, POST /api/find-refs.

Evidence: Sefaria source.

Source checks:

  • $.paths['/api/find-refs'].post is unchanged (SHA-256 starting ace9410fb005).
  • $.paths['/api/find-refs'].post.parameters is absent.
  • $.paths['/api/find-refs'].post.responses['200'] equals {"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindRefsAPIResponse"}}},"description":"Shape of the `result` field returned by `GET /api/async/{task_id}` on successful completion."}.
  • $.components.schemas.FindRefsAPIResponse is unchanged (SHA-256 starting ab16f29518e4).
  • $.components.schemas.AsyncTaskSuccess is unchanged (SHA-256 starting 4ef7fa723544).
  • $.components.schemas.CoreFindRefsRequest is absent.
  • $.components.schemas.CoreFindRefsReferenceData is absent.
  • $.components.schemas.CoreFindRefsMatch is absent.
  • $.components.schemas.CoreFindRefsSection is absent.
  • $.components.schemas.CoreFindRefsResponse is absent.
ChangeActionTargetDescription
linker-detection-schemasUpdate$.components.schemasAdd source-backed request and response schemas for asynchronous citation detection.
linker-detection-requestUpdate$.paths['/api/find-refs'].post.requestBody.content['application/json']Match the validated request accepted by the pinned handler.
linker-detection-queryUpdate$.paths['/api/find-refs'].postAdd the query options read by the pinned response builder.
linker-detection-synchronous-response-removeRemove$.paths['/api/find-refs'].post.responses['200']Remove the synchronous response that the pinned handler never returns.
linker-pending-readyUpdate$.components.schemas.AsyncTaskPending.properties.readyModel the pinned pending response invariant.
linker-success-readyUpdate$.components.schemas.AsyncTaskSuccess.properties.readyModel the pinned success response invariant.
linker-success-resultUpdate$.components.schemas.AsyncTaskSuccess.properties.resultPreserve the generic task result as unknown keyed JSON for boundary-specific validation.
linker-failure-readyUpdate$.components.schemas.AsyncTaskFailure.properties.readyModel the pinned failure response invariant.
Values this correction sets

linker-detection-schemas:

json
{
  "CoreFindRefsRequest": {
    "type": "object",
    "additionalProperties": false,
    "required": ["text"],
    "properties": {
      "text": {
        "type": "object",
        "additionalProperties": false,
        "required": ["title", "body"],
        "properties": {
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        }
      },
      "lang": {
        "type": "string",
        "enum": ["he", "en"]
      },
      "metaDataForTracking": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "title": {
            "type": "string"
          }
        }
      },
      "version_preferences_by_corpus": {
        "type": "object",
        "nullable": true,
        "additionalProperties": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      }
    }
  },
  "CoreFindRefsReferenceData": {
    "type": "object",
    "additionalProperties": false,
    "required": ["heRef", "url", "primaryCategory"],
    "properties": {
      "heRef": {
        "type": "string"
      },
      "url": {
        "type": "string"
      },
      "primaryCategory": {
        "type": "string"
      },
      "he": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "en": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "isTruncated": {
        "type": "boolean"
      }
    }
  },
  "CoreFindRefsMatch": {
    "type": "object",
    "additionalProperties": false,
    "required": ["startChar", "endChar", "text", "linkFailed", "refs"],
    "properties": {
      "startChar": {
        "type": "integer",
        "minimum": 0
      },
      "endChar": {
        "type": "integer",
        "minimum": 0
      },
      "text": {
        "type": "string"
      },
      "linkFailed": {
        "type": "boolean"
      },
      "refs": {
        "type": "array",
        "nullable": true,
        "items": {
          "$ref": "#/components/schemas/ref"
        }
      }
    }
  },
  "CoreFindRefsSection": {
    "type": "object",
    "additionalProperties": false,
    "required": ["results", "refData"],
    "properties": {
      "results": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CoreFindRefsMatch"
        }
      },
      "refData": {
        "type": "object",
        "additionalProperties": {
          "$ref": "#/components/schemas/CoreFindRefsReferenceData"
        }
      },
      "debugData": {
        "type": "array",
        "items": {}
      }
    }
  },
  "CoreFindRefsResponse": {
    "type": "object",
    "additionalProperties": false,
    "required": ["title", "body"],
    "properties": {
      "title": {
        "$ref": "#/components/schemas/CoreFindRefsSection"
      },
      "body": {
        "$ref": "#/components/schemas/CoreFindRefsSection"
      },
      "url": {
        "type": "string"
      }
    }
  }
}

linker-detection-request:

json
{
  "schema": {
    "$ref": "#/components/schemas/CoreFindRefsRequest"
  }
}

linker-detection-query:

json
{
  "parameters": [
    {
      "name": "with_text",
      "in": "query",
      "required": false,
      "schema": {
        "type": "string",
        "enum": ["0", "1"]
      }
    },
    {
      "name": "debug",
      "in": "query",
      "required": false,
      "schema": {
        "type": "string",
        "enum": ["0", "1"]
      }
    },
    {
      "name": "max_segments",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 0
      }
    }
  ]
}

linker-pending-ready:

json
{
  "enum": [false]
}

linker-success-ready:

json
{
  "enum": [true]
}

linker-success-result:

json
{
  "additionalProperties": true,
  "x-sefaria-known-result-schema": {
    "$ref": "#/components/schemas/CoreFindRefsResponse"
  }
}

linker-failure-ready:

json
{
  "enum": [true]
}

Where to go next ​

Sefaria Frontend ToolkitCommunity-driven with Sefaria backing and support. GitHub Get support

AI-generated documentation.

About this documentation

Like the codebase, this documentation was scaffolded and written with GitHub Copilot. I don't have a background in technical writing, and wanted to get something out there.

Pages that have not undergone any human review are explicitly marked, but the others may also read funny or need work too. Sorry about that.

Please report any issues so they can be prioritized.

Thanks, Avi