Skip to content

Repository files navigation

ScamScreener Platform

This repository contains two separate applications in one repo:

  • Training Hub for player-contributed training data and admin-side pipeline control
  • MarketGuard API for Hypixel SkyBlock market data, including Lowest BIN aggregation

What it provides

  • Clear package split between app/training_hub and app/marketguard_api
  • External web sign-in via approved GitHub OAuth and/or Authelia OIDC identities
  • Local app session management after external provider sign-in
  • Branded HTML emails with plain-text fallback for operational mail where enabled
  • Admin backup create/restore for DB + uploads + bundles
  • Player dashboard with own contribution stats
  • Upload form for training-cases-v2.jsonl files
  • Per-account upload history with download links
  • Self-service upload deletion, full contribution purge, and account deletion
  • Self-service account data export workflow delivered by email
  • Admin view over users, basic case list, training runs, and audit log
  • Admin-managed content scrubbing rules for quarantining matching cases from future uploads before storage and training
  • Monitoring metrics endpoint (/api/v1/metrics) and auth-spike alerting
  • Public Lowest BIN v2 endpoint at /api/v2/lowestbin
  • Public Bazaar endpoint at /api/v1/bazaar
  • Public player/profile QUERY endpoint at /api/v1/players
  • Admin button to:
    • build one merged training bundle from all accepted uploads
  • Audit log also records upload and bundle downloads

Data/state:

  • the default deployment stores app state under /app/data
  • Training Hub stores users, sessions, uploads, cases, and audit metadata in MariaDB for staging/production deployments
  • accepted upload payloads, quarantined scrub hits, and generated bundles are kept in the persistent app data volume

Frontend files:

  • HTML templates: sites/
  • CSS: css/

Application packages:

  • app/training_hub/ contains the Training Hub app, routes, storage, auth, and admin flows
  • app/marketguard_api/ contains the Hypixel auction client, Lowest BIN cache, and API routes
  • app/main.py remains available as the combined in-process entrypoint used by tests and local integration scenarios

1) Local setup

python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
Copy-Item .env.example .env

The sample .env.example is a local-development baseline. Before a real deployment, switch the production-only flags called out in section 4. It is intentionally minimal: anything omitted falls back to the app defaults in app/training_hub/config/settings.py and app/marketguard_api/config.py.

Set at least:

  • TRAINING_HUB_SECRET_KEY to a long random value (at least 32 characters recommended)

Optional:

  • TRAINING_HUB_ADMIN_USERNAMES (comma-separated admin allowlist for externally provisioned users)
  • TRAINING_HUB_DB_DRIVER=sqlite if you intentionally want a local development fallback instead of MariaDB

Bootstrap note: web access now comes from external identity providers. Configure either GitHub OAuth or Authelia OIDC plus an explicit allowlist before first sign-in.

2) Run locally

.\.venv\Scripts\Activate.ps1
uvicorn app.training_hub.main:create_app --factory --host 0.0.0.0 --port 8080

In a second shell for the MarketGuard API:

.\.venv\Scripts\Activate.ps1
uvicorn app.marketguard_api.main:create_marketguard_app --factory --host 0.0.0.0 --port 8081

Open:

  • http://localhost:8080 (Training Hub landing page)
  • http://localhost:8080/hub (redirects to login/dashboard)
  • http://localhost:8081/api/v2/lowestbin (MarketGuard Lowest BIN JSON with lastUpdated, products, seller UUID, and auction item_name)
  • http://localhost:8081/api/v1/bazaar (MarketGuard Bazaar summary JSON)
  • http://localhost:8081/api/v1/players (MarketGuard player/profile JSON via the QUERY method)
  • http://localhost:8081/docs (interactive OpenAPI docs for local validation)

3) Docker Deploy

The repository now ships a single Compose stack behind bundled Caddy. It runs five base services plus an optional Redis cache service when MARKETGUARD_REDIS_ENABLED=true with SCAMSCREENER_REDIS_MANAGED=true:

  • scamscreener-hub for the Training Hub
  • scamscreener-api for the public Lowest BIN and Bazaar API
  • marketguard-hub for the public market website under /market/
  • scamscreener-db for the internal MariaDB database
  • caddy for public HTTPS termination and reverse proxy

