Freak HostingLogs

API and docs

Everything the website does is available as a small JSON API: upload a log, read it back, delete it. No account, no API key.

Limits

WhatValue
Size of a log10 MB (413 too_large beyond that)
Retention90 days, then the log is deleted
Uploads per network address30 per hour and 200 per day (429 rate_limited with a Retry-After header)
ContentText only. Binary content is refused (422 not_text)

The current values are always at GET /api/v1/limits. Base address: https://logs.freakhosting.com.

Upload a log

POST

/api/v1/log

Send JSON with the text of the log in content. source is optional and says where the log comes from.

{
  "content": "[12:00:00 INFO]: Starting minecraft server version 1.21.1\n...",
  "source": {
    "game": "minecraft",          // "minecraft" | "fivem" | "other" (default "other": detected from the text)
    "server": "My survival server", // optional, at most 80 characters
    "panel": "panel.example.com"   // optional, at most 120 characters
  }
}

Plain text bodies work too (Content-Type: text/plain), for curl users; game, server and panel can then be given as query parameters.

The server removes secrets and public IP addresses again, whatever the client did, and stores only the cleaned text. Reply 201:

{
  "id": "aB3dE5gH",
  "url": "https://logs.freakhosting.com/aB3dE5gH",
  "raw": "https://logs.freakhosting.com/raw/aB3dE5gH",
  "deleteToken": "q8Zk...",            // keep it: it is the only way to delete the log, and it is never shown again
  "expiresAt": "2027-01-08T12:00:00.000Z",
  "removed": { "address": 4, "secret-setting": 1 },   // what the server removed, by kind
  "problems": 2                        // how many problems the analysis found
}

curl

# a file, as plain text
curl -sS -X POST -H 'Content-Type: text/plain' --data-binary @latest.log 'https://logs.freakhosting.com/api/v1/log?game=minecraft'

# a file, as JSON (jq builds the body)
jq -Rs '{content: ., source: {game: "minecraft"}}' latest.log \
  | curl -sS -X POST -H 'Content-Type: application/json' --data-binary @- https://logs.freakhosting.com/api/v1/log

JavaScript

const response = await fetch('https://logs.freakhosting.com/api/v1/log', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ content: logText, source: { game: 'minecraft', server: 'My server' } }),
});
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);   // { error: { code, message } }
console.log(body.url, body.deleteToken);

Read a log's details

GET

/api/v1/log/:id

The details and the analysis, not the text (that is /raw/:id).

{
  "id": "aB3dE5gH",
  "createdAt": "2026-10-10T12:00:00.000Z",
  "expiresAt": "2027-01-08T12:00:00.000Z",
  "size": 12045112,            // bytes of the stored text
  "lines": 200000,
  "source": { "game": "minecraft", "server": "My survival server" },
  "analysis": {
    "game": "minecraft",       // detected: "minecraft" | "fivem" | "unknown"
    "lines": 200000,
    "starts": 3,               // how many server starts the log shows; problems come from the newest
    "info": { "minecraft": "1.21.1", "software": "Paper", "softwareVersion": "1.21.1-130-main@a1b2c3d", "java": 21 },
    "problems": [
      {
        "id": "java-too-old",
        "severity": "error",   // "error" | "warning" | "info"
        "title": "This needs Java 21, the server runs Java 17",
        "explanation": "A program in the server ... was built for a newer Java ...",
        "evidence": ["[12:00:03 ERROR]: ... UnsupportedClassVersionError ..."],
        "fixes": [{ "kind": "java", "version": 21, "label": "Switch to Java 21" }],
        "data": { "required": 21, "running": 17 }
      }
    ]
  }
}
curl -sS https://logs.freakhosting.com/api/v1/log/aB3dE5gH

Raw text

GET

/raw/:id

The stored (cleaned) text as text/plain; charset=utf-8. Sent with X-Content-Type-Options: nosniff and a locked-down Content-Security-Policy, so a browser shows it as text and never runs anything in it.

curl -sS https://logs.freakhosting.com/raw/aB3dE5gH

Delete a log

DELETE

/api/v1/log/:id

Send the delete token from the upload reply as a bearer token. Reply 204 with no body. A missing token gives 401, a wrong one 403.

curl -sS -X DELETE -H 'Authorization: Bearer YOUR_DELETE_TOKEN' https://logs.freakhosting.com/api/v1/log/aB3dE5gH
await fetch('https://logs.freakhosting.com/api/v1/log/' + id, { method: 'DELETE', headers: { Authorization: 'Bearer ' + deleteToken } });

Limits

GET

/api/v1/limits

{ "maxBytes": 10485760, "retentionDays": 90, "uploadsPerHour": 30, "uploadsPerDay": 200 }

Errors

Every error has the same shape, with a stable code to program against and a message for people:

{ "error": { "code": "too_large", "message": "The log is larger than the limit of 10 MB." } }
StatuscodeWhen
400invalid_json, invalid_requestThe body is not valid JSON, or has no string content
401unauthorizedDelete without a bearer token
403forbidden, blockedThe delete token does not belong to this log; the address is blocked
404not_foundNo such log (deleted, never existed, or not a valid ID)
405method_not_allowedWrong HTTP method for the route (the Allow header says which)
408timeoutThe upload was too slow
410expiredThe log's retention has passed
413too_largeMore than 10 MB
415unsupported_media_typeNot application/json or text/plain
422empty, not_text, unprocessableNothing in the log; binary content; the log could not be processed
429rate_limitedToo many uploads or requests; wait Retry-After seconds
500internal_errorSomething went wrong on the server (try again; if it persists, tell us)
503, 507busy, storage_fullThe server is processing too many logs at once, or cannot store more right now

CORS

Every /api/v1/* reply carries Access-Control-Allow-Origin: *, preflight requests are answered, and Content-Type and Authorization are allowed. There are no cookies and no credentials anywhere, so a web page on any origin can call the API.

The viewer

Open the url of a log in a browser. Search with Ctrl+F (Enter and Shift+Enter move between matches), filter by errors and warnings, click a line number to link to that line (#L120), shift-click to select a range (#L120-L140). The panel on the side lists the problems found, with the lines that show them and what to do about them.

IDs and delete tokens

An ID is 8 characters without look-alikes (no 0 O 1 l I), drawn from a cryptographically secure random source. A delete token is 192 random bits; only a hash of it is stored.