yoftdocs

API documentation

Beyond forecasting

Analyze time series with anomaly detection, imputation, and embeddings.

Anomaly detection

Scores every time step of a series, surfacing points that deviate from normal behaviour without anyone hand-tuning thresholds.

POST /v1/anomaly

Request body

FieldTypeDescription
modelstringModel to use. Defaults to yoft
seriesobject[]Target series (16–2048 points each)
test_startintegerIndex where scoring starts; everything before it is treated as the normal reference window (default 0 = score everything)
curl
curl -X POST https://YOUR_API_BASE/v1/anomaly \
  -H "Authorization: Bearer $YOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"test_start": 8, "series": [{"name": "s1", "values": [1.0, 1.2, 1.1, 1.4, 1.3, 1.5, 1.4, 1.6, 1.5, 1.7, 1.6, 1.8, 1.7, 1.9, 1.8, 9.9]}]}'

Response

FieldDescription
pitDistributional surprise — higher means the observed value falls further outside the model's predictive distribution
crpsMagnitude of the gap between the predictive distribution and the observation
test_startEcho of the requested start index for the score arrays
200 response
{
  "request_id": "req_7b2c48...",
  "model": "yoft",
  "model_version": "v1",
  "test_start": 8,
  "series": [
    {
      "name": "s1",
      "pit": [
        0.62,
        0.71,
        0.55,
        0.83,
        0.64,
        0.79,
        0.6,
        41.2
      ],
      "crps": [
        0.05,
        0.06,
        0.04,
        0.07,
        0.05,
        0.06,
        0.05,
        6.83
      ]
    }
  ],
  "usage": {
    "input_points": 16,
    "output_points": 16,
    "series_count": 1
  }
}

One score per time step from test_start onward (array length = series length − test_start). Strong on sharp spikes and level shifts; less sensitive to gradual, calendar-driven changes.

Imputation

Send a series with gaps and get the missing values back — for recovering telemetry after outages or maintenance stops.

POST /v1/impute

Missing values are JSON null. Each series needs at least one null and at least one observed value (all-missing and no-missing are both 400).

curl
curl -X POST https://YOUR_API_BASE/v1/impute \
  -H "Authorization: Bearer $YOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"series": [{"name": "s1", "values": [1.0, 1.2, 1.1, 1.4, null, null, 1.4, 1.6, 1.5, 1.7, 1.6, 1.8, 1.7, 1.9, 1.8, 2.0]}]}'

Response

FieldDescription
valuesFull-length series: observed positions unchanged, missing positions filled with the median estimate
missing_indicesIndices that were imputed
quantilesQuantiles at the missing positions (0.1 / 0.2 / 0.3 / 0.4 / 0.5 / 0.6 / 0.7 / 0.8 / 0.9), in the same order as missing_indices
200 response
{
  "request_id": "req_9e14c3...",
  "model": "yoft",
  "model_version": "v1",
  "series": [
    {
      "name": "s1",
      "values": [
        1,
        1.2,
        1.1,
        1.4,
        1.32,
        1.38,
        1.4,
        1.6,
        …
      ],
      "missing_indices": [
        4,
        5
      ],
      "quantiles": {
        "0.1": [
          1.19,
          1.24
        ],
        "0.5": [
          1.32,
          1.38
        ],
        "0.9": [
          1.46,
          1.53
        ]
      }
    }
  ],
  "usage": {
    "input_points": 16,
    "output_points": 2,
    "series_count": 1
  }
}

Embeddings (similarity search and classification)

Turn a series into a fixed-length vector, then use it for similarity search or to train your own lightweight classifier.

POST /v1/embed

yoft returns 3840-dimensional vectors. The dimension depends on the model checkpoint, so read dim from the response.

curl
curl -X POST https://YOUR_API_BASE/v1/embed \
  -H "Authorization: Bearer $YOFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"series": [{"name": "s1", "values": [1.0, 1.2, 1.1, 1.4, 1.3, 1.5, 1.4, 1.6, 1.5, 1.7, 1.6, 1.8, 1.7, 1.9, 1.8, 2.0]}]}'
200 response
{
  "request_id": "req_0d5f1a...",
  "model": "yoft",
  "model_version": "v1",
  "dim": 3840,
  "embeddings": [
    {
      "name": "s1",
      "vector": [
        0.0121,
        -0.0384,
        …
      ]
    }
  ],
  "usage": {
    "input_points": 16,
    "output_points": 0,
    "series_count": 1
  }
}

What to use it for

  • Similarity search: cosine similarity between vectors finds series (or days) with similar shape
  • Classification: train logistic regression on a small labelled set, then classify from vectors alone
  • Clustering: group equipment, stores, or circuits by behaviour

Practical note: cosine similarity between raw vectors saturates above 0.98 and hides differences. Subtract the mean vector of the comparison set (center them) before computing similarity.