Skip to content

API reference · API keys

Report the site's health ​

  • Method: POST
  • Path: /v1/me/sites/{site_id}/health
  • Operation ID: reportSiteHealth
  • Tags: Connected sites

Versions, when the plugin last finished a sync, and how many sync errors it counted since its last report. Shown in Connected sites in show.fm.

Scope: sites:write.

Make a request ​

Set these environment variables before running a sample. Each language reads the same values; no identifier needs replacing inside the code.

VariableValue to supply
SHOWFM_API_KEYYour API key. Keep it on your server.
SITE_IDYour site id, returned by the code exchange or WP-CLI registration.
ADMIN_URLYour WordPress admin address, on the same origin and below the home path of SITE_URL, containing /wp-admin/. Optional in the API; these examples supply it.

Samples run on your server: curl 7.76+, Node.js 22+ (TypeScript via your TypeScript runner), Python 3, or PHP 8 with the cURL extension. Never put your API key in browser code.

bash
: "${SHOWFM_API_KEY:?Set SHOWFM_API_KEY in your environment}"
: "${SITE_ID:?Set SITE_ID in your environment}"
: "${ADMIN_URL:?Set ADMIN_URL in your environment}"

curl --fail-with-body --silent --show-error --request POST \
  "https://api.show.fm/v1/me/sites/${SITE_ID}/health" \
  --header "Authorization: Bearer ${SHOWFM_API_KEY}" \
  --header "Content-Type: application/json" \
  --data "{\"admin_url\":\"${ADMIN_URL}\",\"plugin_version\":\"1.0.0\",\"wp_version\":\"6.8.1\",\"php_version\":\"8.3\",\"last_sync_at\":\"2026-10-07T09:00:00Z\",\"sync_error_count\":0}"
ts
function env(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} in your environment`);
  return value;
}

async function main() {
  const url = new URL(`https://api.show.fm/v1/me/sites/${encodeURIComponent(env("SITE_ID"))}/health`);

  const response = await fetch(url, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${env("SHOWFM_API_KEY")}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      admin_url: env("ADMIN_URL"),
      plugin_version: "1.0.0",
      wp_version: "6.8.1",
      php_version: "8.3",
      last_sync_at: "2026-10-07T09:00:00Z",
      sync_error_count: 0
    }),
    signal: AbortSignal.timeout(30_000)
  });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }
  console.log(JSON.stringify(await response.json(), null, 2));
}

main().catch(error => {
  console.error(error);
  process.exitCode = 1;
});
js
function env(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} in your environment`);
  return value;
}

async function main() {
  const url = new URL(`https://api.show.fm/v1/me/sites/${encodeURIComponent(env("SITE_ID"))}/health`);

  const response = await fetch(url, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${env("SHOWFM_API_KEY")}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      admin_url: env("ADMIN_URL"),
      plugin_version: "1.0.0",
      wp_version: "6.8.1",
      php_version: "8.3",
      last_sync_at: "2026-10-07T09:00:00Z",
      sync_error_count: 0
    }),
    signal: AbortSignal.timeout(30_000)
  });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }
  console.log(JSON.stringify(await response.json(), null, 2));
}

main().catch(error => {
  console.error(error);
  process.exitCode = 1;
});
python
import os
import json
from urllib.parse import quote, urlencode
from urllib.request import Request, urlopen
from urllib.error import HTTPError

url = f'https://api.show.fm/v1/me/sites/{quote(os.environ["SITE_ID"], safe="")}/health'
body = json.dumps({
    "admin_url": os.environ["ADMIN_URL"],
    "plugin_version": "1.0.0",
    "wp_version": "6.8.1",
    "php_version": "8.3",
    "last_sync_at": "2026-10-07T09:00:00Z",
    "sync_error_count": 0,
}).encode()
request = Request(url, data=body, method="POST", headers={
    "Authorization": "Bearer " + os.environ["SHOWFM_API_KEY"],
    "Content-Type": "application/json"
})
try:
    with urlopen(request, timeout=30) as response:
        print(json.dumps(json.load(response), indent=2))
except HTTPError as error:
    raise RuntimeError(f"HTTP {error.code}: {error.read().decode()}") from error
php
<?php
function requiredEnv(string $name): string {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name in your environment");
    }
    return $value;
}