The stack keeps persistent state under /app/data, auto-generates a strong app secret on first boot when you do not provide one, auto-generates persistent MariaDB credentials for the managed internal database, and preserves the same public URLs as before.

One-time setup:

Copy-Item .env.production.example .env.production
# edit .env.production

Then start production:

python scripts/update.py

What this path expects:

  • a real public domain in CADDY_SITE_ADDRESS such as scamscreener.creepans.net
  • TRAINING_HUB_PUBLIC_BASE_URL is set to the real public https://... URL
  • GitHub OAuth and/or Authelia OIDC are configured with explicit allowlists
  • TRAINING_HUB_ADMIN_USERNAMES and/or TRAINING_HUB_ADMIN_EMAILS are set for deterministic admin bootstrap
  • SMTP is configured only if you explicitly enable password reset or admin MFA mail flows
  • TRAINING_HUB_SITE_* values are reviewed for /impressum and /datenschutz
  • persistent storage is kept on the Docker volumes

What this path provides automatically:

  • one internal hub container, one internal API container, one internal market website container, one internal MariaDB container, one public Caddy container, and an optional internal Redis container
  • automatic HTTPS via Caddy
  • /api/v1/health healthchecks for the hub and a dedicated internal health route for the API
  • public blocking of /api/v1/health, /api/v1/metrics, and internal-only health paths
  • generated persistent secret key when TRAINING_HUB_SECRET_KEY is omitted
  • generated persistent MariaDB app/root passwords when SCAMSCREENER_DB_MANAGED=true

Operational helpers for this path:

  • python scripts/update.py runs preflight, rebuilds the image, restarts the stack, waits for app health, and marks the deployment as OAuth-ready
  • python scripts/update.py --skip-pull skips upstream base-image pulls during rebuild
  • python scripts/migrate.py creates repo/volume backups, stops the legacy local-login split stack without deleting volumes, and then starts the OAuth/OIDC release in place
  • python scripts/reset.py asks for confirmation and then deletes the full compose deployment state for a clean restart
  • python scripts/reset.py --yes --prune-images also removes the locally built app image

The production topology is Compose-first. Running a single docker run container no longer reproduces the full production stack because the hub, public API, and MariaDB are isolated into separate services.

