Forts Tools

Which version is this replay?

Forts replays only play back correctly on the build they were recorded on. Upload a replay to find out which release that is.

Maximum file size 300 MB.

API reference

Identify a Forts replay from its own header. Server-to-server; the browser-facing surface is the form above.

EndpointPOST https://forts-tools.com/api/version
Request bodymultipart/form-data
Response bodyapplication/json
AuthenticationNone. No key, no origin allow-list.
Browser accessNo CORS headers are sent. fetch() from a page is blocked by the browser before the body is readable. Call this endpoint server-side.

Parameters

NameInTypeRequiredNotes
replaymultipart bodyfilerequiredOne Forts .fwr recording.

Example request

curl -X POST -F "replay=@your-replay.fwr" \
     https://forts-tools.com/api/version

Response

Field names, type names and token values are fixed. They are not translated.

Every field has one type or null. null means the file did not record the value: never words standing in for a value, never 0 for a figure that was never written. An empty array means the file records none, not that the value is missing.

schema is forts-version/2. It changes only on a breaking change; a new field never changes it. Any other value is outside this contract.

FieldTypeDescription
okbooleantrue on success, false on failure.
schemastringContract version. Currently forts-version/2.
releaseobjectThe release the recording reports. Fields below.
map_namestring | nullMap name as the recording carries it.
durationstring | nullMatch length, mm:ss.
duration_secnumber | nullMatch length in seconds, two decimals.
playersobject[]One object per player. Fields below.
commandersobject[]One object per commander. Fields below.
modsstring[]Add-on names the recording carries. Empty when it carries none.
winnerstring | null"left" or "right".
release
build_idstringIdentifier for this release in the build table.
versionstringRelease number, e.g. 1.38.2.
revisionstring | nullRevision, e.g. r22447.
releasedstring | nullRelease date, YYYY-MM-DD.
labelstringDisplay label. English on every locale.
exactbooleanfalse means the era number in the recording covers several releases; the one named above is the newest it could be, not certainly the one it was recorded on.
is_currentbooleanWhether this is the release the game currently ships.
players[]
namestring | nullPlayer name as the recording carries it. Not redacted.
sidestring | null"left" or "right". Fixed tokens, not display text.
steam_idstring | nullSteam account id as the recording carries it.
commanders[]
namestring | nullCommander name as the recording carries it. Not translated.
sidestring | null"left" or "right". Fixed tokens, not display text.

Limits

LimitValueNotes
File size4096 B – 300 MB
File parts1Sent as replay. If more than one is sent, the last is read.
Requests per minute, per caller6Shared with the upload form on this page. Over it: 429.
RetentionnoneThe upload is deleted as soon as identification finishes. No file is produced and nothing expires.

Errors

Every failure returns {"ok": false, "error": "…"} with one of the status codes below. error is a human-readable message in the language negotiated from Accept-Language. Branch on the status code, not on the message text.

StatusMeaning
200Success.
400Missing file part, file below the minimum size, unreadable file, or an invalid parameter value.
405Method other than POST.
413Body above the maximum size.
422File read but not usable: unsupported game version, or nothing decodable.
429Rate limit exceeded. Back off; do not retry immediately.
500Internal error.
503Busy, timed out, or the endpoint is disabled.

Everything else in the file

The table above is what this page and POST /api/version answer with. For everything the recording says about itself — its map assets, its add-ons, per-side detail, whether it reaches the end of the match — POST /api/replay returns the whole decode as JSON.

EndpointPOST https://forts-tools.com/api/replay
Request bodymultipart/form-data
Response bodyapplication/json
AuthenticationNone. No key, no origin allow-list.
Browser accessNo CORS headers are sent. fetch() from a page is blocked by the browser before the body is readable. Call this endpoint server-side.

Example request

curl -X POST -F "replay=@your-replay.fwr" \
     https://forts-tools.com/api/replay

Response

schema is forts-replay/1. It changes only on a breaking change; a new field never changes it. Any other value is outside this contract.

Limits

LimitValueNotes
File size4096 B - 64 MBLower than the form's own ceiling above. One branch of the read costs far more on a recording that stops before the match does, and this ceiling is where even that branch finishes inside the job limit.

The full field-by-field reference is on the Workbench page.