Skip to content

Algorithms API#

The Algorithms endpoints let a server integration discover the search algorithms available in its Storyteller tenant, inspect their current category boosts, and create or replace a boost using stable caller-facing identifiers.

Your system can define editorial presets such as high, medium, or low. Storyteller does not store those preset names or mappings; send the concrete boost configuration that your preset represents.

Endpoints#

Get Search Algorithms#

GET https://integrations.usestoryteller.com/api/search-algorithms

Get Category Boosts#

GET https://integrations.usestoryteller.com/api/search-algorithms/{algorithmKey}/category-boosts

Create or Replace a Category Boost#

PUT https://integrations.usestoryteller.com/api/search-algorithms/{algorithmKey}/category-boosts/{categoryExternalId}

Headers#

Header Required Description
x-storyteller-api-key Yes A Server App API key for authentication.
Content-Type: application/json PUT only Identifies the request body as JSON.

Storyteller derives the tenant from the Server App key. Do not send a tenant identifier or expose the key in browser code.

Get Search Algorithms#

Returns every active search algorithm in the authenticated tenant, ordered by key. The response is not paginated.

curl --request GET \
  "https://integrations.usestoryteller.com/api/search-algorithms" \
  --header "x-storyteller-api-key: your-api-key-here"

Response (200 OK)#

{
  "searchAlgorithms": [
    {
      "key": "cards-default",
      "name": "Cards Default Algorithm",
      "description": "Storyteller default search algorithm for cards",
      "type": "cards"
    },
    {
      "key": "clips-default",
      "name": "Clips Default Algorithm",
      "description": "Storyteller default search algorithm for clips",
      "type": "clips"
    }
  ]
}
Field Type Description
key string Stable algorithm key to use in the category-boost routes.
name string Human-readable algorithm name.
description string or null Optional explanation of the algorithm.
type string Content type ranked by the algorithm: clips or cards.

Database IDs and the algorithm's other ranking configuration are not exposed.

Get Category Boosts#

Returns the current category boosts for one algorithm, ordered by category external ID. An existing algorithm with no configured boosts returns an empty categoryBoosts array.

algorithmKey is trimmed and matched case-insensitively. It must be non-empty and no more than 256 characters.

curl --request GET \
  "https://integrations.usestoryteller.com/api/search-algorithms/clips-default/category-boosts" \
  --header "x-storyteller-api-key: your-api-key-here"

Response (200 OK)#

{
  "searchAlgorithmKey": "clips-default",
  "categoryBoosts": [
    {
      "categoryExternalId": "example-category",
      "weight": 42,
      "decayType": "none",
      "decayOrigin": "now",
      "decayScale": "1d",
      "decayOffset": null,
      "decayValue": 0.5
    }
  ]
}

The response contains stable algorithm and category identifiers only. It does not expose database IDs.

Create or Replace a Category Boost#

PUT identifies one boost by algorithm key and category external ID. It creates the boost when none exists and completely replaces the concrete configuration when it does.

categoryExternalId must be the existing category's canonical lowercase external ID. Whitespace, uppercase characters, reserved characters, missing values, and overlong values are rejected rather than normalized.

curl --request PUT \
  "https://integrations.usestoryteller.com/api/search-algorithms/clips-default/category-boosts/example-category" \
  --header "x-storyteller-api-key: your-api-key-here" \
  --header "Content-Type: application/json" \
  --data '{
    "weight": 42,
    "decayType": "none",
    "decayOrigin": "now",
    "decayScale": "1d",
    "decayOffset": null,
    "decayValue": 0.5
  }'

Request Body#

Field Type Default Description
weight number 100 Finite number greater than or equal to zero. Zero disables the effective boost.
decayType string gauss linear, gauss, exp, or none, matched case-insensitively. none applies a fixed weight without decay.
decayOrigin string now now, an invariant date, or a now-math expression such as now-1d; maximum 64 characters.
decayScale string 1d Positive duration such as 30m, 1.5h, or 2d; maximum 64 characters.
decayOffset string or null null Optional duration using the same grammar and length limit as decayScale. Empty text normalizes to null.
decayValue number 0.5 Finite number greater than zero and less than or equal to one.

PUT is a complete replacement. Omitted fields take these defaults instead of preserving stored values.

Success Responses#

A new boost returns 201 Created and a relative Location header. Updating a boost or replaying an identical request returns 200 OK.

HTTP/1.1 201 Created
Location: /api/search-algorithms/clips-default/category-boosts/example-category

Every success returns the effective normalized configuration:

{
  "outcome": "created",
  "searchAlgorithmKey": "clips-default",
  "categoryExternalId": "example-category",
  "weight": 42,
  "decayType": "none",
  "decayOrigin": "now",
  "decayScale": "1d",
  "decayOffset": null,
  "decayValue": 0.5
}

outcome is created, updated, or unchanged. The database change is committed before the response. Cache and search projections are reconciled asynchronously and may take a short time to converge.

Errors#

Errors use Problem Details.

Status Meaning
400 Bad Request A route identifier, JSON body, decay setting, duration, or number is invalid.
401 Unauthorized The Server App key is missing or invalid.
404 Not Found The active algorithm or category does not exist in the authenticated tenant. Another tenant's resources are never disclosed.
500 Internal Server Error An unexpected persistence, background-job dispatch, cache, search, or infrastructure failure occurred.

The PUT is idempotent and safe to retry. If the database commit succeeds but asynchronous reconciliation cannot be dispatched, the request returns 500; retrying the same PUT returns unchanged and schedules reconciliation again. Concurrent PUTs use last-committed-write-wins semantics. ETag and If-Match conditional updates are not supported.