$url = "https://api.show.fm" . "/v1/me/sites/" . rawurlencode(requiredEnv("SITE_ID")) . "/health";
$curl = curl_init($url);
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer " . requiredEnv("SHOWFM_API_KEY"), "Content-Type: application/json"],
    CURLOPT_POSTFIELDS => json_encode([
        "admin_url" => requiredEnv("ADMIN_URL"),
        "plugin_version" => "1.0.0",
        "wp_version" => "6.8.1",
        "php_version" => "8.3",
        "last_sync_at" => "2026-10-07T09:00:00Z",
        "sync_error_count" => 0,
    ], JSON_THROW_ON_ERROR),
]);
$body = curl_exec($curl);
if ($body === false) {
    throw new RuntimeException(curl_error($curl));
}
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($status < 200 || $status >= 300) {
    throw new RuntimeException("HTTP $status: $body");
}
echo json_encode(json_decode($body, false, 512, JSON_THROW_ON_ERROR), JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR) . PHP_EOL;

Base URL ​

  • https://api.show.fm

Authentication ​

  • apiKey: HTTP bearer

    An API key from Settings → API keys. showfm_live_ in production.

Path parameters ​

  • site_id (required): string, format: uuid

    Your site's id (UUID), from the code exchange or WP-CLI registration. Only the calling site key's own site.

Request body ​

Required: true

Content type: application/json

schema: SiteHealthRequest, no additional properties

  • php_version (required): string, pattern: ^[0-9A-Za-z.+_ -]{1,32}$

    Up to 32 letters, digits, dots, dashes, underscores, plus signs and spaces.

  • plugin_version (required): string, pattern: ^[0-9A-Za-z.+_ -]{1,32}$

    Up to 32 letters, digits, dots, dashes, underscores, plus signs and spaces.

  • wp_version (required): string, pattern: ^[0-9A-Za-z.+_ -]{1,32}$

    Up to 32 letters, digits, dots, dashes, underscores, plus signs and spaces.

  • admin_url: string, minLength: 1, maxLength: 2048

    Optional WordPress admin address for reconnect links. Must be https, on the same origin as site_url, under its home path and contain /wp-admin/, with no credentials, port or fragment. Stored as the plugin settings address. Omit to preserve an existing address; older connections without one use the site home path plus /wp-admin/.

  • last_sync_at: string | null, format: date-time, pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$

    When the plugin last finished a sync.

  • sync_error_count: integer, minimum: 0, maximum: 1000000

    Sync errors since the last report. Default 0.

Responses ​

Browse the documented response statuses, headers and body fields.

200 OK ​

Response headers ​

  • RateLimit-Policy

    The bucket that applied, e.g. "account";q=60;w=60.

    string

  • RateLimit

    Requests left and seconds to reset, e.g. "account";r=59;t=42.

    string

Response body ​

Content type: application/json

no additional properties

400, 401, 403, 404, 500, 503 ​

  • 400 invalid_request: a bad body (see error.details), or a key sent in the URL.
  • 401 unauthorized (no Bearer key) or invalid_api_key.
  • 403 insufficient_scope, forbidden (role or team-key setting) or plan_upgrade_required.
  • 404 not_found: the key cannot reach this resource.
  • 500 internal_error. Retry; quote X-Request-Id if it persists.
  • 503 service_unavailable. Retry shortly.

Response body ​

Content type: application/json

schema: Error, no additional properties

  • error (required): object, no additional properties
    • code (required): string, possible values: "invalid_request", "not_found", "unavailable", "unauthorized", "invalid_api_key", "insufficient_scope", "forbidden", "plan_upgrade_required", "rate_limited", "service_unavailable", "internal_error", "not_implemented"

    • message (required): string

    • details: array

      Items:

      no additional properties

      • field (required): string

      • message (required): string

      • reason: string

        A stable reason a client may branch on, for example outside_retention.

    • docs_url: string

    • request_id: string

429 rate_limited. Wait for Retry-After seconds. ​

Response headers ​

  • Retry-After

    integer

  • RateLimit-Policy

    The bucket that applied, e.g. "account";q=60;w=60.

    string

  • RateLimit

    Requests left and seconds to reset, e.g. "account";r=59;t=42.

    string

Response body ​

Content type: application/json

Uses the shared Error schema. View response fields.

Was this page helpful?