MENU navbar-image

Introduction

Read-only, server-to-server access to upcoming Southern African running events.

The RunningCalendar API is a versioned, read-only HTTP API for trusted third-party applications. It exposes upcoming, publicly-visible running events so you can show calendar data and link users back to runningcalendar.co.za.

Authenticating requests

To authenticate requests, include an Authorization header with the value "Bearer rc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".

All authenticated endpoints are marked with a requires authentication badge in the documentation below.

Send your key as a bearer token: Authorization: Bearer rclive.... Keys are issued by the RunningCalendar team and are secret — keep them server-side. A disabled or revoked key returns 403; an unknown or missing key returns 401.

Events

List upcoming events

requires authentication

Returns a paginated list of upcoming, publicly-visible event editions, ordered by date ascending. Mirrors the public website's visibility exactly. Every item carries links to its page on the website: url for your website and app_url for your app, both tagged so the visits are credited to your key, and an untagged canonical_url for matching.

When updated_since is provided the endpoint switches to sync mode: it returns every edition whose updated_at >= updated_since, regardless of visibility, so a consumer can replay all changes since its last poll. Each item carries a sync_status field — "active" means the edition is currently live on the calendar; "removed" means it was changed but is no longer publicly visible (draft, cancelled, or past). A removed item carries only id, slug, sync_status, and updated_at — never full event data — to avoid leaking non-public content. Browse filters (country, province, city, distance) are ignored in sync mode; only updated_since and pagination apply.

Known sync limitations:

Example request:
curl --request GET \
    --get "https://api.runningcalendar.co.za/v1/events?from=2026-07-01&to=2026-12-31&country=ZA&province=gauteng&city=cape-town&distance=10km%2Chalf-marathon&updated_since=2026-06-01T00%3A00%3A00Z&per_page=25&page=1" \
    --header "Authorization: Bearer rc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"from\": \"2026-10-22T07:13:49\",
    \"to\": \"2052-11-14\",
    \"updated_since\": \"2026-10-22T07:13:49\",
    \"country\": \"ng\",
    \"province\": \"z\",
    \"city\": \"m\",
    \"distance\": \"architecto\",
    \"per_page\": 22
}"
const url = new URL(
    "https://api.runningcalendar.co.za/v1/events"
);

const params = {
    "from": "2026-07-01",
    "to": "2026-12-31",
    "country": "ZA",
    "province": "gauteng",
    "city": "cape-town",
    "distance": "10km,half-marathon",
    "updated_since": "2026-06-01T00:00:00Z",
    "per_page": "25",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer rc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "from": "2026-10-22T07:13:49",
    "to": "2052-11-14",
    "updated_since": "2026-10-22T07:13:49",
    "country": "ng",
    "province": "z",
    "city": "m",
    "distance": "architecto",
    "per_page": 22
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200, Success):


{
    "data": [
        {
            "id": 1,
            "name": "Cape Town Marathon",
            "slug": "cape-town-marathon",
            "date": "2026-10-18",
            "end_date": null,
            "summary": "The 2026 Cape Town Marathon takes place on Sunday, 18 October 2026, at Green Point, Cape Town. It is a single 42.2km road race. Online entries are open.",
            "organiser": {
                "name": "Cape Town Marathon NPC",
                "url": "https://runningcalendar.co.za/organisers/cape-town-marathon-npc?utm_source=example&utm_medium=referral&utm_campaign=events_api",
                "app_url": "https://runningcalendar.co.za/organisers/cape-town-marathon-npc?utm_source=example&utm_medium=app&utm_campaign=events_api"
            },
            "races": [
                {
                    "name": "42.2km",
                    "distance_metres": 42195,
                    "distance_label": "Marathon",
                    "race_type": "road",
                    "start_time": "06:00",
                    "race_fee_from": 250,
                    "race_fee_currency": "ZAR"
                }
            ],
            "venue": {
                "town": "Cape Town",
                "province": "Western Cape",
                "country_iso2": "ZA",
                "lat": -33.9249,
                "lng": 18.4241
            },
            "image_url": "https://media.runningcalendar.co.za/7441/cape-town-marathon-logo.png",
            "verification_status": "verified",
            "url": "https://runningcalendar.co.za/events/cape-town-marathon/2026?utm_source=example&utm_medium=referral&utm_campaign=events_api",
            "app_url": "https://runningcalendar.co.za/events/cape-town-marathon/2026?utm_source=example&utm_medium=app&utm_campaign=events_api",
            "canonical_url": "https://runningcalendar.co.za/events/cape-town-marathon/2026"
        }
    ],
    "links": {
        "first": "...",
        "last": "...",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "per_page": 25,
        "total": 1,
        "source": "RunningCalendar",
        "docs_url": "https://api.runningcalendar.co.za/docs"
    }
}
 

