Researched 2026-10-16 against https://files.mega65.org. The Filehost has no documented public API. The endpoints below are the ones the site's own pages call. They may change without notice, so the client parses every response defensively and caches the last good copy.
Notation: verified means a live response was observed; inferred means it was read from site JavaScript or deduced.
- Base URL:
https://files.mega65.org/php/. Requests arePOSTwith a form-encoded body, as the site sends them. A plainGETalso works for the parameterless lists. - Content type: responses are JSON but labelled
Content-Type: text/html, withCache-Control: no-store. A freshPHPSESSIDcookie is set every time, but no session is needed for read access. - Response shapes are inconsistent. Some endpoints return arrays and others return objects with numeric keys plus a
statefield.state: "EMPTY"means not found, restricted, or no permission. - Field formats vary:
- dates appear as
2021/06/02,17 Jul 2022and2026-10-16 01:58:16; oshas a leading space;downloadsis space-padded;ratingmay benull,"","-"or"5.0 (2)".
- dates appear as
- No checksums are published. The app records size and SHA-256 itself in a
manifest.jsonnext to each download. - Terms:
robots.txtreturns 404, and the Terms of Use contain no clause on automated access. The app sends a descriptiveUser-Agent, caches the catalogue for 6 hours, and fetches details only when they are needed.
| Endpoint | Params | Use | Shape |
|---|---|---|---|
readfilespublic.php |
none | Main catalogue: 520 public files, latest version only | [{fileid, title, category, type, os, rating, downloads, search, published, sortdate, versionid, filename, size, location, author, …}] |
readfiledetail.php |
fileid (UUID or linkid) |
Detail pane | [{state:"OK", title, description, linkid, category, type, os, rating, ratingcount, downloads, pal, ntsc, versionid, filename, size, version, location, coretext, romtext, published, author}] or [{"state":"EMPTY"}] |
readversionlistpublic.php |
fileid |
Version history | [{fileid, version, versionid, filename, size, comment, published, active:"Y"/"N", location}], newest first |
| Endpoint | What it returns |
|---|---|
readgallerypublic.php |
Thumbnails |
readmedias.php |
Screenshots and videos, with objectid and origin=F |
readcomments.php |
Comments and ratings |
readpagesearch.php |
Search across all object types, with search |
readtopten.php |
Top-ten lists |
readcategorychart.php |
Category counts |
readarticledetail.php |
Articles |
readcontent.php |
Terms and privacy pages |
- Used:
login.phpandlogout.php(see Sign-in), plussavefileupload.phpandsavefileupdate.phpon the MEGA65 File Host Upload page (see My File Uploads below). - Never called:
request.php,redeem.php,saveupdatedownload.php,savecomment.php,savescore*.php,savemediaupload.php,savemedialink.php,savedeletemedia.php,savedeletefileversion.php,saveupdateversion.php,saveupdateview.php.
- URL: resolve
locationagainst/php/, so../files/m/x_AbC123.7zbecomeshttps://files.mega65.org/files/m/x_AbC123.7z. - Served statically by Apache, with
Content-Length,ETag,Last-ModifiedandAccept-Ranges: bytes. The client resumes partial downloads withRange. - No
Content-Dispositionheader, and the stored name has a random suffix. The file is saved under the API'sfilenameinstead.
readversionlistpublic.php without fileid returns 982 rows for only 325 files and omits the release packages. It is not suitable for release discovery. Always pass fileid.
- What counts as a stable core package:
author == "MEGA65"category == "Firmware"type == "Release Package"- the title contains "Release Package" and not "Development"
- Target board: taken from the parentheses in the title, e.g.
MEGA65 Core Release Package (mega65r6) no ROM. - The Filehost
versionfield is a per-file revision counter, not the MEGA65 release number. The release number is parsed from the package file name:mega65r6-release-0.97.2-03b24c6-norom.7zgives target, release, commit hash and a no-ROM flag;- legacy names look like
MEGA65-R3-Rel_0_9-norom.7z; - the version comment ("Release 0.97 …") is the fallback.
- The R6 package also contains the R5 (beta PCB) core. There is no public R4 package.
- Package layout (0.97.2, verified by extracting it):
<name>/sdcard-files/holds the SD-card files (FREEZER.M65 etc.);<name>/*.corand*.bitare the cores;beta-pcb/holds the R5 core;extra/HICKUP.M65andflasher/mflash.prgare not copied to the card.
| Package | fileid |
|---|---|
| Release package (mega65r3) no ROM | 8d295d12-4422-4dc4-9553-64bf424e860e |
| Release package (mega65r6) no ROM | 764642f7-83bc-4162-9911-99a0a6283d08 |
| mega65-tools Windows release | 06c55815-7826-4ad6-be0e-b8dc5e721b6d |
| mega65-tools Windows development | 658322fd-e586-4b4f-a991-89470b269b4a |
The release packages themselves are discovered dynamically. Only the two tools fileids are pinned.
- What is restricted: only the closed MEGA65 ROM, and packages that include it, need more than anonymous access (Filehost article "How to download closed ROM files").
- How you get access: a registered user redeems the paper ownership code shipped with the machine, once, on the website (
redeem.php). - How restriction shows in the data: restricted files are absent from
readfilespublic. Anonymously,readfiledetailreturnsEMPTYfor them. The public no-ROM package descriptions contain a "private link" (https://files.mega65.org?id=<fileid>) to the package with the ROM.
- Request:
POST login.phpwith form fieldslogindata[username]andlogindata[password]. This is jQuery's encoding of{"logindata": {...}}. - Required header:
X-Requested-With: XMLHttpRequest. Without it the server answers{"state":"NOTOK","message":"Invalid request"}before checking credentials (verified). The app sends it on every Filehost POST. - Response:
{"state":"OK"}, or{"state":"NOTOK","message":…}for bad credentials. - Session: held in the
PHPSESSIDcookie.logout.phpends it. - Expiry: session-aware endpoints may answer
RELOGIN,TIMEOUTorLOGINERROR. The app treats these as "signed out". - No API token or OAuth exists.
- You sign in with your own account, in the app's Filehost page. The password goes only to
files.mega65.orgover HTTPS, and is never logged.- By default only the user name is remembered.
- "Remember my password" stores it encrypted with Windows DPAPI, readable only by your Windows account on that PC.
- Signing out deletes the saved password.
- The server decides access. A non-public file ID is only queried when you are signed in, and the app only lists its versions after
readfiledetailreturnsOKfor your session.CatalogueServicethrows otherwise. - Owner-only metadata is never written to the disk cache. Downloaded packages are stored in your local download cache like any other download.
- Update My MEGA65 → "Include the closed ROM":
- Follows the private link from the public package.
- Uses the ROM package only if your account can see it.
- Otherwise falls back to the no-ROM package and says why.
- The redeem flow is not automated. Redeem your code on the website.
- Verified: sign-in works with a real account (2026-10-16).
- Verified (R6 0.97.2): the with-ROM package has the same layout as the no-ROM one plus
sdcard-files/MEGA65.ROM(128 KB). Its top folder ismega65r6-release-0.97.2-03b24c6, with no-noromsuffix. The app checks thatMEGA65.ROMis really present before reporting a with-ROM update. - Still to confirm: the API
filenameof the with-ROM version. The parser treats anything other than-noromas including the ROM. The parser accepts…-<hash>.7zor any suffix other than-norom.
Read 2026-10-18 from the website's upload page (html/fileupload.php). The read endpoints were checked live with a real account; the two write endpoints have not yet been called against the live site.
| Endpoint | Method and params | Answer |
|---|---|---|
readfilelist.php |
GET | [{id, title}]: your own uploads (verified) |
readfile.php |
POST fileid |
{"0": {id, title, description, searchtags, shortlink, filetypeid, ntsc, pal, osmega65, osc65, osc64, osvixen, oswindows, osmac, oslinux, osonline, introdisk, highscore, groupname, coreversionid, romversionid, locked}, "state": "OK"} (verified) |
readversionlist.php |
POST fileid |
[{version, versionid, filename, size, comment, uploaded, active, checked, location}], inactive versions included (verified) |
readfiletypes.php |
GET | [{id, name, extension, filecategory}], e.g. 58 = Core (verified) |
readcoreversionsupload.php |
POST | [{core, versionid, versiontext}] (verified) |
readromversions.php |
POST | [{state, versionid, versiontext}] (verified) |
savefileupload.php |
POST multipart: file in field fileupload, plus the fields below |
{state: "OK", message, fileid}, or EXIST/ERROR with a message |
savefileupdate.php |
POST form: fileid plus the attribute fields |
{state: "OK", message} |
- Attribute fields:
title,type(file type id),description,searchtags,shortlink,ntsc,pal,osmega65,osc65,osc64,osvixen,oswindows,osmac,oslinux,osonline,introdisk,highscore,grouppublic,groupmega65,groupadmin,groupowner,coreversionid,romversionid. Flags areY/N; exactly one group isY. The DevKit button posts asgroupmega65;readfilereports it asgroupname: "devkit". - Escaping, as the page does it: backslashes are doubled in title, description, search tags and comment;
&,<and>are HTML-escaped in title and search tags.readfilereturns the title HTML-escaped, so it is unescaped before editing. - Upload-only fields:
fileid(-1for a new file),comment,version(1 to 9999.9, one decimal),mode(initfor a new file,newto add a version,replaceto delete the latest version and put the upload in its place). A new version becomes the active one. - The upload sends all attributes too, so MEGA65 GUI reads them with
readfilefirst and sends them back, so an upload never resets them. - Rules copied from the page: at most 200 MB; extensions doc, docx, xls, xlsx, txt, zip, rar, tar, 7z, dmg, pdf, iso, m65, d81, d64, prg, asm, bas, lst, c65, cor, rom, bin, mcs, bit, hic, sid, mod, osx, exe, rdf, bdf, cfg, tcr, chr or none; a title, a type and at least one platform are required; a short link is letters, digits and
-. Highscore is offered only for Game types, and a ROM version only for MEGA65 cores. - Not done in the app: previews (
savemediaupload.php), deleting files or versions, and choosing the active version. Use the website for those.
A file on the MEGA65 File Host Upload page can be linked to a GitHub repository (stored in upload-links.json). Sync reads the newest non-draft release from the public GitHub API, picks the release file by a pattern such as MegaST-*.zip, and uploads it as a new version unless that tag or that file name is already on the Filehost. The version comes from the tag (v1.2 becomes 1.2); tags that do not fit nnnn.n get the next free version. The app asks before every upload, also when the check runs at start-up.
- Would the Filehost operators welcome a desktop client? Should it call
saveupdatedownload.phpso download counts stay accurate? (Not called today; worth asking the operators.) - Do signed-in sessions return additional rows from
readfilespublic? - Which endpoints back the Projects and Compatibility index pages?