Event Intelligence
Turn a GPX course into terrain, decisive climbs and course demands through one MovePacket API. Event Intelligence is an authorised beta: call it from your application once MovePacket has enabled it for your workspace.
What you get#
- Distance, ascent, descent and an elevation profile.
- Terrain mix and decisive climbs, including their position, gradient and score.
- Course demands and critical sections for a dashboard, event brief or AI conversation.
- A private, versioned JSON result and a record of successful analyses and attempts.
Analysis runs inside MovePacket using a pinned extraction of the SEMIPRO route engine and demand scoring. It does not call or modify SEMIPRO.coach. This version uses the route's supplied elevation; weather, road-surface enrichment and athlete-specific demand matching are not included.
Analyse a course#
Use your provisioned workspace key from your server. Keys identify an owner; this release does not add multi-project memberships or role-specific keys.
import {readFile} from 'node:fs/promises';
import {randomUUID} from 'node:crypto';
// Keep this key stable if you retry this exact request after a network interruption.
const attemptKey = randomUUID();
const response = await fetch('https://movepacket.com/v1/event-analyses', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MOVEPACKET_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': attemptKey
},
body: JSON.stringify({
gpx_xml: await readFile('./course.gpx', 'utf8'),
event: {name: 'My event', type: 'road_race', course_format: 'point_to_point'}
})
});
const result = await response.json();
if (!response.ok) throw new Error(result.error);
console.log(result.id, result.status, result.analysis?.route);
201 returns a newly completed analysis. 200 returns an existing attempt. 202 means another request for the same attempt is still processing; retrieve its links.self until it reaches ready or failed. Do not assume every successful HTTP response contains a successful analysis.
Requests accept one continuous GPX track segment or route, maximum 3 MiB / 50,000 points, with valid coordinates and elevation at every point. Courses must be over zero and at most 3,000 km. XML entities and document declarations are rejected. Multiple disconnected segments are rejected rather than silently joined. Lap count is descriptive metadata: distances describe the supplied file once.
Optional event fields: name (160 characters), type, date (YYYY-MM-DD), course_format (point_to_point, loop, laps), course_laps (1–100). Event types are road_race, criterium, time_trial, gran_fondo, sportive, gravel, mtb, mtb_xc, ultra, stage, triathlon_bike_leg and other.
Results and usage#
| Endpoint | Purpose |
|---|---|
POST /v1/event-analyses |
Analyse a course and save its result |
GET /v1/event-analyses |
List the latest 20 attempts; use offset for older pages |
GET /v1/event-analyses/{id} |
Retrieve status and the private result |
DELETE /v1/event-analyses/{id} |
Remove the saved result and event name |
GET /v1/event-analyses/usage |
Current UTC month's attempts, successes, failures, pending attempts and daily allowance |
The envelope contains id, name, status, created_at, completed_at, error_code, links.self, and, on a detail response, analysis. The analysis has contract version movepacket_event_intelligence_v1, its own analysis_version, route, judgement, decisive climbs, critical segments, course sections, evidence and uncertainty. wind and public_url are null in this version.
Billing is off. Usage is not an invoice. measured_cost: null means running cost has not been measured; it is not a zero-cost claim. There are no external weather, AI or SEMIPRO API calls in this route-only version. Cloudflare processing and database storage still use infrastructure resources.
Retries and limits#
Each workspace can start 100 attempts per UTC day, within a shared 1,000-attempt daily service ceiling. Invalid uploads rejected before analysis do not consume an attempt. Failures after admission do consume an attempt but do not increment successful usage. Deleting a result does not refund usage. Limits use a single database admission statement to handle simultaneous requests.
An Idempotency-Key must contain 8–128 letters, digits, underscores or hyphens. Reusing it with the same course, event and contract returns the same attempt without additional usage. Reusing it with different input returns 409 idempotency_conflict. If omitted, the normalized points, event and contract determine a duplicate key. Timestamps and other GPX metadata do not affect analysis or deduplication.
After a terminal failure, start a new attempt with a new key. Requests left processing for more than five minutes are marked interrupted when that owner's API is next accessed. The original GPX is not stored for automatic recovery. A deleted attempt returns 410; supply a new key to analyse it again.
Data handling#
Results are private to the authenticated owner. There is no public result URL, and no raw GPX is retained. Derived results include course characteristics and an elevation profile, not the original GPS coordinate track. Use only files you have permission to process.
Delete removes the result and event name from the live database. Minimal attempt metadata remains for usage and idempotency: owner, ID, timestamps, status, success flag and owner-salted input/key digests. Deletion is not a purge of backups, previously downloaded copies or the whole workspace. No automated result expiry is enabled in this version.
Demo and evidence#
The demo course is synthetic and is not a navigable route. Automated checks compare its metrics, demand judgements, climb scores and critical sections against SEMIPRO's recorded public demo output. This verifies extraction parity on that fixture; it does not establish accuracy for every route or substitute for course reconnaissance.