mobieusKnow API: mobieusBuddy & mobieusChallenge History #460
Author
Patrick Bass
Submitted
Jul 28, 2026 3:38pm
Reviewed
Jul 28, 2026 3:38pm
Summary
API reconciliation to 1.23.0 — full surface coverage, corrected plan gate, X-API-Version

API: mobieusBuddy & mobieusChallenge

Peer accountability and competitive challenges, both of which move health data between members — so both are consent-gated and audited. Documented in the REST API from 1.23.0.

These surfaces were reachable before 1.23.0 but enforced no scope. If you built against them earlier, your key now needs the scopes below.

Plan and feature gates

Available on Pro, Creator, Creator Plus, and Sovereign. Each product is also behind its own feature flag — mobieus_buddy and mobieus_challenge. When a flag is off, its routes return 404, not 403: a disabled feature is invisible rather than advertised.

Scopes

Scope follows the data, not the product. Anything that reads or governs access to a health record takes a health:* scope; social actions that carry a message rather than a health value take social:*.

Scope Used for
health:read The buddy graph, pacts, challenge leaderboards, and reading a buddy's shared data
health:write Creating or revoking a sharing grant — invite, accept, withdraw, pause, resume, set-grants, join a challenge, leave one
social:read Challenge and buddy metadata, feeds, invitations
social:write Nudges, cheers, comments, reactions, flags

mobieusBuddy

Method Path Scope
GET /api/v1/buddy health:read
POST /api/v1/buddy/invite health:write
POST /api/v1/buddy/{id}/accept health:write
POST /api/v1/buddy/{id}/withdraw health:write
POST /api/v1/buddy/{id}/pause · /resume health:write
POST /api/v1/buddy/{id}/grants health:write
POST /api/v1/buddy/{id}/prefs health:write
GET /api/v1/buddy/{ownerId}/data/{category} health:read
GET POST /api/v1/buddy/interactions social:read / social:write
GET /api/v1/buddy/pacts · POST /api/v1/buddy/{id}/pacts health:read / health:write

Reading a buddy's data

curl https://YOUR-TENANT.mobieus.io/api/v1/buddy/42/data/weight \
  -H "Authorization: Bearer mc_live_..."

The owner must have granted you that category. Without a grant you get 403 not_shared — the same response you get for a member who never shared with you, so the endpoint does not disclose whether a relationship exists.

Every read is written to the owner's access log. They can see who looked, at what, and when, and they can revoke at any time; revocation takes effect on the next call.

The response is shaped to the detail level the owner chose, not to what you asked for: full returns entries, summary returns a rollup without absolute values, streak returns consistency only. Do not assume entries are present.

mobieusChallenge

Method Path Scope
GET POST /api/v1/challenges social:read / social:write
GET /api/v1/challenges/{id} social:read
POST /api/v1/challenges/{id}/join · /leave · /join-by-code health:write
GET /api/v1/challenges/{id}/leaderboard health:read
GET POST /api/v1/challenges/{id}/feed social:read / social:write
POST /api/v1/challenges/{id}/feed/{postId}/react · /delete social:write
POST /api/v1/challenges/{id}/invite · /invite/decline social:write
GET POST /api/v1/challenges/{id}/flags · /flag social:read / social:write

Joining a challenge is a health:write action because it creates a sharing grant: your scored metric becomes visible to that challenge's members for its duration. Leaving revokes it.

Leaderboards read from server-computed snapshots of the scored metric only — never raw logs. A percentage challenge stores the percentage, not the weight behind it.

403 not_participant on a leaderboard or feed means the key owner has not joined that challenge. It is not a scope problem.

See also

## API: mobieusBuddy & mobieusChallenge

Peer accountability and competitive challenges, both of which move health data between members — so both are consent-gated and audited. Documented in the REST API from **1.23.0**.

These surfaces were reachable before 1.23.0 but enforced no scope. If you built against them earlier, your key now needs the scopes below.

### Plan and feature gates

