StrideMoor lets you expose your own activity and health data to an AI agent that you build or host.
Typical use: have your agent read your sleep and recovery every morning and draft training advice, or sync your runs into your personal knowledge base.
{"value": 7.2, "unit": "h"} — you never have to guess a unit.Send the key in a header on every request:
curl -H "X-API-Key: sk_sm_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
https://www.8keya.com/api/v1/agent/capabilities
Start with /agent/capabilities: it tells you which endpoints this key may call, which scopes it holds, and what the rate limits are.
Then get a full picture of today in a single call:
curl -H "X-API-Key: sk_sm_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
https://www.8keya.com/api/v1/agent/overview
All read scopes are granted by default when a key is created. Each one covers a category of data:
| scope | Description |
|---|---|
| read:profile | Profile, cumulative stats, running/cycling realm |
| read:runs | Runs: list, detail, averages, bookmarks |
| read:stats | Weekly/monthly/yearly summary stats |
| read:routes | Routes: list, detail, leaderboard, nearby |
| read:social | Friends and follow relationships |
| read:challenges | Challenges: list, ranking, detail, comparison |
| read:health | Health: data points, daily stats, history, recovery, ECG |
| read:devices | Bound devices and their status |
| read:points | Points: balance, transactions, products |
| read:content | Community feed, posts, comments (public content) |
| read:notifications | My notifications |
| read:ai | Previously generated AI analyses (read-only) |
| read:system | Weather, reverse geocoding, version, public config |
| read:agent | Agent aggregate endpoints |
| write:bookmarks | Run bookmarks: add / remove (write, not granted by default) |
| write:favorites | Run & route favorites: add / remove (write, not granted by default) |
| write:follow | Follow / unfollow users (write, not granted by default) |
60 endpoints in total, all GET. Endpoints marked self-only or participant-only verify ownership and return 403 on cross-user access.
| Endpoint | Description |
|---|---|
| GET /agent/capabilities | Self-describing: this key's scopes, all available endpoints, unit conventions, rate limits Agents bootstrap from this; no guessing needed. |
| GET /agent/health-summary | Health summary for the last N days (aggregates only, no raw samples) ?days=1-30 (default 7). Use /health/* with a bounded window for raw samples. Parameters: days optional (string) |
| GET /agent/overview | Overview: today's activity + latest run + recovery state + running realm Replaces 5-6 separate calls. |
| GET /agent/recent-runs | Recent run summaries (with units and per-run pace) ?limit=1-200 (default 5) & ?page. Parameters: limit optional (string) · page optional (string) |
| GET /agent/today | All metrics for one day (steps / distance / calories / sleep / VO2max / ECG count) Optional ?date=YYYY-MM-DD; defaults to the server's current date. Parameters: date optional (date, default None) |
| GET /agent/weekly-report | This week vs last week: distance, duration, count, average pace Optional ?date= to pick the reference day. Parameters: date optional (date, default None) |
| Endpoint | Description |
|---|---|
| GET /user/paojing | Running realm (running level system) Current realm, progress and badges. |
| GET /user/profile | My profile Nickname, avatar, body parameters, VIP level. |
| GET /user/qijing | Cycling realm (cycling level system) |
| GET /user/stats/heats | Activity heatmap Activity intensity aggregated by date. |
| GET /users/{id}/stats | Cumulative stats (self only) ⚠️ The path parameter must be your own users.id, otherwise 403. |
| Endpoint | Description |
|---|---|
| GET /runs | Run list (paginated) ?page & ?page_size (max 200). Parameters: page optional (integer, default 1) · page_size optional (integer, default 10) |
| GET /runs/{id} | Run detail (own runs only) Someone else's run returns 401. |
| GET /runs/{id}/bookmark | Bookmark a run (write) Bookmarking twice returns a business error; replays with Idempotency-Key return the first response. |
| GET /runs/{id}/bookmark | Remove a run bookmark (write) No error when it was not bookmarked. |
| GET /runs/{id}/favorite | Add a run to favorites (write) Separate list from bookmark; the app shows them independently. |
| GET /runs/{id}/favorite | Remove a run from favorites (write) |
| GET /runs/averages | Run averages (pace / distance / duration / cadence) |
| GET /runs/bookmarks/list | Bookmarked runs Parameters: sport_type optional (string, default None) |
| Endpoint | Description |
|---|---|
| GET /stats | Weekly / monthly / yearly summary stats ?period=week|month|year|total & ?sport_type=all|run|cycle & ?date= Parameters: sport_type optional (string, default all) · period optional (string, default week) · date optional (string, default None) |
| Endpoint | Description |
|---|---|
| GET /routes | Route list |
| GET /routes/{id} | Route detail |
| GET /routes/{id}/favorite | Favorite a route (write) |
| GET /routes/{id}/favorite | Unfavorite a route (write) |
| GET /routes/{id}/leaderboard | Route leaderboard (public) Parameters: page optional (integer, default 1) · page_size optional (integer, default 20) · sort_by optional (string, default None) · sport_type optional (string, default None) |
| GET /routes/favorites | Favourite routes Parameters: page optional (integer, default 1) · page_size optional (integer, default 10) |
| GET /routes/nearby | Nearby routes (public) ?lat & ?lng & ?radius (meters) & ?limit. Parameters: lat required (number) · lng required (number) · radius optional (number, default 5000) · limit optional (integer, default 20) |
| Endpoint | Description |
|---|---|
| GET /friends | Friend list Parameters: page optional (integer, default 1) · page_size optional (integer, default 20) |
| GET /friends/requests/pending | Pending friend requests Parameters: page optional (integer, default 1) · page_size optional (integer, default 20) |
| GET /users/{id}/follow | Follow a user (write) :id is the target user's users.id; following yourself is rejected. The actor is always the key owner. |
| GET /users/{id}/follow | Unfollow a user (write) |
| GET /users/followers | My followers Parameters: page optional (integer, default 1) · page_size optional (integer, default 20) |
| GET /users/followings | Accounts I follow Parameters: page optional (integer, default 1) · page_size optional (integer, default 20) |
| Endpoint | Description |
|---|---|
| GET /challenges | Challenge list ?status & ?page & ?page_size. Parameters: status optional (string) · page optional (integer, default 1) · page_size optional (integer, default 10) |
| GET /challenges/{id} | Challenge detail (participants only) Non-participants get 403. |
| GET /challenges/{id}/comparison | Challenge comparison report (participants only) Non-participants get 403. |
| GET /challenges/ranking | Challenge ranking (public) ?type=challenger|defender & ?limit. Parameters: type optional (string, default challenger) · limit optional (integer, default 20) |
| Endpoint | Description |
|---|---|
| GET /health/daily-stats | Daily health statistics ⚠️ from/to (YYYY-MM-DD) required; span ≤30 days. Parameters: from required (date) · to required (date) |
| GET /health/data-points | Health data points (heart rate / blood pressure / SpO2 / stress / invasive) ⚠️ from/to required; a single request may span at most 30 days. Parameters: type required (string) · from required (integer) · to optional (integer, omitted = unbounded) · page optional (integer, default 1) · size optional (integer, default 100) |
| GET /health/ecg | ECG records ⚠️ from/to required; span ≤30 days. Parameters: from required (integer) · to optional (integer, omitted = unbounded) · page optional (integer, default 1) · size optional (integer, default 20) |
| GET /health/history | Health history by type and date ⚠️ ?type required; start_date + end_date span ≤30 days. Parameters: type required (string) · start_date required (string) · end_date required (string) · date required (date) |
| GET /health/recovery | Recovery aggregate (recovery time / training load / body state / VO2max / weekly volume) Server-side fixed-window aggregate; no time parameters needed. |
| Endpoint | Description |
|---|---|
| GET /devices | Bound devices (model / battery / last sync time) |
| Endpoint | Description |
|---|---|
| GET /points/balance | Points and token balance |
| GET /points/products | Redeemable products |
| GET /points/transactions | Points transaction history Parameters: page optional (string, default 1) · page_size optional (string, default 20) · type optional (string, default 0) |
| Endpoint | Description |
|---|---|
| GET /feed | Community feed (public content) Parameters: cursor optional (string, default None) · limit optional (integer, default 10) · from optional (string) · to optional (string) |
| GET /feed/{id}/track | Track attached to a feed post (public content) |
| GET /posts | Post list (public content) Parameters: page optional (integer, default 1) · page_size optional (integer, default 10) |
| GET /posts/{id} | Post detail (public content) |
| GET /posts/{id}/comments | Post comments (public content) Parameters: page optional (integer, default 1) · page_size optional (integer, default 10) |
| Endpoint | Description |
|---|---|
| GET /notifications | My notifications Parameters: page optional (integer, default 1) · page_size optional (integer, default 20) |
| GET /notifications/unread/count | Unread notification count |
| Endpoint | Description |
|---|---|
| GET /ai/analyses/{run_id} | Previously generated run analysis (read-only, never triggers a new AI call) Returns only your own cached analysis; 404 if none, 403 for someone else's. |
| GET /ai/daily-quote | Daily quote Parameters: city optional (string) · locale optional (string) |
| GET /ai/features | AI feature list |
| Endpoint | Description |
|---|---|
| GET /app/version | Latest app version (public) Parameters: current optional (integer, default 0) · platform optional (string, default android) |
| GET /geocode/reverse | Reverse geocoding (public) ?lat & ?lng. Parameters: location required (string) |
| GET /system/config/{key} | Public system config value (public) |
| GET /weather | Weather (public) Parameters: city required (string) · lat required (number) · lng required (number) · locale optional (string) |
Every numeric field is a value/unit object. Units used:
| field | unit |
|---|---|
| distance | m |
| duration | s |
| pace | s/km |
| cadence_run / cadence_cycle | spm / rpm |
| steps | count |
| calories | kcal |
| sleep | h |
| heart_rate | bpm |
| blood_oxygen | % |
| body_temp | °C |
| vo2max | ml/kg/min |
Failures return a real HTTP status code (errors are never hidden inside a 200), with a body of {code, message}:
| HTTP | Description |
|---|---|
| 400 | Invalid parameters |
| 401 | Missing, invalid or revoked API key |
| 403 | Insufficient scope, or attempting to access another user's data |
| 404 | Not found, or not owned by you |
| 429 | Rate limited (see Retry-After) |
By default each key is limited to 60 requests per minute and 5000 per day. Exceeding it returns 429 with a Retry-After header.
Timestamps are UTC seconds or RFC3339, alongside a local_date. All time-series endpoints require an explicit, bounded range of at most 30 days.
disclaimer field (in Chinese and English). Please preserve it in your agent's output — it is not an optional decoration you may strip.If your client supports MCP you can skip writing any HTTP code — point it at StrideMoor's MCP endpoint and it discovers the available tools itself. See MCP Access.
An OpenAPI 3.1 spec is also published and can be imported directly by agent platforms that support function calling:
StrideMoor