4) Environment variables

  • CADDY_SITE_ADDRESS default http://localhost (set a real domain for public Caddy TLS)
  • CADDY_HTTP_PORT default 80
  • CADDY_HTTPS_PORT default 443
  • PORT optional runtime port override used by the app image
  • WEB_CONCURRENCY optional worker count for the app image (default 1; keep this value for the player QUERY route until its per-IP rate limiter is centralized)
  • TRAINING_HUB_HOST default 0.0.0.0
  • TRAINING_HUB_PORT default 8080
  • TRAINING_HUB_ENV default development (production enforces strict startup checks)
  • TRAINING_HUB_PUBLIC_BASE_URL optional absolute public base URL; recommended for production and used for reset links plus allowed-host fallback
  • TRAINING_HUB_ALLOWED_HOSTS optional allowlist for Host header validation
  • SCAMSCREENER_DB_MANAGED default false; set true for the bundled internal MariaDB service
  • SCAMSCREENER_DB_NAME default scamscreener_hub
  • SCAMSCREENER_DB_USER default scamscreener
  • TRAINING_HUB_DB_DRIVER default sqlite in development and mariadb in staging/production
  • TRAINING_HUB_DATABASE_URL optional full DSN override (mariadb://user:pass@host:3306/db)
  • TRAINING_HUB_DB_HOST default 127.0.0.1
  • TRAINING_HUB_DB_PORT default 3306
  • TRAINING_HUB_DB_NAME default scamscreener_hub
  • TRAINING_HUB_DB_USER default scamscreener
  • TRAINING_HUB_DB_PASSWORD required when driver is mariadb unless the managed compose stack injects it from its generated runtime secret
  • TRAINING_HUB_DB_REQUIRE_TLS default false in development and true for external MariaDB in production
  • TRAINING_HUB_DB_SSL_CA optional CA path for external MariaDB TLS verification
  • TRAINING_HUB_DB_SSL_CERT optional client certificate for MariaDB TLS
  • TRAINING_HUB_DB_SSL_KEY optional client key for MariaDB TLS
  • TRAINING_HUB_DB_SSL_VERIFY_HOSTNAME default true
  • TRAINING_HUB_SECRET_KEY required
  • TRAINING_HUB_SESSION_TTL_MINUTES default 720
  • TRAINING_HUB_SESSION_BIND_IP default false
  • TRAINING_HUB_SESSION_BIND_USER_AGENT default false
  • TRAINING_HUB_GITHUB_OAUTH_CLIENT_ID / TRAINING_HUB_GITHUB_OAUTH_CLIENT_SECRET enable GitHub sign-in
  • TRAINING_HUB_GITHUB_OAUTH_ALLOWED_LOGINS / TRAINING_HUB_GITHUB_OAUTH_ALLOWED_EMAILS / TRAINING_HUB_GITHUB_OAUTH_ALLOWED_SUBJECTS restrict GitHub access
  • TRAINING_HUB_AUTHELIA_OIDC_ISSUER_URL / TRAINING_HUB_AUTHELIA_OIDC_CLIENT_ID / TRAINING_HUB_AUTHELIA_OIDC_CLIENT_SECRET enable Authelia OIDC
  • TRAINING_HUB_AUTHELIA_OIDC_SCOPES default openid,profile,email
  • TRAINING_HUB_AUTHELIA_OIDC_ALLOWED_EMAILS / TRAINING_HUB_AUTHELIA_OIDC_ALLOWED_USERNAMES / TRAINING_HUB_AUTHELIA_OIDC_ALLOWED_SUBJECTS restrict Authelia access
  • TRAINING_HUB_SMTP_HOST SMTP server host
  • TRAINING_HUB_SMTP_PORT SMTP server port (default 587)
  • TRAINING_HUB_SMTP_USERNAME optional SMTP username
  • TRAINING_HUB_SMTP_PASSWORD optional SMTP password
  • TRAINING_HUB_SMTP_FROM_EMAIL sender address for outbound account exports and operational mail
  • TRAINING_HUB_SMTP_USE_TLS default false (implicit TLS/SMTPS)
  • TRAINING_HUB_SMTP_USE_STARTTLS default true (explicit STARTTLS)
  • TRAINING_HUB_SITE_PROJECT_CLASSIFICATION default Private non-commercial community project
  • TRAINING_HUB_SITE_OPERATOR_NAME optional operator/provider name rendered on /impressum
  • TRAINING_HUB_SITE_POSTAL_ADDRESS optional postal address rendered on /impressum
  • TRAINING_HUB_SITE_CONTACT_CHANNEL optional public contact channel rendered on /impressum
  • TRAINING_HUB_SITE_PRIVACY_CONTACT optional privacy contact rendered on /datenschutz
  • TRAINING_HUB_SITE_HOSTING_LOCATION default Ashburn, Virginia, USA
  • TRAINING_HUB_WEBAUTHN_RP_ID optional WebAuthn relying-party ID (defaults from TRAINING_HUB_PUBLIC_BASE_URL or allowed hosts)
  • TRAINING_HUB_WEBAUTHN_RP_NAME default ScamScreener
  • TRAINING_HUB_WEBAUTHN_ORIGINS optional comma-separated WebAuthn origins (defaults from TRAINING_HUB_PUBLIC_BASE_URL, or from allowed hosts in production)
  • TRAINING_HUB_ENFORCE_HTTPS default false (true in production)
  • TRAINING_HUB_ENABLE_RATE_LIMIT default true
  • TRAINING_HUB_ENFORCE_ORIGIN_CHECK default true
  • TRAINING_HUB_MAX_UPLOAD_BYTES default 5242880
  • TRAINING_HUB_MAX_UPLOAD_DOWNLOADS_PER_MINUTE_PER_USER default 60
  • TRAINING_HUB_MAX_BUNDLE_DOWNLOADS_PER_MINUTE_PER_USER default 30
  • TRAINING_HUB_MAX_UPLOADS_PER_DAY_PER_USER default 40
  • TRAINING_HUB_MAX_UPLOAD_BYTES_PER_DAY_PER_USER default 209715200
  • TRAINING_HUB_MAX_UPLOAD_CASES_PER_DAY_PER_USER default 20000
  • TRAINING_HUB_MAX_UPLOADS_PER_DAY_PER_IP default 120
  • TRAINING_HUB_GLOBAL_UPLOAD_STORAGE_CAP_BYTES default 5368709120
  • TRAINING_HUB_RETENTION_SESSIONS_DAYS default 30
  • TRAINING_HUB_RETENTION_PASSWORD_RESET_DAYS default 7
  • TRAINING_HUB_RETENTION_AUDIT_LOGS_DAYS default 180
  • TRAINING_HUB_RETENTION_UPLOADS_DAYS default 365
  • TRAINING_HUB_RETENTION_BUNDLES_DAYS default 365
  • TRAINING_HUB_RETENTION_BACKUPS_DAYS default 30
  • TRAINING_HUB_RETENTION_RATE_LIMIT_DAYS default 7
  • TRAINING_HUB_RETENTION_AUTO_ENABLED default false
  • TRAINING_HUB_RETENTION_AUTO_INTERVAL_MINUTES default 1440
  • TRAINING_HUB_BACKUP_RESTORE_MAX_BYTES default 536870912
  • TRAINING_HUB_SECURITY_ALERT_WINDOW_MINUTES default 15
  • TRAINING_HUB_SECURITY_ALERT_COOLDOWN_MINUTES default 15
  • TRAINING_HUB_SECURITY_ALERT_FAILED_LOGIN_THRESHOLD default 10
  • TRAINING_HUB_SECURITY_ALERT_MFA_FAILED_THRESHOLD default 6
  • TRAINING_HUB_SECURITY_ALERT_PASSWORD_RESET_THRESHOLD default 10
  • TRAINING_HUB_STORAGE_DIR default ./data
  • TRAINING_HUB_ADMIN_EMAILS optional in development, but required in production unless TRAINING_HUB_ADMIN_USERNAMES is set
  • TRAINING_HUB_ADMIN_USERNAMES optional in development, but required in production unless TRAINING_HUB_ADMIN_EMAILS is set
  • TRAINING_HUB_TRUSTED_PROXIES optional, comma-separated exact IPs or CIDR ranges (docker-compose.yml keeps 127.0.0.1 for the internal healthcheck and appends the internal Caddy IP automatically)
  • TRAINING_HUB_PROJECT_ROOT optional
  • SCAMSCREENER_INTERNAL_API_METRICS_URL optional absolute internal URL for aggregating live API metrics from a separate API process or container
  • MARKETGUARD_HYPIXEL_API_BASE_URL default https://api.hypixel.net/v2
  • MARKETGUARD_REQUEST_TIMEOUT_SECONDS default 10
  • MARKETGUARD_MAX_PARALLEL_PAGES default 8
  • MARKETGUARD_SNAPSHOT_RETRIES default 3
  • MARKETGUARD_DB_DRIVER must be mariadb
  • MARKETGUARD_DATABASE_URL optional direct MariaDB DSN override
  • MARKETGUARD_DB_HOST / MARKETGUARD_DB_PORT / MARKETGUARD_DB_NAME / MARKETGUARD_DB_USER / MARKETGUARD_DB_PASSWORD configure the API database when MARKETGUARD_DATABASE_URL is unset
  • MARKETGUARD_DB_REQUIRE_TLS and MARKETGUARD_DB_SSL_CA enable verified external MariaDB TLS; the managed internal compose database defaults to plain internal transport
  • MARKETGUARD_CACHE_TTL_SECONDS default 60
  • MARKETGUARD_STALE_IF_ERROR_SECONDS default 300
  • MARKETGUARD_HISTORY_RETENTION_DAYS default 45
  • MARKETGUARD_LOWESTBIN_RATE_LIMIT_PER_MINUTE default 30
  • MARKETGUARD_HYPIXEL_API_KEY required for /api/v1/players; keep it only in the deployment secret environment
  • MARKETGUARD_PLAYERS_RATE_LIMIT_PER_MINUTE default 3 per source IP; set 0 only for controlled internal testing
  • MARKETGUARD_PLAYERS_MAX_UPSTREAM_CONCURRENCY default 4 per API worker; raise it only after checking the Player QUERY efficiency metrics and Hypixel quota
  • MARKETGUARD_LOCAL_CACHE_ENABLED toggles the small per-process response cache
  • MARKETGUARD_LOCAL_CACHE_TTL_SECONDS and MARKETGUARD_LOCAL_CACHE_MAX_ENTRIES bound local API RAM usage
  • MARKETGUARD_REDIS_ENABLED toggles the shared Redis response cache
  • MARKETGUARD_REDIS_URL optional direct Redis URL override
  • MARKETGUARD_REDIS_HOST / MARKETGUARD_REDIS_PORT / MARKETGUARD_REDIS_DB / MARKETGUARD_REDIS_PASSWORD configure Redis when MARKETGUARD_REDIS_URL is unset
  • MARKETGUARD_REDIS_REQUIRE_TLS enables rediss:// for external Redis
  • MARKETGUARD_REDIS_CACHE_TTL_SECONDS and MARKETGUARD_REDIS_KEY_PREFIX control Redis response caching
  • MARKETGUARD_REDIS_MAXMEMORY and MARKETGUARD_REDIS_MAXMEMORY_POLICY tune the internal Redis container when SCAMSCREENER_REDIS_MANAGED=true
  • MARKETGUARD_HTTP_USER_AGENT default ScamScreener-MarketGuard/1.0
  • MARKETGUARD_TRUSTED_PROXIES optional, comma-separated exact IPs or CIDR ranges (falls back to TRAINING_HUB_TRUSTED_PROXIES when unset)
  • TRAINING_HUB_API_DOCS_ENABLED default true outside production, false in production
  • MARKETGUARD_API_DOCS_ENABLED default true for the standalone MarketGuard app, set false in production

Production-mode startup checks (TRAINING_HUB_ENV=production) enforce:

  • TRAINING_HUB_ENFORCE_HTTPS=true
  • strong TRAINING_HUB_SECRET_KEY (>= 32 chars)
  • TRAINING_HUB_ENABLE_RATE_LIMIT=true
  • TRAINING_HUB_ENFORCE_ORIGIN_CHECK=true
  • explicit TRAINING_HUB_ALLOWED_HOSTS (no wildcard)
  • MariaDB selected by default unless TRAINING_HUB_DB_DRIVER is explicitly overridden
  • MariaDB TLS enabled for external MariaDB connections unless the managed internal compose database is used
  • at least one external sign-in provider must be configured

Admin trigger creates a merged bundle and records the run as prepared.

Security headers include CSP, COOP/CORP, X-Frame-Options, and Permissions-Policy. Failed/locked login attempts for known accounts are written to the audit log. Admin can run retention cleanup from /admin to prune stale sessions, reset tokens, legacy MFA challenges, generic auth flows, logs, uploads, bundles, backups, and rate-limit rows. Automatic retention cleanup runs in the background when TRAINING_HUB_RETENTION_AUTO_ENABLED=true. Admin can create and restore backups from /admin (archive includes DB export + uploads + bundles; restore requires valid signed manifest). Prometheus-compatible monitoring is available at the internal-only /api/v1/metrics endpoint.

Container hardening defaults:

  • runs as non-root user
  • read-only root filesystem in docker-compose.yml
  • dropped Linux capabilities (cap_drop: ALL)
  • no-new-privileges enabled
  • internal MariaDB transport stays on the private Compose network; use external MariaDB plus TLS settings if you need DB-layer encryption

Supply-chain checks:

  • GitHub Actions workflow .github/workflows/server-security.yml runs pip-audit and trivy
  • Dependabot config .github/dependabot.yml enables weekly dependency updates

5) API endpoints

  • GET /api/v1/health (internal only)
  • GET /api/v2/lowestbin
  • QUERY /api/v2/lowestbin
  • GET /api/v1/bazaar
  • QUERY /api/v1/players
  • QUERY /api/v1/player-finance
  • GET /market/
  • GET /market/bazaar
  • POST /api/v1/client/uploads
  • POST /api/v1/client/uploads/anonymous
  • POST /api/v1/client/auth/logout