Available on **Pro**, **Creator**, **Creator Plus**, and **Sovereign**. Each product is also behind its own feature flag — `mobieus_buddy` and `mobieus_challenge`. When a flag is off, its routes return `404`, not `403`: a disabled feature is invisible rather than advertised.

### Scopes

Scope follows the **data**, not the product. Anything that reads or governs access to a health record takes a `health:*` scope; social actions that carry a message rather than a health value take `social:*`.

| Scope | Used for |
|---|---|
| `health:read` | The buddy graph, pacts, challenge leaderboards, and reading a buddy's shared data |
| `health:write` | Creating or revoking a sharing grant — invite, accept, withdraw, pause, resume, set-grants, join a challenge, leave one |
| `social:read` | Challenge and buddy metadata, feeds, invitations |
| `social:write` | Nudges, cheers, comments, reactions, flags |

### mobieusBuddy

| Method | Path | Scope |
|---|---|---|
| `GET` | `/api/v1/buddy` | `health:read` |
| `POST` | `/api/v1/buddy/invite` | `health:write` |
| `POST` | `/api/v1/buddy/{id}/accept` | `health:write` |
| `POST` | `/api/v1/buddy/{id}/withdraw` | `health:write` |
| `POST` | `/api/v1/buddy/{id}/pause` · `/resume` | `health:write` |
| `POST` | `/api/v1/buddy/{id}/grants` | `health:write` |
| `POST` | `/api/v1/buddy/{id}/prefs` | `health:write` |
| `GET` | `/api/v1/buddy/{ownerId}/data/{category}` | `health:read` |
| `GET` `POST` | `/api/v1/buddy/interactions` | `social:read` / `social:write` |
| `GET` | `/api/v1/buddy/pacts` · `POST /api/v1/buddy/{id}/pacts` | `health:read` / `health:write` |

#### Reading a buddy's data

```bash
curl https://YOUR-TENANT.mobieus.io/api/v1/buddy/42/data/weight \
  -H "Authorization: Bearer mc_live_..."
```

The owner must have granted you that category. Without a grant you get `403 not_shared` — the same response you get for a member who never shared with you, so the endpoint does not disclose whether a relationship exists.

Every read is written to the owner's access log. They can see who looked, at what, and when, and they can revoke at any time; revocation takes effect on the next call.

The response is shaped to the **detail level** the owner chose, not to what you asked for: `full` returns entries, `summary` returns a rollup without absolute values, `streak` returns consistency only. Do not assume entries are present.

### mobieusChallenge

| Method | Path | Scope |
|---|---|---|
| `GET` `POST` | `/api/v1/challenges` | `social:read` / `social:write` |
| `GET` | `/api/v1/challenges/{id}` | `social:read` |
| `POST` | `/api/v1/challenges/{id}/join` · `/leave` · `/join-by-code` | `health:write` |
| `GET` | `/api/v1/challenges/{id}/leaderboard` | `health:read` |
| `GET` `POST` | `/api/v1/challenges/{id}/feed` | `social:read` / `social:write` |
| `POST` | `/api/v1/challenges/{id}/feed/{postId}/react` · `/delete` | `social:write` |
| `POST` | `/api/v1/challenges/{id}/invite` · `/invite/decline` | `social:write` |
| `GET` `POST` | `/api/v1/challenges/{id}/flags` · `/flag` | `social:read` / `social:write` |

Joining a challenge is a `health:write` action because it **creates a sharing grant**: your scored metric becomes visible to that challenge's members for its duration. Leaving revokes it.

Leaderboards read from server-computed snapshots of the scored metric only — never raw logs. A percentage challenge stores the percentage, not the weight behind it.

`403 not_participant` on a leaderboard or feed means the key owner has not joined that challenge. It is not a scope problem.

### See also

- [mobieusCore API — Overview](/know/api-overview)
- [mobieusCore API — Authentication, scopes & rate limits](/know/api-authentication)
- [mobieusCore API — mobieusHealth](/know/api-health)