Naar de inhoud
AI and API

Using fivemad with an AI assistant

Read our docs as Markdown, pull our JSON datasets, look up a joaat hash and call our calculators from ChatGPT, Claude, Cursor or your own script.

Deze docs zijn voorlopig in het Engels.

Last updated

Everything on fivemad is public and free, including for a machine. You do not need a key, an account or a contract. This page is the whole story in one place: how an assistant reads our documentation, how it pulls our data, and how it calls the parts of our tools that are pure calculation.

If you are the assistant reading this: start at llms.txt.

Read any docs page as Markdown

Add .md to any /docs URL and you get the page as plain Markdown with a text/markdown content type.

Text
https://fivemad.com/docs/server-setup/server-cfg      the page
https://fivemad.com/docs/server-setup/server-cfg.md   the same page as Markdown
https://fivemad.com/docs.md                           the index of every page

The Markdown is the real source of the page. The first lines say where it came from, which section it belongs to and when it was last touched, so a model that only sees the file still knows what it is holding.

Terminal
curl https://fivemad.com/docs/server-setup/server-cfg.md
Markdown
<!-- fivemad.com, Markdown source of https://fivemad.com/docs/server-setup/server-cfg -->
> Source: https://fivemad.com/docs/server-setup/server-cfg
> Section: Server setup
> Tags: server.cfg, convars, onesync, sv_enforceGameBuild, ensure, endpoints, ace, config
> Last updated: 2026-09-22
> Site map for assistants: https://fivemad.com/llms.txt

# server.cfg explained line by line

What every common server.cfg line does: endpoints, hostname, tags, license key, slots,
game build, OneSync, ensure order, convars, ACE permissions and splitting configs.

`server.cfg` is not a special format. It is a list of **server console commands** that
FXServer runs from top to bottom when it starts...

Every docs page also has an Open button next to the breadcrumbs. It gives you the Markdown view, a copy of the Markdown on your clipboard, and a one click hand-off to ChatGPT, Claude or Cursor with the page’s .md URL already in the prompt.

llms.txt and llms-full.txt

File What it holds
/llms.txt The short map: what fivemad is, every tool with one line, the whole docs tree, every dataset with its row count and size, and the API.
/llms-full.txt The documentation itself, every page in full, in one plain text file.

Both are built from the same registry and the same files the site ships, so the counts in them are real. They are listed in robots.txt too, and every docs page carries them as <link rel="alternate"> in its head.

Terminal
curl https://fivemad.com/llms.txt
Text
# fivemad.com

> Free tools, reference data and documentation for FiveM server owners and developers.
> 47 browser tools, 104 documentation pages and 29 public JSON datasets built from the GTA V game files.
> Nothing here needs an account. The tools run in the browser; the data below is static JSON you can fetch directly.

## How to use this site as an assistant

- Add .md to any docs URL for the plain Markdown source: https://fivemad.com/docs/server-setup/server-cfg.md
- Whole documentation in one file: https://fivemad.com/llms-full.txt
- Dataset index with row counts and sizes: https://fivemad.com/data/index.json
...

## Datasets

