---
title: Challenge results API
description: Build challenge leaderboards, heatmaps, participant details, and activity analytics
order: 6
---

# Challenge results API

Whitelabel portals and other supported integrations can build a challenge results experience with the endpoints below. They all use the challenge code and require an authenticated API request.

```
/api/v1/gamification/challenge/{code}/
```

::: warning Integration access
API credentials, supported authentication flows, and rate limits are arranged with DistantRace support. Treat a `404` from a result or analytics endpoint as unavailable to the current caller; the same response is used when privacy settings hide the resource.
:::

## Endpoint sequence

| Endpoint | Use |
|----------|-----|
| `GET result-settings/` | Discover result columns, sorting, totals, sections, distances, and which optional views are available |
| `GET heatmap/` | Load aggregate workout-density cells when `show_heatmap` is enabled |
| `GET results/{challenger_id}/detailed/` | Load one participant's result, aggregate statistics, comparisons, and activity timeline |
| `GET results/{challenger_id}/activities/{activity_id}/analytics/` | Load splits, charts, and permitted sensor analytics for one accepted activity |

Start with `result-settings/`. Use its flags and column descriptors to decide which controls and screens to render instead of assuming every challenge has the same result format.

Get `challenger_id` values from the challenge's paginated `results/` leaderboard. Activity IDs come from the nested `activities.results` list in the detailed response.

## Result settings

`GET /api/v1/gamification/challenge/{code}/result-settings/`

The response describes the current challenge result presentation:

- `primary_column` and `ordered_by` identify the ranking metric and default order.
- `columns` and `team_columns` are ordered rendering descriptors; their keys map to fields in participant and team leaderboard rows.
- `totals`, `progress`, `sections`, `distances`, and `participant_data` provide optional challenge-wide context.
- `show_map` and `show_heatmap` tell the client which map views to offer. `show_analytics` says whether this caller may see another participant's physiological activity data; it does not restrict the caller's own reachable analytics.
- `results_limited` is `null` for unrestricted results. A number means that the caller can see only that many top rows, and result filtering, ordering, and pagination controls should be hidden.

These values are caller-aware. For example, the same challenge can return unrestricted settings to a participant and limited settings to a signed-in non-participant.

## Workout heatmap

`GET /api/v1/gamification/challenge/{code}/heatmap/`

The heatmap aggregates accepted GPS activities into approximately 150-metre grid cells. Each cell is `[longitude, latitude, weight]`, where the weight is the number of distinct activities that passed through it. An activity contributes at most once to each cell, and workouts marked private in their source app are excluded.

Heatmaps are generated lazily. When no stored heatmap exists, the first request starts background generation and returns:

```json
{"status": "pending"}
```

Poll again after a few seconds. A ready response contains `generated_at`, `cell_size`, `activity_count`, `max_weight`, `truncated`, and `cells`. Stored data can be served while a stale heatmap is refreshed in the background.

Use `max_weight` to normalize a weighted density layer. If `truncated` is `true`, the response contains the heaviest cells rather than every generated cell.

The endpoint returns `404` when the organizer has not enabled `show_heatmap`, during a hidden-results window, or when public results are restricted and the caller is not a participant.

## Detailed participant result

`GET /api/v1/gamification/challenge/{code}/results/{challenger_id}/detailed/`

The response combines:

- The participant's leaderboard row, chosen distance, rank, and `result_rank_total`.
- `statistics` such as distance, duration, pace or speed, energy, steps, activity count, active days, longest streak, and average heart rate when available.
- `is_own_result`, which identifies whether the row belongs to the authenticated participant.
- `head_to_head`, available only when a participant views their own result. It includes rank and percentile, the ranking metric, gaps to nearby competitors and the leader, the field average, and podium rows.
- `activities`, a nested paginated list of accepted, visible activities credited to the result. Each row includes basic workout metadata, average pace, a route shape when available, and `has_analytics`.

For a fixed-distance result, the activity list stops at the activity that completed the selected distance. Later activities do not appear because they did not contribute to that result.

### Nested activity pagination

The activity list has the usual `count`, `next`, `previous`, and `results` fields, but uses dedicated query parameters so it does not conflict with top-level pagination:

| Parameter | Meaning |
|-----------|---------|
| `activities_page` | Page number, starting at 1 |
| `activities_per_page` | Items per page; default 25 and subject to the API maximum |

### Location-free route shapes

Activity timeline routes are not geographic coordinates. The server translates and scales each GPS track into a fixed `158 × 108` SVG coordinate space and returns only:

- `path` — SVG path data
- `start` and `end` — points in the normalized coordinate space
- `point_count` — number of points in the returned shape

Absolute latitude, longitude, bounds, and center are not included. The same route translated to another location produces the same shape, so it is suitable for a thumbnail but cannot be plotted on a geographic map.

## Per-activity analytics

`GET /api/v1/gamification/challenge/{code}/results/{challenger_id}/activities/{activity_id}/analytics/`

The activity must be accepted, visible, and attached to that exact participant result. The response contains basic distance, duration, pace, and speed plus any analytics that can be derived from the stored streams:

| Block | Contents |
|-------|----------|
| `route` | The same location-free route shape used in the activity timeline |
| `km_splits` | Full kilometre splits plus an optional final partial split, including fastest and slowest markers |
| `elevation` | Downsampled profile, ascent, descent, minimum, and maximum |
| `heart_rate` and `hr_zones` | Downsampled heart-rate series, average, maximum, reference maximum, and time in five zones |
| `cadence` | Downsampled cadence series and average |
| `effort_score` | Heart-rate-derived effort estimate |

Blocks are independently nullable because providers and devices supply different streams. `has_streams` reports whether usable stream analytics exist. `x_kind` identifies whether chart x-values represent cumulative distance or elapsed time.

Low-sensitivity blocks—route shape, splits, pace, and elevation—are available to any caller who can reach the result. Physiological blocks—heart rate, zones, cadence, and effort—are always available for the caller's own reachable result. For another participant's activity, they are returned only when the organizer enabled `show_analytics` and the caller passes the result visibility rules. Otherwise those blocks are `null` and `physio_restricted` is `true`.

## Visibility and privacy rules

| Setting or state | Effect |
|------------------|--------|
| `show_heatmap` off | Heatmap returns `404`; `result-settings` reports `show_heatmap: false` |
| `show_analytics` off | Other participants' physiological activity blocks are removed; own reachable analytics are unaffected |
| Hidden-results window active | Participant result drill-downs are hidden; heatmap returns `404`; `show_heatmap` and `show_analytics` are false |
| `hide_results_public` on | Signed-in non-participants are limited to the configured top results, cannot load the heatmap, and cannot view other participants' physiological analytics |
| Workout not accepted or not visible | It is omitted from the timeline and cannot be opened through the analytics endpoint |

Challenge participants retain access to full results outside a hidden-results window. Organization staff access can differ from participant access, but clients should still follow the caller-specific values returned by `result-settings/`.

## Related

- [Public API overview](public-api-overview.md)
- [Whitelabel and enterprise setup](../running-events/whitelabel-and-enterprise-setup.md)
