Developer documentation

Telemetry in. Events and exposure out.

The interface below is being implemented against the validated detector. It is not generally available — access today is through a design partnership, and there are no uptime guarantees.

Authentication

Bearer token on every request. Keys are environment-scoped; a sk_test_ key returns real computation against your payload but is never metered.

Authorization: Bearer sk_live_...

Score a trip

POST /v1/trips:score — speed in m/s and curvature in 1/m, sampled at a fixed rate. Curvature may be supplied directly or derived from yaw rate and speed.

Request
{
  "fps": 20.0,
  "trip_id": "3f9a2c",
  "speed_mps":     [24.9, 24.9, 24.8, ...],
  "curvature_1pm": [0.0021, 0.0019, ...],
  "thresholds": {
    "harsh_brake_mps2": -3.0,
    "harsh_accel_mps2": 3.0,
    "hard_corner_mps2": 3.0
  }
}
Response
{
  "trip_id": "3f9a2c",
  "distance_km": 1.047,
  "events": [{
    "kind": "harsh_brake",
    "start_frame": 412,
    "end_frame": 441,
    "duration_s": 1.45,
    "peak_mps2": -4.31,
    "mean_speed_mps": 17.2
  }],
  "rates_per_100km": {
    "harsh_brake": 95.5,
    "harsh_accel": 0.0,
    "hard_corner": 0.0
  },
  "calibration": "uncalibrated"
}

Every response carries a calibration field. While it reads uncalibrated, the rates are measurements against a chosen threshold and carry no validated relationship to loss. We would rather ship that field than let a number be mistaken for a score.

Parameters

FieldTypeDefaultNotes
fpsnumberRequired. Sample rate of the arrays.
speed_mpsnumber[]Required. Metres per second.
curvature_1pmnumber[]Required, same length as speed. Positive = right turn.
smooth_window_snumber0.5Applied before differentiation.
min_duration_snumber0.2Shorter crossings are discarded as noise.
merge_gap_snumber1.0Same-kind events closer than this merge.
min_corner_speed_mpsnumber5.0Below this, cornering is parking.

Errors

StatusCodeMeaning
400length_mismatchspeed and curvature arrays differ in length.
400implausible_curvatureImplied lateral acceleration exceeds what tyres can deliver — usually a steering angle sent as curvature.
401invalid_keyMissing or unrecognised bearer token.
422trip_too_shortFewer than two samples; nothing to differentiate.
429rate_limitedRetry after the interval in the response header.

implausible_curvature is a deliberate hard failure rather than a warning. Wrong units there produce event counts that look merely high, which is far more dangerous than a rejected request.

Run it in your own environment

The detector is a small pure-Python library with no service dependency, for partners who would rather not send telemetry anywhere.

from wahanx.risk import events as E

cfg = E.EventConfig(fps=20.0, harsh_brake_mps2=-3.0)
ev  = E.detect_events(trip_df, cfg)   # columns: sequence_id, frame_idx, speed, curvature
km  = E.exposure_km(trip_df, cfg)
E.summarise(ev, km)
# {'harsh_brake_per_100km': 24.4, 'hard_corner_per_100km': 39.3, ...}