Skip to main content
YUCTS Status

Install YUCTS Status

Add YUCTS Status to your home screen for quick access. The latest status you loaded stays available offline.

On iPhone and iPad (Safari)

  1. Tap the Share button in the toolbar.
  2. Choose “Add to Home Screen”.
  3. Tap “Add”.

On Mac (Safari)

Choose File › Add to Dock (macOS Sonoma or later).

On Chrome, Edge and Android

Use the install button below, or the install icon in the address bar / browser menu.

If your browser cannot install web apps, bookmark this page instead.

Developers & API

A public REST API for status, incidents and maintenance — plus an embeddable widget, badges, feeds and calendars.

Getting started

All public endpoints are plain HTTPS GET requests that return JSON. No key is needed. Try the system status:

curl -s "https://status.yucts.com/api/v2/status?locale=en"

# Conditional request — 304 Not Modified when nothing changed
curl -s -i "https://status.yucts.com/api/v2/services?locale=ja" -H 'If-None-Match: "<etag from the previous response>"'

API versions

  • v1 (/api/*) is the stable 1.x API used by existing apps and widgets. It is frozen: fields are never removed or renamed.
  • v2 (/api/v2/*) is the current API: consistent envelopes, error codes, request ids, ETags, cursor pagination and seven languages.

Deprecation policy

Breaking changes only ship under a new version path. A deprecated version stays available for at least 12 months and announces itself with Deprecation and Sunset headers before removal.

Authentication

Every endpoint on this page is public and read-only: no authentication is needed. Administrative endpoints are not part of this documentation — signed-in administrators find their reference in the admin console (API reference). Never put credentials in a URL.

Endpoints

The complete reference, generated from the same code that serves the API, is available as an OpenAPI 3.1 document. /openapi.json

Loading the API reference…

Errors

v2 errors share one shape. Use the code (not the message) in your logic and include the request id when reporting a problem.

{
  "error": {
    "code": "not_found",
    "message": "Incident not found.",
    "status": 404,
    "request_id": "c0ffee00-…"
  }
}

Rate limits

Requests that miss the edge cache are limited per client IP (600 per minute by default). When limited you receive HTTP 429 with a Retry-After header.

Caching

Public responses are cacheable for 30 seconds (v1: 60 seconds) and carry an ETag — send it back in If-None-Match to get 304 Not Modified. Personal responses such as locale detection are never cached.

Languages

Pass locale=zh-TW, zh-HK, zh-CN, en, ja, ko or vi. Missing translations fall back to Japanese; every text field reports the language actually served in its *_locale field.

Webhooks

Administrators can send incident and maintenance events to HTTPS endpoints (generic JSON, Discord or Slack). Every request is signed:

X-Yucts-Signature: t=1767225600,v1=5f2c…
X-Yucts-Event: incident.created
X-Yucts-Delivery: 42

Compute HMAC-SHA256 over "<t>.<raw body>" with your webhook secret and compare it to v1 in constant time. Reject timestamps older than five minutes and de-duplicate on X-Yucts-Delivery.

import { createHmac, timingSafeEqual } from 'node:crypto';

// header = X-Yucts-Signature, rawBody = the exact request body string
export function verifyYuctsSignature(rawBody, header, secret) {
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header ?? '');
  if (!m) return false;
  const [, t, sig] = m;
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; // replay window
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  return timingSafeEqual(Buffer.from(sig, 'hex'), expected);
}

Code examples

JavaScript
const res = await fetch('https://status.yucts.com/api/v2/status?locale=en');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { data } = await res.json();
console.log(data.status);             // "operational" | "degraded" | "partial_outage" | ...
console.log(data.active_incidents);   // ongoing incidents with their latest update
TypeScript
type ServiceStatus = 'operational' | 'degraded' | 'down' | 'maintenance' | 'unknown';
interface ServiceSummary {
  id: number;
  name: string;
  status: ServiceStatus;
  uptime: { h24: number | null; d30: number | null; d90: number | null }; // null = no data
}

async function services(locale = 'ja'): Promise<ServiceSummary[]> {
  const res = await fetch(`https://status.yucts.com/api/v2/services?locale=${locale}`);
  if (!res.ok) {
    const { error } = await res.json(); // { code, message, status, request_id }
    throw new Error(`${error.code} (${error.request_id})`);
  }
  return (await res.json()).data;
}
Swift / SwiftUI
struct Envelope<T: Decodable>: Decodable { let data: T }
struct SystemStatus: Decodable {
    let status: String
    let counts: Counts
    struct Counts: Decodable { let total, operational, degraded, down, maintenance, unknown: Int }
}

func fetchStatus(locale: String = "zh-TW") async throws -> SystemStatus {
    var url = URLComponents(string: "https://status.yucts.com/api/v2/status")!
    url.queryItems = [URLQueryItem(name: "locale", value: locale)]
    let (data, response) = try await URLSession.shared.data(from: url.url!)
    guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw URLError(.badServerResponse) }
    return try JSONDecoder().decode(Envelope<SystemStatus>.self, from: data).data
}
PHP (WordPress)
<?php
// WordPress: cache the status for 60 seconds with a transient.
function yucts_status() {
    $cached = get_transient('yucts_status');
    if ($cached !== false) return $cached;
    $res = wp_remote_get('https://status.yucts.com/api/v2/status?locale=en', ['timeout' => 5]);
    if (is_wp_error($res) || wp_remote_retrieve_response_code($res) !== 200) return null;
    $body = json_decode(wp_remote_retrieve_body($res), true);
    set_transient('yucts_status', $body['data'], 60);
    return $body['data'];
}

Step-by-step guides for Swift/SwiftUI, JavaScript/TypeScript, WordPress and XenForo are in the repository documentation.

Embed widget

Show live status on any page (XenForo, WordPress, plain HTML). The 1.x widget keeps working unchanged; the v2 widget adds the new design, isolation from page styles and seven languages.

<!-- 2.0 widget: same attributes, Shadow DOM isolation, 7 languages -->
<div class="yucts-status" data-view="overview" data-locale="zh-TW"></div>
<script src="https://status.yucts.com/embed/v2.js" defer></script>
<!-- 1.x widget (unchanged) -->
<div id="yucts-status"></div>
<script src="https://status.yucts.com/embed.js" defer></script>

Changelog

  • 2.0 — API v2, OpenAPI 3.1, Vietnamese for all content, embed v2, badges, feeds, iCalendar, exports, OpenMetrics (each behind a feature switch).
  • 1.x — /api/overview, /api/status, /api/incidents, /api/slo, /api/maintenance, /api/geo, embed.js.