Firmware API
Basics
| Base URL | https://openfc.dev/api/v1 |
| Auth | None. Public and read-only. |
| Format | JSON. Every response includes api_version and generated_at. |
| CORS | Enabled for all origins. |
| Rate limits | None. Static files behind a CDN. |
The API is regenerated from the firmware manifest on every deploy, and the build fails if a published hash disagrees with the binary actually being served. A response can therefore never advertise a hash for a file that is not the file you would download.
api_version only changes on a breaking change. New fields may be added within v1, so parse leniently and ignore unknown keys.
Endpoints
| Endpoint | Returns |
|---|---|
GET /api/v1/index.json | Service description and the endpoint list. |
GET /api/v1/firmware/latest.json | The newest competition-certified release. |
GET /api/v1/firmware/releases.json | Every published release, newest first. |
GET /api/v1/firmware/hashes.json | SHA-256 → release lookup, for verifying a connected board. |
Latest certified firmware
Answers “what should this board be running?” latest is null if nothing is currently certified.
{
"api_version": "v1",
"generated_at": "2026-07-31T01:39:53.093Z",
"latest": {
"version": "1.3.0",
"released": "2026-07-31",
"description": "Adds get_info and closes the raw-diagnostics watchdog gap",
"changelog": "...",
"binary_sha256": "0403cd4246c29d8e524b9f0cbe9300ea3fb399366996a1a8f8b61efd071b8887",
"app_sha256": "0217fc0dbc1acb26c4e7ae9edbd3833a87ff8e530a83655e0d52db4a006fa3f7",
"download_url": "https://openfc.dev/firmware/openfc-v1.3.0-merged.bin",
"certified_for_competition": true,
"min_hw_version": "1.1"
}
}Two hashes, and which one to use
Each release publishes two SHA-256 values. Using the wrong one is the most common integration mistake, because both are valid hashes of “the firmware” — of different things.
| Field | Hash of | Compare against |
|---|---|---|
app_sha256 | The application partition image | The fw_hash a connected board reports in hello. |
binary_sha256 | The merged .bin file you download | A file on disk, before flashing it. |
app_sha256. To verify a downloaded file, use binary_sha256. The lookup table below accepts either and tells you which one matched.Verifying a board for competition
The board computes the SHA-256 of its own running application partition at boot and reports it as fw_hash. That is a hash of the code actually executing, not a version string a modified build could simply claim — so it is meaningful evidence rather than a self-declaration.
Three steps:
- Send
{"cmd":"get_info"}and readfw_hashfrom thehelloreply. - Fetch
/api/v1/firmware/hashes.json. - Look up the hash. It is competition-legal only when the entry exists and
certified_for_competitionistrue.
{
"api_version": "v1",
"generated_at": "2026-07-31T01:39:53.093Z",
"hashes": {
"0217fc0dbc1acb26c4e7ae9edbd3833a87ff8e530a83655e0d52db4a006fa3f7": {
"version": "1.3.0", "certified_for_competition": true, "kind": "app"
},
"0403cd4246c29d8e524b9f0cbe9300ea3fb399366996a1a8f8b61efd071b8887": {
"version": "1.3.0", "certified_for_competition": true, "kind": "binary"
}
}
}const hashes = await fetch(
'https://openfc.dev/api/v1/firmware/hashes.json'
).then((r) => r.json());
const entry = hashes.hashes[fwHash.toLowerCase()];
if (!entry) console.log('FAIL — unknown firmware');
else if (!entry.certified_for_competition) console.log('FAIL — uncertified build');
else console.log('PASS —', entry.version);TypeScript client
This site's own client is importable if you are working in TypeScript. It wraps the same endpoints and returns a single verdict.
import { verifyFirmware } from '@/lib/openfc-api';
const verdict = await verifyFirmware(fwHash, 'https://openfc.dev');
verdict.certified // legal for competition
verdict.recognised // a published build, certified or not
verdict.version // "1.3.0"
verdict.outdated // a newer certified release exists
verdict.latestVersion // "1.3.0"verdictFor() is the same logic as a pure function, if you want to cache the index and check many boards offline.
Checking for updates
const { latest } = await fetch(
'https://openfc.dev/api/v1/firmware/latest.json'
).then((r) => r.json());
if (latest && fwHash.toLowerCase() !== latest.app_sha256) {
console.log('Update available:', latest.version, '→', latest.download_url);
}Compare hashes rather than version strings: the hash distinguishes a genuine release from a local build that reports the same version number.
Stability
Endpoint paths and existing field names within v1 will not change or be removed. A published release is never edited or deleted — if a build is withdrawn, certified_for_competition flips to false and the entry stays, so an old hash always resolves to a truthful answer rather than disappearing.