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
| What | Value |
|---|---|
| Size of a log | 10 MB (413 too_large beyond that) |
| Retention | 90 days, then the log is deleted |
| Uploads per network address | 30 per hour and 200 per day (429 rate_limited with a Retry-After header) |
| Content | Text 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
/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
/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
/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
/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
/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." } }
| Status | code | When |
|---|---|---|
| 400 | invalid_json, invalid_request | The body is not valid JSON, or has no string content |
| 401 | unauthorized | Delete without a bearer token |
| 403 | forbidden, blocked | The delete token does not belong to this log; the address is blocked |
| 404 | not_found | No such log (deleted, never existed, or not a valid ID) |
| 405 | method_not_allowed | Wrong HTTP method for the route (the Allow header says which) |
| 408 | timeout | The upload was too slow |
| 410 | expired | The log's retention has passed |
| 413 | too_large | More than 10 MB |
| 415 | unsupported_media_type | Not application/json or text/plain |
| 422 | empty, not_text, unprocessable | Nothing in the log; binary content; the log could not be processed |
| 429 | rate_limited | Too many uploads or requests; wait Retry-After seconds |
| 500 | internal_error | Something went wrong on the server (try again; if it persists, tell us) |
| 503, 507 | busy, storage_full | The 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.