---
title: "Record a steering render (partner-tier keys only)"
method: POST
path: "/api/v1/steering-events"
tags: ["Observations"]
---

# Record a steering render (partner-tier keys only)

`POST /api/v1/steering-events`

## Request

- Base URL: `https://api.shelfatlas.com`
- URL: `https://api.shelfatlas.com/api/v1/steering-events`
- Auth: HTTP bearer

First-party telemetry: a partner's consumer surface posts one row per candidate chain every time it localizes a "best choice" card, so the chosen store can be compared against the nearest store per candidate chain. Rolled up into daily, per-chain aggregates only — no per-request identifiers or coordinates are ever stored; `distance_band` is a client-computed bucket ('<1'|'1-3'|'3-10'|'>10'), never a raw lat/lng. Partner-tier API keys only (ShelfAtlas' own consumer surfaces); any other tier gets `forbidden_tier`. Chain ids are resolved from the given store ids server-side — never accepted from the client.

## Request body

- SteeringEventRequest
  - `product_id` string, uuid, required
  - `winning_store_id` string, uuid, required: The store the "best choice" card actually pointed to.
  - `visitor_key` string, uuid: Opaque per-device key the consumer surface generates and keeps locally, used only for the report's COUNT(DISTINCT visitor). Omit to skip unique-visitor counting for this render.
  - `involved` object[], required: One entry per candidate chain compared for this render.
    - `nearest_store_id` string, uuid, required: The candidate chain's store nearest the visitor.
    - `distance_band` '<1' | '1-3' | '3-10' | '>10', required: Client-computed distance bucket, kilometres — never a raw coordinate.
    - `price_gap_cents` integer, required: This candidate's price minus the winning store's, in cents.

## Response `202`

Steering rows recorded.

- SteeringEventResult
  - `ok` true, required
  - `recorded` integer, required: Number of `involved` rows rolled up.

## Other responses

- `400`: Malformed body (`invalid_body`) — including a coordinate-like key (`lat`/`lng`/`lon`/`latitude`/`longitude`) anywhere in the payload, `involved` empty or over 25 entries, or an unrecognised field — or a referenced entity does not exist: no product matches `product_id` (`unknown_product`), or a store id in `winning_store_id`/`involved[].nearest_store_id` does not match any store (`unknown_store`).
- `401`: No `Authorization` header (`missing_auth`); the API key is malformed/unrecognised (`invalid_auth`); or the key was revoked (`revoked`).
- `403`: The API key is not partner-tier (`forbidden_tier`).

---

[API](https://skmtc.dev/shelfatlas/apis/shelfatlas-catalog-api.md) · [All operations](https://skmtc.dev/shelfatlas/apis/shelfatlas-catalog-api/llms.txt) · [OpenAPI document](https://skmtc.dev/shelfatlas/apis/shelfatlas-catalog-api/revisions/943a8773856b?raw)