/api/v1/health is an internal-only observability endpoint that returns status, UTC time, user/upload counts, and storage metadata. /api/v2/lowestbin returns an object with top-level lastUpdated plus a products object whose keys are item identifiers and whose values contain the current Lowest BIN price, seller auctioneerUuid, Hypixel auction item_name, and snapshot-based avg7d / avg30d averages over deduplicated Hypixel snapshots. QUERY /api/v2/lowestbin accepts a JSON body with a non-empty products array and returns the same response shape containing only the requested identifiers. Unknown identifiers are omitted. The QUERY method is additive and does not replace the GET endpoint; because the HTTP QUERY method is currently an IETF Internet-Draft, clients should retain GET as a compatibility fallback.

QUERY /api/v1/players accepts up to ten Minecraft usernames or UUIDs paired with a required SkyBlock profile UUID. It returns each player in request order with the canonical UUID, first join timestamp, requested profile, bank/purse coins, decoded armor and equipment item lists, and SkyBlock skill level plus XP. The endpoint is public but rate-limited and uses MARKETGUARD_HYPIXEL_API_KEY only on the server. Profile privacy settings or upstream failures can make individual fields unavailable; the response reports that through status and unavailableFields without exposing raw upstream data. If that key is missing or rejected by Hypixel, the route returns HTTP 419 with a generic error detail. The top-level response status is ok or stale when served from the shared cache; clients can also inspect X-Data-Stale. Cache misses for the same normalized request share one in-flight upstream lookup, the upstream work is bounded per worker, and skill definitions are cached for one hour.