Example response (200, Sync mode (updated_since)):


{
    "data": [
        {
            "id": 1,
            "name": "Cape Town Marathon",
            "slug": "cape-town-marathon",
            "date": "2026-10-18",
            "end_date": null,
            "summary": "The 2026 Cape Town Marathon takes place on Sunday, 18 October 2026, at Green Point, Cape Town. It is a single 42.2km road race. Online entries are open.",
            "organiser": {
                "name": "Cape Town Marathon NPC",
                "url": "https://runningcalendar.co.za/organisers/cape-town-marathon-npc?utm_source=example&utm_medium=referral&utm_campaign=events_api",
                "app_url": "https://runningcalendar.co.za/organisers/cape-town-marathon-npc?utm_source=example&utm_medium=app&utm_campaign=events_api"
            },
            "races": [
                {
                    "name": "42.2km",
                    "distance_metres": 42195,
                    "distance_label": "Marathon",
                    "race_type": "road",
                    "start_time": "06:00",
                    "race_fee_from": null,
                    "race_fee_currency": null
                }
            ],
            "venue": {
                "town": "Cape Town",
                "province": "Western Cape",
                "country_iso2": "ZA",
                "lat": -33.9249,
                "lng": 18.4241
            },
            "image_url": "https://media.runningcalendar.co.za/7441/cape-town-marathon-logo.png",
            "verification_status": "verified",
            "url": "https://runningcalendar.co.za/events/cape-town-marathon/2026?utm_source=example&utm_medium=referral&utm_campaign=events_api",
            "app_url": "https://runningcalendar.co.za/events/cape-town-marathon/2026?utm_source=example&utm_medium=app&utm_campaign=events_api",
            "canonical_url": "https://runningcalendar.co.za/events/cape-town-marathon/2026",
            "sync_status": "active",
            "updated_at": "2026-06-01T08:00:00Z"
        },
        {
            "id": 2,
            "slug": "old-cancelled-race",
            "sync_status": "removed",
            "updated_at": "2026-06-01T09:00:00Z"
        }
    ],
    "links": {
        "first": "...",
        "last": "...",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "per_page": 25,
        "total": 2,
        "source": "RunningCalendar",
        "docs_url": "https://api.runningcalendar.co.za/docs"
    }
}
 

Example response (401, Missing or invalid key):


{
    "error": {
        "code": "unauthenticated",
        "message": "Invalid API key."
    }
}
 

Example response (429, Rate limited):


{
    "error": {
        "code": "rate_limited",
        "message": "Too many requests."
    }
}
 

Request   

GET v1/events

Headers

Authorization        

Example: Bearer rc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

from   string  optional    

ISO date — lower bound on the event date. Defaults to today. Ignored in sync mode. Example: 2026-07-01

to   string  optional    

ISO date — inclusive upper bound on the event date. Must be >= from. Ignored in sync mode. Example: 2026-12-31

country   string  optional    

ISO2 country code. Defaults to all active Southern-African countries. Ignored in sync mode. Example: ZA

province   string  optional    

Province slug. Ignored in sync mode. Example: gauteng

city   string  optional    

Town/city slug. Ignored in sync mode. Example: cape-town

distance   string  optional    

One or more distance band slugs, comma-separated. One of: ultra, marathon, 30km, half-marathon, 15km, 10km, 5km. Ignored in sync mode. Example: 10km,half-marathon

updated_since   string  optional    

ISO datetime — enables sync mode. Returns all editions changed at or after this timestamp. Example: 2026-06-01T00:00:00Z

per_page   integer  optional    

Page size, 1–100 (hard-capped at 100). Defaults to 25. Example: 25

page   integer  optional    

Page number. Example: 1

Body Parameters

from   string  optional    

Must be a valid date. Example: 2026-10-22T07:13:49

to   string  optional    

Must be a valid date. Must be a date after or equal to from. Example: 2052-11-14

updated_since   string  optional    

Must be a valid date. Example: 2026-10-22T07:13:49

country   string  optional    

Must contain only letters. Must be 2 characters. Example: ng

province   string  optional    

Must not be greater than 120 characters. Example: z

city   string  optional    

Must not be greater than 120 characters. Example: m

distance   string  optional    

Example: architecto

per_page   integer  optional    

Must be at least 1. Example: 22

Response

Response Fields

data   object     
summary   string|null     

A short, generated plain-text summary of the event (where, which distances, entry status). null when there is nothing to say.

organiser   object|null     

Who organises the event, or null when unknown. url / app_url link to the organiser's page on RunningCalendar (tagged like the event links) and are null when there is no public page.