- [Props with pictures](https://fivemad.com/data/props.json): Every GTA V prop model that has a picture,
  with a readable label, category, tags and its real size in metres.
  (30,033 rows, 2.6 MB; rows: [model, label, category, tags, [x,y,z] size in m, minBuild, atlasCell, has3d])

Tip

If you are pasting context into a chat by hand, llms.txt plus the two or three .md pages it points at is almost always better than llms-full.txt. The full file is large.

The datasets

The reference data behind the tools is static JSON under /data. It is the same file the tool itself fetches, so nothing is held back.

Start with the index, which is generated from the real files:

Terminal
curl https://fivemad.com/data/index.json
JSON
{
  "site": "https://fivemad.com",
  "generated": "2026-09-23",
  "docs": "https://fivemad.com/docs/ai",
  "count": 29,
  "totalBytes": 12857308,
  "datasets": [
    {
      "id": "props",
      "title": "Props with pictures",
      "url": "https://fivemad.com/data/props.json",
      "about": "Every GTA V prop model that has a picture, with a readable label, category, tags and its real size in metres.",
      "shape": "rows: [model, label, category, tags, [x,y,z] size in m, minBuild, atlasCell, has3d]",
      "rows": 30033,
      "bytes": 2713710,
      "size": "2.6 MB",
      "page": "https://fivemad.com/tools/objects-list",
      "pageName": "Objects / Props List"
    }
  ]
}

Each entry tells you the URL, what the file holds, how a row is laid out, how many rows there are and how big the download is. The rows are short arrays on purpose: these files are fetched by browsers, so the column names live in the index and in a cols field inside the file, not on every row.

Some of these files are several megabytes. If all you need is one lookup, use the search or hash endpoints below instead of downloading the whole thing.

One short JSON answer over the tool list, the documentation and the dataset index.

Terminal
curl "https://fivemad.com/api/search?q=handling&limit=3"
JSON
{
  "query": "handling",
  "type": "all",
  "total": 16,
  "returned": 3,
  "limit": "60 requests per minute per IP",
  "hint": "Add .md to any docs URL for the plain Markdown source.",
  "results": [
    {
      "type": "doc",
      "title": "Vehicle Handling Editor",
      "url": "https://fivemad.com/docs/tools/vehicle-handling-editor",
      "markdown": "https://fivemad.com/docs/tools/vehicle-handling-editor.md",
      "summary": "Tune CHandlingData with sliders, import an existing handling.meta, toggle flag bits, and export handling.meta, runtime Lua or a carcols.meta mod kit.",
      "extra": {
        "section": "Tools",
        "match": "The Vehicle Handling Editor lets you tune a vehicle's CHandlingData block with sliders and a one line explanation per field..."
      },
      "score": 117.5
    },
    {
      "type": "tool",
      "title": "Vehicle Handling Editor",
      "url": "https://fivemad.com/tools/vehicle-handling-editor",
      "summary": "Tune mass, drive force, grip and suspension from a UI, then export handling.meta or runtime Lua.",
      "extra": { "category": "Config & Code", "tags": ["Vehicles", "Download"] },
      "score": 110
    }
  ]
}

Parameters: q (required), type (all, tools, docs, datasets), limit (1 to 50, default 10). Every documentation hit carries its .md URL, so the next step is one more fetch. The score is only there to explain the order; do not read anything into the absolute number.

Look up a joaat hash

Paste a hash and get the name back. The search runs over every name set the site ships: props and map objects, vehicles, peds, weapons and their components, animation dictionaries and clips, particle assets and effects, sounds and sound sets, ymap and IPL names, MLO interiors, scaleform movies, ped decorations, timecycle modifiers, animpostfx effects, player stats and cutscenes.

Terminal
curl "https://fivemad.com/api/hash?q=0xB779A091"
JSON
{
  "query": "0xB779A091",
  "searched": { "names": 113305, "sets": 22 },
  "note": "joaat is a 32 bit hash, so a value can belong to more than one name. Every match is listed; none is picked for you...",
  "limit": "60 requests per minute per IP",
  "count": 1,
  "results": [
    {
      "query": "0xB779A091",
      "readAs": "hash",
      "hash": { "unsigned": 3078201489, "signed": -1216765807, "hex": "0xB779A091" },
      "matchCount": 1,
      "matches": [
        {
          "name": "adder",
          "kind": "vehicle",
          "kindLabel": "Vehicle model",
          "page": "https://fivemad.com/tools/model-hash-browser?q=adder"
        }
      ]
    }
  ]
}

The other direction, with the name this time:

Terminal
curl "https://fivemad.com/api/hash?q=adder"
JSON
{
  "results": [
    {
      "query": "adder",
      "readAs": "name",
      "name": "adder",
      "lua": "`adder`",
      "hash": { "unsigned": 3078201489, "signed": -1216765807, "hex": "0xB779A091" },
      "matchCount": 1,
      "matches": [{ "name": "adder", "kind": "vehicle", "kindLabel": "Vehicle model" }]
    }
  ]
}

It works the other way round too: pass a name and you get the unsigned, signed and hex forms plus the Lua backtick literal, and the same match list says whether the game actually ships that name.

  • q accepts an unsigned value, a signed int32, 0x hex, bare 8 digit hex, or a name.
  • Up to 25 values in one call, separated by commas or new lines.
  • kind narrows the answer, for example kind=vehicle,ped. searched.byKind in the response lists every kind and how many names it holds.
  • A match may carry a parent: one animation dictionary, particle asset or sound set that contains the name. Because the hash depends on the name alone, a name is stored once, so the same clip or effect often lives in other dictionaries too. Treat parent as an example, not as the whole answer.

Important

joaat is a 32 bit hash, so a value can belong to more than one name. Every match is returned as a list and none of them is picked for you. If matchCount is above 1, the answer is genuinely ambiguous and you have to decide from context.

Here is a real one. 0x37D80B0E is both a prop model and a ymap of the same name, so both come back:

Terminal
curl "https://fivemad.com/api/hash?q=0x37D80B0E"
JSON
{
  "results": [
    {
      "query": "0x37D80B0E",
      "readAs": "hash",
      "matchCount": 2,
      "matches": [
        { "name": "prop_cheetah_covered", "kind": "prop", "kindLabel": "Prop / object model" },
        { "name": "prop_cheetah_covered", "kind": "ymap", "kindLabel": "ymap / IPL name" }
      ]
    }
  ]
}

A name we do not ship comes back with matchCount: 0. That means we have no record of it, not that it does not exist.

The page for the same thing is the joaat Hash Calculator, under the “Reverse lookup” tab.

Call a tool

The parts of the toolkit that are a pure function of their input can be called directly, so an assistant does not have to work out a flag value in its head. The list is at /api/tools.

Endpoint What it does
/api/tools/joaat joaat hash of one or more strings
/api/tools/driving-style driving style flags for TaskVehicleDriveToCoord and friends
/api/tools/animation-flags the flag argument of TaskPlayAnim
/api/tools/warning-buttons button flags for SetWarningMessage
/api/tools/handling-flags strHandlingFlags, strModelFlags and strDamageFlags

The index gives you a working example URL for each one, so an assistant can discover the whole thing from a single fetch:

Terminal
curl https://fivemad.com/api/tools
JSON
{
  "count": 5,
  "tools": [
    {
      "id": "driving-style",
      "name": "Driving style flags",
      "about": "eVehicleDrivingFlags for TaskVehicleDriveToCoord, TaskVehicleDriveWander and SetDriveTaskDrivingStyle: decode a value or build one from flag names.",
      "url": "https://fivemad.com/api/tools/driving-style",
      "page": "https://fivemad.com/tools/driving-style-calculator",
      "params": [
        { "name": "value", "about": "Decode this value: 786603, -1073741824, 0xC00AB, 0b1011 or 1|2|128." },
        { "name": "flags", "about": "Encode instead: flag names separated by commas (StopForVehicles, StopForPeds, ...)." },
        { "name": "preset", "about": "One of: Normal, Strict, Ignore lights, Avoid vehicles, Reckless, ..." }
      ],
      "example": "https://fivemad.com/api/tools/driving-style?value=786603"
    }
  ]
}

Decode a value:

Terminal
curl "https://fivemad.com/api/tools/driving-style?value=786603"
JSON
{
  "tool": "driving-style",
  "name": "Driving style flags",
  "page": "https://fivemad.com/tools/driving-style-calculator",
  "limit": "120 requests per minute per IP",
  "value": 786603,
  "signed": 786603,
  "hex": "0x000C00AB",
  "binary": "0000 0000 0000 1100 0000 0000 1010 1011",
  "active": [
    { "bit": 0, "value": 1, "name": "StopForVehicles", "label": "Stop for vehicles", "desc": "Brakes and waits behind vehicles in its way instead of driving into them.", "unknown": false },
    { "bit": 1, "value": 2, "name": "StopForPeds", "label": "Stop for peds", "desc": "Stops for pedestrians on the road.", "unknown": false },
    { "bit": 3, "value": 8, "name": "SteerAroundStationaryVehicles", "label": "Steer around stationary vehicles", "desc": "Steers around parked and empty vehicles.", "unknown": false },
    { "bit": 5, "value": 32, "name": "SteerAroundObjects", "label": "Steer around objects", "desc": "Steers around props and objects on the road.", "unknown": false },
    { "bit": 7, "value": 128, "name": "StopAtTrafficLights", "label": "Stop at traffic lights", "desc": "Obeys red lights and stop lines.", "unknown": false },
    { "bit": 18, "value": 262144, "name": "UseShortCutLinks", "label": "Use shortcut links", "desc": "Allows shortcut road links such as dirt tracks and alleys. Removes most route limits.", "unknown": false },
    { "bit": 19, "value": 524288, "name": "ChangeLanesAroundObstructions", "label": "Change lanes around obstructions", "desc": "Changes lanes to pass slower traffic and obstructions.", "unknown": false }
  ],
  "expression": "StopForVehicles | StopForPeds | SteerAroundStationaryVehicles | SteerAroundObjects | StopAtTrafficLights | UseShortCutLinks | ChangeLanesAroundObstructions",
  "natives": ["TaskVehicleDriveToCoord", "TaskVehicleDriveToCoordLongrange", "TaskVehicleDriveWander", "SetDriveTaskDrivingStyle"],
  "valuesUsedByRockstar": [0, 1, 4, 16, 131, 139, 7785, 7791, 262144, 262208, 262275, 525116, 786468]
}

Build one from names instead. The answer has the same shape, so you can round trip it:

Terminal
curl "https://fivemad.com/api/tools/driving-style?flags=StopForVehicles,StopAtTrafficLights,SteerAroundPeds"
JSON
{
  "value": 145,
  "signed": 145,
  "hex": "0x00000091",
  "binary": "0000 0000 0000 0000 0000 0000 1001 0001",
  "expression": "StopForVehicles | SteerAroundPeds | StopAtTrafficLights"
}

Hashing, in bulk:

Terminal
curl "https://fivemad.com/api/tools/joaat?text=adder,WEAPON_PISTOL"
JSON
{
  "tool": "joaat",
  "note": "The game lower-cases a string before hashing it, so ADDER and adder give the same value.",
  "results": [
    { "input": "adder", "unsigned": 3078201489, "signed": -1216765807, "hex": "0xB779A091", "lua": "`adder`" },
    { "input": "WEAPON_PISTOL", "unsigned": 453432689, "signed": 453432689, "hex": "0x1B06D571", "lua": "`weapon_pistol`" }
  ]
}

handling.meta writes its flag fields as bare hex, so that is how this endpoint reads a value, and it gives you the line back ready to paste:

Terminal
curl "https://fivemad.com/api/tools/handling-flags?set=strHandlingFlags&value=440010"
JSON
{
  "set": "strHandlingFlags",
  "label": "Handling flags",
  "value": 4456464,
  "hex": "440010",
  "metaValue": "<strHandlingFlags value=\"440010\" />",
  "binary": "0000 0000 0100 0100 0000 0000 0001 0000",
  "active": [
    { "bit": 4, "value": 16, "name": "HF_NO_HANDBRAKE", "desc": "Handbrake disabled." },
    { "bit": 18, "value": 262144, "name": "HF_REDUCED_DRIVE_OVER_DAMAGE", "desc": "Takes less damage driving over things." },
    { "bit": 22, "value": 4194304, "name": "HF_TYRES_RAISE_SIDE_IMPACT_THRESHOLD", "desc": "Tyres resist side impacts better." }
  ],
  "expression": "HF_NO_HANDBRAKE | HF_REDUCED_DRIVE_OVER_DAMAGE | HF_TYRES_RAISE_SIDE_IMPACT_THRESHOLD"
}

Call an endpoint with no parameters and it answers with its full flag list, its presets and what each bit means, which is enough for a model to pick the right flags on its own:

Terminal
curl "https://fivemad.com/api/tools/animation-flags"

POST with a JSON body works the same as the query string:

Terminal
curl -X POST https://fivemad.com/api/tools/animation-flags \
  -H "content-type: application/json" \
  -d '{"flags":"AF_LOOPING,AF_UPPERBODY"}'

These use the exact same code as the tool pages, so the two can never give different answers.

Rate limits

Per IP, in a fixed one minute window:

Endpoint Limit
/api/search 60 per minute
/api/hash 60 per minute
/api/tools and /api/tools/* 120 per minute
All of the above together 240 per minute

Over the limit you get 429 with a retry-after header in seconds and a JSON body that says which limit you hit:

JSON
{
  "error": "rate_limited",
  "message": "Too many requests. This endpoint allows 60 requests per minute per IP (240 across the whole API). Try again in 41s.",
  "docs": "https://fivemad.com/docs/ai"
}

The static files (/data/*.json, the .md pages, llms.txt) are served straight off disk and are not rate limited. Please cache them rather than refetching: they change when we rebuild, not per request.

The older endpoints keep their own limits: /api/server allows 30 lookups per minute per IP and /api/blacklist allows 20.

CORS, caching and errors

  • The /api/* endpoints on this page answer with access-control-allow-origin: * and handle a preflight, so a browser based agent can call them from any page.
  • The static files (/data/*.json, /data/index.json, the .md pages, llms.txt) are served by the front end web server, not by the app, so whether they carry that header depends on the deployment. From a server side script, curl or an assistant’s own fetcher this makes no difference. If you are calling them from a browser and get a CORS error, use /api/search or /api/hash instead, or proxy the file yourself.
  • Errors are JSON with an error code, a message written for a human, and a link back to this page. Status codes are the ordinary ones: 400 bad input, 404 unknown tool, 429 rate limited, 503 when an index is not loaded yet.
  • /api/* answers are cached for 60 seconds. The static files carry a longer cache.

What an assistant can and cannot do here

It can:

  • read any documentation page as Markdown, and the whole set at once;
  • list and download every dataset, with the row shape given up front;
  • resolve a joaat hash to a name, or a name to a hash, across the whole game;
  • compute the flag values the natives want, and get the flag meanings back with them;
  • link a person straight to the page that shows the same thing.

It cannot:

  • run the tools that need a file, a browser or the game files. The texture editor, the clothing designer, the ymap and ytyp builders, the profiler and the 3D viewers all work on data you drop into the page, in your own browser, and there is no upload endpoint for them.
  • write anything. Everything here is read only.
  • look up a name we do not ship. Our data comes from the game files and from public FiveM sources; a model, sound or animation that a custom resource adds is not in it.
  • be treated as a live game API. Nothing here talks to a running server, except /api/server, which reports what a FiveM server publishes about itself.

A worked example

“What driving style should I use for an ambulance that runs red lights but still avoids traffic?”

Terminal
# 1. see what the flags mean
curl "https://fivemad.com/api/tools/driving-style"

# 2. build the value
curl "https://fivemad.com/api/tools/driving-style?flags=SwerveAroundAllVehicles,SteerAroundStationaryVehicles,SteerAroundPeds,SteerAroundObjects,AllowGoingWrongWay"

# 3. check the vehicle model exists and get its hash
curl "https://fivemad.com/api/hash?q=ambulance"

The answer to step 2 carries the value, its signed and hex forms and the native names it belongs to, which is everything needed to write the TaskVehicleDriveToCoord call.