Updates Portal API

The Updates Portal exposes a small public JSON API so you can poll status, ingest changelog entries, watch the roadmap, and check known issues from your own systems. No authentication required.

Base URL

https://updates.foura.ai

Service Status

GET /api/v1/status

Returns the live operational status of every FourA service, plus active and recent incidents. Server-side cached for 15 seconds, so polling more often than that returns the same payload.

curl https://updates.foura.ai/api/v1/status
{
  "overall": "operational",
  "services": [
    {
      "slug": "api",
      "name": "API",
      "description": "...",
      "status": "operational",
      "daily": [
        { "date": "2026-05-19", "status": "operational", "major_outage_minutes": 0, "partial_outage_minutes": 0, "degraded_minutes": 0, "internal_degraded_minutes": 0 }
      ]
    }
  ],
  "active_incidents": [],
  "recent_incidents": [
    { "id": "...", "service_slug": "api", "service_name": "API", "impact": "minor", "started_at": "...", "resolved_at": "..." }
  ]
}
Top-level field Type Description
overall string operational if every service is healthy, otherwise one of the service status values
services array One entry per monitored service with slug, name, description, current status, and daily history (up to 90 days)
active_incidents array Incidents that are currently open
recent_incidents array Resolved incidents from the last 14 days

Service status values: operational, degraded, partial_outage, major_outage, maintenance.

Incident impact values: minor (degraded performance), major (partial disruption), critical (service disruption).

Polling pattern

Use this endpoint to wire FourA status into your own dashboard or paging system.

import requests

def check_foura():
    r = requests.get("https://updates.foura.ai/api/v1/status", timeout=5)
    r.raise_for_status()
    data = r.json()
    if data["overall"] != "operational":
        # Page on-call, post to Slack, flip a feature flag, etc.
        for svc in data["services"]:
            if svc["status"] != "operational":
                print(f"{svc['name']}: {svc['status']}")
    return data

The legacy GET /api/status returns 410 Gone and points callers here.

Changelog

GET /api/changelog

Returns published changelog entries in reverse chronological order.

curl "https://updates.foura.ai/api/changelog?limit=20"

Query parameters:

Parameter Type Default Description
page integer 1 1-indexed page number
limit integer 20 Entries per page (max 50)
category string - Filter to new, improved, or fixed
{
  "entries": [
    {
      "id": 42,
      "title": "...",
      "body": "Markdown body",
      "category": "new",
      "tags": "[\"api\",\"dashboard\"]",
      "published": 1,
      "published_at": "2026-05-19T12:00:00Z",
      "created_at": "2026-05-19 11:42:08",
      "updated_at": "2026-05-19 11:44:31"
    }
  ],
  "total": 137,
  "page": 1,
  "limit": 20
}
Field Type Description
id integer Entry ID
title string Entry title
body string Markdown body
category string new, improved, or fixed
tags string A JSON array encoded as a string. Parse it before use: json.loads(entry["tags"]).
published integer Always 1 here. The endpoint only returns published entries.
published_at string ISO 8601 with a Z suffix
created_at string YYYY-MM-DD HH:MM:SS, UTC, with no zone marker
updated_at string Same format as created_at

The two timestamp formats are different on purpose: published_at is the editorial date and carries a zone, while created_at and updated_at are storage timestamps. Both are UTC. A parser that assumes one format for all three will throw on the other two.

RSS

The full changelog (30 most recent entries) is also published as RSS at:

https://updates.foura.ai/rss

Subscribe in Feedly, Miniflux, Thunderbird, or any reader. The feed body matches the changelog body, including markdown rendered to HTML.

Roadmap

GET /api/roadmap

Returns every published roadmap item, sorted by vote count then creation time.

curl https://updates.foura.ai/api/roadmap
{
  "items": [
    {
      "id": 12,
      "title": "...",
      "description": "...",
      "status": "planned",
      "category": "developer-experience",
      "votes": 23,
      "target_date": "Q3 2026",
      "completed_at": null,
      "created_at": "2026-03-30 09:32:47"
    }
  ]
}

Item status values: planned, in_progress, done, cancelled. The board at updates.foura.ai/roadmap renders three columns, so an item set to cancelled reaches you through this endpoint and never appears on the page.

category is a lowercase slug, not the label the page prints. Slugs in use today: api, infrastructure, developer-experience, dashboard, billing, analytics, authentication. Treat the list as open, since a new item can introduce a new one.

target_date is free text ("Q3 2026"), not a date. completed_at is null until an item ships. Both completed_at and created_at use YYYY-MM-DD HH:MM:SS in UTC.

Voting

POST /api/roadmap/:id/vote

Toggles a vote on a single roadmap item. Votes are anonymous and tied to the caller's IP + User-Agent. Calling again removes the vote.

curl -X POST https://updates.foura.ai/api/roadmap/12/vote
{ "votes": 24, "voted": true }

voted reports the post-call state: true if your vote was added, false if it was removed.

Known Issues

GET /api/issues

Returns issues tracked by FourA support.

curl "https://updates.foura.ai/api/issues?tab=open"

Query parameters:

Parameter Type Default Description
tab string open open for active issues, resolved for resolved/closed
{
  "issues": [
    {
      "id": 5,
      "title": "...",
      "body": "Markdown description",
      "severity": "medium",
      "status": "investigating",
      "service_id": 3,
      "resolution": "",
      "opened_at": "2026-05-18T09:00:00Z",
      "resolved_at": null,
      "updated_at": "2026-05-18 09:04:11",
      "service_name": "API"
    }
  ]
}
Field Type Description
id integer Issue ID
title string Short summary
body string Markdown description
severity string low, medium, high, or critical
status string open, investigating, resolved, or closed
service_id integer or null Numeric ID of the affected service. null when the issue isn't tied to one.
service_name string or null The service's display name, resolved for you. Read this instead of mapping service_id yourself.
resolution string How it was fixed. Empty string while the issue is open.
opened_at string ISO 8601 with a Z suffix
resolved_at string or null ISO 8601 with a Z suffix, null while open
updated_at string YYYY-MM-DD HH:MM:SS, UTC, with no zone marker

service_id is a numeric foreign key, not the slug you see on the status page. Match issues to services by service_name.

The resolved tab returns the 30 most recently resolved issues and stops there. The open tab returns all of them.

Notes

  • All endpoints are public. There's no API key required, but expect generous rate limiting per source IP.
  • Responses are JSON over HTTPS. Roadmap and issues take no paging parameters. The one cap is ?tab=resolved on issues, which returns 30 rows.
  • For free-text or raw HTML versions of the changelog, use the /rss feed instead of /api/changelog.
Last updated: August 20, 2026