image_url   string|null     

The event's logo, sized for listings (at most 600×600), or null when the event has no logo. Load it from this URL: don't copy it, so updates reach your site.

url   string     

Link to this event's page for use on your website. It carries tracking parameters that identify your key: use it exactly as returned, and don't add, change or strip parameters.

app_url   string     

The same page, tagged for links opened from a mobile app. Use it instead of url inside an app.

canonical_url   string     

The event page with no parameters. It never changes for an edition: use it (or id) to match and deduplicate events, not as a link.

races   object     
race_fee_from   number|null     

The senior entry fee ("Entry Fee") for the race. 0 means free entry; null means no senior fee is listed. Junior, early-bird, 60+ and licence fees are never used.

race_fee_currency   string|null     

ISO 4217 currency code of race_fee_from, e.g. ZAR. null whenever race_fee_from is null.

Fetch a single event

requires authentication

Looks up one event edition by numeric id or by event slug. Applies the exact same visibility scope as the list — a draft, unpublished, hidden, or past edition returns 404 (never a leak). The payload uses the same basic fields as a list item.

Example request:
curl --request GET \
    --get "https://api.runningcalendar.co.za/v1/events/cape-town-marathon" \
    --header "Authorization: Bearer rc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://api.runningcalendar.co.za/v1/events/cape-town-marathon"
);

const headers = {
    "Authorization": "Bearer rc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200, Found):


{
    "data": {
        "id": 1,
        "name": "Cape Town Marathon",
        "slug": "cape-town-marathon",
        "date": "2026-10-18",
        "end_date": null,
        "summary": "The 2026 Cape Town Marathon takes place on Sunday, 18 October 2026, at Green Point, Cape Town. It is a single 42.2km road race. Online entries are open.",
        "organiser": {
            "name": "Cape Town Marathon NPC",
            "url": "https://runningcalendar.co.za/organisers/cape-town-marathon-npc?utm_source=example&utm_medium=referral&utm_campaign=events_api",
            "app_url": "https://runningcalendar.co.za/organisers/cape-town-marathon-npc?utm_source=example&utm_medium=app&utm_campaign=events_api"
        },
        "races": [
            {
                "name": "42.2km",
                "distance_metres": 42195,
                "distance_label": "Marathon",
                "race_type": "road",
                "start_time": "06:00",
                "race_fee_from": 250,
                "race_fee_currency": "ZAR"
            }
        ],
        "venue": {
            "town": "Cape Town",
            "province": "Western Cape",
            "country_iso2": "ZA",
            "lat": -33.9249,
            "lng": 18.4241
        },
        "image_url": "https://media.runningcalendar.co.za/7441/cape-town-marathon-logo.png",
        "verification_status": "verified",
        "url": "https://runningcalendar.co.za/events/cape-town-marathon/2026?utm_source=example&utm_medium=referral&utm_campaign=events_api",
        "app_url": "https://runningcalendar.co.za/events/cape-town-marathon/2026?utm_source=example&utm_medium=app&utm_campaign=events_api",
        "canonical_url": "https://runningcalendar.co.za/events/cape-town-marathon/2026"
    }
}
 

Example response (404, Not found / not visible):


{
    "error": {
        "code": "not_found",
        "message": "Resource not found."
    }
}
 

Request   

GET v1/events/{idOrSlug}

Headers

Authorization        

Example: Bearer rc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

idOrSlug   string     

The numeric edition id or the event slug. Example: cape-town-marathon

Response

Response Fields

data   object     
summary   string|null     

A short, generated plain-text summary of the event (where, which distances, entry status). null when there is nothing to say.

organiser   object|null     

Who organises the event, or null when unknown. url / app_url link to the organiser's page on RunningCalendar (tagged like the event links) and are null when there is no public page.

image_url   string|null     

The event's logo, sized for listings (at most 600×600), or null when the event has no logo. Load it from this URL: don't copy it, so updates reach your site.

url   string     

Link to this event's page for use on your website. It carries tracking parameters that identify your key: use it exactly as returned, and don't add, change or strip parameters.

app_url   string     

The same page, tagged for links opened from a mobile app. Use it instead of url inside an app.

canonical_url   string     

The event page with no parameters. It never changes for an edition: use it (or id) to match and deduplicate events, not as a link.

races   object     
race_fee_from   number|null     

The senior entry fee ("Entry Fee") for the race. 0 means free entry; null means no senior fee is listed. Junior, early-bird, 60+ and licence fees are never used.

race_fee_currency   string|null     

ISO 4217 currency code of race_fee_from, e.g. ZAR. null whenever race_fee_from is null.