Market Spread Radar — HTTP API

Stable, JSON-based API powering the web app. This page documents discovered/used endpoints in the codebase.

Contents

Auth model & cookies

Rate limiting is role-aware (guest/user/vip/admin). Some auth endpoints are open to allow flows.

Errors

Errors are JSON with HTTP status codes. Common fields: error, optional hint, sometimes message_key.

{
  "error": "invalid_credentials",
  "hint": "Check username/email and password"
}

Authentication

POST /api/v1/auth/register.php

Create an account. Sends a verification email if mail is configured.

Body (JSON){ "username": "alice", "email": "a@ex.com", "password": "secret" }
200{ "ok": true }
409{ "error": "user_exists" }
curl -X POST https://marketspreadradar.com/api/v1/auth/register.php \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","email":"a@ex.com","password":"secret"}'

POST /api/v1/auth/login.php

Authenticates a user. Creates a PHP session and, if remember is true, an HttpOnly REMEMBER cookie.

Body (JSON){ "identifier": "alice or email", "password": "***", "remember": true }
200
{
  "ok": true,
  "user": { "id": 1, "username": "alice", "email": "a@ex.com", "role": "user" }
}
401{ "error": "invalid_credentials" }
curl -i -X POST https://marketspreadradar.com/api/v1/auth/login.php \
  -H "Content-Type: application/json" \
  -d '{"identifier":"alice","password":"secret","remember":true}'

GET /api/v1/auth/me.php

Returns session/remember-resolved user. If not authenticated, returns { "role": "guest" }.

AuthCookie PHPSESSID or REMEMBER, or Authorization: Bearer.
200{ "id":1, "username":"alice", "role":"user", "created_at":"...", "email_verified_at":"..." } or { "role":"guest" }
curl -b "PHPSESSID=..." https://marketspreadradar.com/api/v1/auth/me.php

POST /api/v1/auth/logout.php

Destroys the session and deletes the persistent REMEMBER token if present.

curl -X POST -b "PHPSESSID=..." https://marketspreadradar.com/api/v1/auth/logout.php

POST /api/v1/auth/resend_verification.php

Re-sends an email verification link to the authenticated user (if not yet verified).

curl -X POST -b "PHPSESSID=..." https://marketspreadradar.com/api/v1/auth/resend_verification.php

POST /api/v1/auth/reset_request.php

Sends a password reset link to a known account.

Body{ "identifier": "alice or email" }
200{ "ok": true } (generic response)

POST /api/v1/auth/reset_apply.php

Consumes a reset token and sets a new password.

Body{ "token": "...", "password": "newPassword" }
200{ "ok": true }
4xx{ "error": "invalid_or_expired" }

GET /api/v1/auth/verify_email.php if enabled

Verifies the email from a link: /api/v1/auth/verify_email.php?token=.... Redirects back to UI with status.

Profile

GET /api/v1/profile.php

Returns the authenticated user’s profile fields and (optionally) an API token summary.

{
  "user": {
    "id":1,"username":"alice","email":"a@ex.com","role":"user",
    "firstname":"...","lastname":"...","address":"...","city":"...",
    "zipcode":"...","country":"..."
  },
  "token": { "present": true, "full": "****" }  // when available
}

POST /api/v1/profile.php

Updates profile fields; password is optional and only updated if provided.

BodyAny of: firstname, lastname, email, address, city, zipcode, country, password (JSON)
200{ "ok": true }

POST /api/v1/profile_avatar.php

Uploads/replaces the user’s avatar.

Content-Typemultipart/form-data
Fieldsavatar (PNG/JPG/GIF/WebP)
200{ "ok": true, "url": "/images/avatars/<id>.png?ts=..." }
curl -X POST -b "PHPSESSID=..." \
  -F "avatar=@/path/to/avatar.png" \
  https://marketspreadradar.com/api/v1/profile_avatar.php

Traffic Analytics

POST /api/v1/metrics/view.php

Registers a page view for an arbitrary path (server normalizes common cases).

Body{ "path": "/some/path" }
200{ "ok": true, "today": 123 }

GET /api/v1/metrics/views_series.php

Returns daily view counts for a path in a date window (UTC).

Query?path=/&from=YYYY-MM-DD&to=YYYY-MM-DD
200
{
  "total": 4567,
  "points": [ { "day": "2025-09-01", "views": 123 }, ... ]
}
curl "https://marketspreadradar.com/api/v1/metrics/views_series.php?path=/&from=2025-09-01&to=2025-09-30"

Rate Limits

Role-aware buckets are enforced (see role_policies table). Defaults:

GET /api/v1/rate_status.php

Returns current counters for the caller.

{
  "role": "user",
  "buckets": [
    { "bucket":"api_min","limit_count":120,"window_seconds":60,
      "used": 12, "remaining":108, "reset_at":"2025-09-14T12:34:56Z" }
  ]
}

UI helpers

On 429, JSON may include next_step, hint_key, url for helpful UI banners.

Admin — Mail Center

POST /api/v1/admin/mail_send.php

Sends an email to a single recipient (admin-only).

Body{ "to": "user@example.com", "subject": "Hello", "body": "..." }
200{ "ok": true }

POST /api/v1/admin/mail_enqueue.php

Enqueues a mass mailing (admin-only). Optional role targeting.

Body{ "subject":"News", "body":"...", "role":"user" }
200{ "ok": true, "queued": 123 }

Internationalization (client)

Client loads strings from /lang/<code>.json; persists prefs_lang, prefs_theme, prefs_currency.

Quick examples

# Login (persist session + remember)
curl -c cookies.txt -X POST https://marketspreadradar.com/api/v1/auth/login.php \
  -H "Content-Type: application/json" \
  -d '{"identifier":"alice","password":"secret","remember":true}'

# Check identity
curl -b cookies.txt https://marketspreadradar.com/api/v1/auth/me.php

# Track a page view
curl -b cookies.txt -X POST https://marketspreadradar.com/api/v1/metrics/view.php \
  -H "Content-Type: application/json" -d '{"path":"/"}'

# Fetch daily view series
curl -b cookies.txt "https://marketspreadradar.com/api/v1/metrics/views_series.php?path=/&from=2025-09-01&to=2025-09-30"

Changelog (this document)