QUERY /api/v1/player-finance accepts exactly {playerUuid, profileId} with either compact or dashed UUIDs and returns compact lowercase UUIDs. The public route uses the existing player rate limit and shared response cache. It first verifies through Hypixel /v2/skyblock/profile that the player belongs to the requested profile, then reads /v2/skyblock/museum with the server-side MARKETGUARD_HYPIXEL_API_KEY. Only the requested member is normalized. The response contains bank, purse, Hypixel's authoritative museum value and appraisal, donated position IDs, decoded special exhibit IDs, counts, and knownTotal only when bank, purse, and museum value are all available. Raw Coop members and Museum NBT are never returned. Privacy-disabled or temporarily unavailable Museum data produces status: "partial" with unavailableFields while preserving available bank and purse values. A missing or rejected server key returns HTTP 419. Costs, revenue, profit, and ROI are not available from these upstream fields and are intentionally not estimated or included.

The protected Admin Analytics Metrics page includes the player route's cache-hit rate, average response time, active upstream loads, coalesced requests, and upstream failures. The Compose deployment already supplies its internal API metrics URL. Keep WEB_CONCURRENCY=1 while this route uses the built-in process-local per-IP limiter; Redis shares cached responses but does not make that limiter distributed.

Example QUERY /api/v1/players request:

QUERY /api/v1/players HTTP/1.1
Content-Type: application/json

{"players":[{"player":"Pankraz01","profileId":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}]}

Example QUERY /api/v1/player-finance request:

QUERY /api/v1/player-finance HTTP/1.1
Content-Type: application/json

{"playerUuid":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","profileId":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}

Example complete player-finance result:

{
  "status": "ok",
  "stale": false,
  "fetchedAt": 1715478978620,
  "playerUuid": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "profile": {
    "id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
    "name": "Apple",
    "selected": true,
    "finance": {
      "bank": 125000000.0,
      "purse": 4250000.5,
      "museumValue": 85000000.0,
      "knownTotal": 214250000.5
    },
    "museum": {
      "value": 85000000.0,
      "appraisal": true,
      "donatedIds": ["ASPECT_OF_THE_END", "NECRON_HELMET"],
      "donatedCount": 2,
      "specialIds": ["DCTR_SPACE_HELM"],
      "specialCount": 1
    }
  },
  "unavailableFields": []
}

Example QUERY /api/v2/lowestbin request:

QUERY /api/v2/lowestbin HTTP/1.1
Content-Type: application/json

{"products":["HYPERION","TRUE_ESSENCE"]}

Example successful player result:

{
  "status": "ok",
  "players": [
    {
      "status": "ok",
      "uuid": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
      "name": "Pankraz01",
      "firstJoin": 1587483921000,
      "profile": {
        "id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
        "name": "Apple",
        "selected": true,
        "wealth": {
          "bank": 125000000.0,
          "purse": 4250000.5,
          "equipment": [],
          "armor": []
        },
        "skills": {
          "farming": {"level": 60, "xp": 111234567.0}
        }
      },
      "unavailableFields": []
    }
  ]
}

Example GET /api/v2/lowestbin response:

{
  "lastUpdated": 1700000000000,
  "products": {
    "HYPERION": {
      "price": 98000000.0,
      "auctioneerUuid": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "item_name": "Hyperion",
      "avg7d": 97500000,
      "avg30d": 96000000
    },
    "TRUE_ESSENCE": {
      "price": 23437.5,
      "auctioneerUuid": "cccccccccccccccccccccccccccccccc",
      "item_name": "True Essence",
      "avg7d": 22850,
      "avg30d": 22120
    }
  }
}

API documentation:

  • /docs, /redoc, and /openapi.json are intended for local development and controlled internal use
  • the combined production app disables them by default when TRAINING_HUB_ENV=production
  • the standalone MarketGuard app can disable them explicitly with MARKETGUARD_API_DOCS_ENABLED=false

The client upload API is meant for non-browser clients such as a Minecraft mod. The preferred mod path is the anonymous endpoint authenticated by a normalized local clientId plus server-verified SHA-256 headers over the raw NDJSON payload. Browser-backed API use can still rely on the normal external web sign-in session, but password-based API login is no longer part of the supported surface. Do not add custom application-layer crypto on top of TLS without a concrete threat model.

Example anonymous upload:

curl -sS https://scamscreener.creepans.net/api/v1/client/uploads/anonymous \
  -X POST \
  -H "Content-Type: application/x-ndjson" \
  -H "X-ScamScreener-Filename: training-cases-v2.jsonl" \
  -H "X-ScamScreener-Client-Id: your-normalized-client-id" \
  -H "X-ScamScreener-Payload-Sha256: YOUR_PAYLOAD_SHA256" \
  -H "X-ScamScreener-Handshake-Sha256: YOUR_HANDSHAKE_SHA256" \
  --data-binary @training-cases-v2.jsonl

Notes:

  • The anonymous mod endpoint is POST /api/v1/client/uploads/anonymous.
  • Users can manually link already-known mod clientId values from Account -> Clients; once linked, historical uploads for that client ID appear in the dashboard.
  • The server recalculates X-ScamScreener-Payload-Sha256 and X-ScamScreener-Handshake-Sha256; mismatches are rejected with 400.
  • /api/v1/client/uploads accepts the raw JSONL body and applies the same validation, quotas, deduplication, and audit logging as the dashboard upload form.
  • /api/v1/client/uploads/anonymous accepts the raw JSONL body and applies the same validation, quotas, deduplication, and audit logging without requiring a web login.
  • Full mod-side integration guidance: MINECRAFT_MOD_INTEGRATION.md

License

This repository is licensed under the GNU Affero General Public License v3.0 only. SPDX identifier: AGPL-3.0-only

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages