Skip to main content
These endpoints are public. No Bearer token, no wallet signing, no x-user-address header. Safe to call from any client, including browser apps and on-chain tooling. Both endpoints set Cache-Control: public so intermediaries (CDNs, browser caches) can serve them. The backend also keeps an in-memory cache (around 60s for price, 10s for status) so bursty traffic does not hit upstream sources.

GET /api/price/bch-usd

Latest BCH/USD reading from a Bitcoin Cash native price oracle, with a CoinGecko fallback.

Sources

PrioritySourceNotes
1General Protocols oracle relay at oracles.generalprotocols.comSigned price messages, the USD/BCH pubkey is 02d09db08af1ff4e8453919cc866a4be427d7bfe18f2c05e5444c196fcf6fd2818.
2CoinGecko simple/priceFree, no auth. Used only when the oracle path fails or times out.
Each source has a 6s timeout. Results are cached in memory for 60s, after which the next request refreshes from the oracle. When both sources fail, the cache is not poisoned, the endpoint returns 502 price_unavailable and the next call retries.

Request

GET /api/price/bch-usd
No query parameters. No headers required.

Response

{
  "usd": 423.18,
  "source": "oracle",
  "oraclePubkey": "02d09db08af1ff4e8453919cc866a4be427d7bfe18f2c05e5444c196fcf6fd2818",
  "messageTimestamp": 1717900800,
  "signedMessageHex": "00a4...",
  "signatureHex": "3045...",
  "updatedAt": 1717900800123,
  "cachedFor": 59000
}
FieldTypeDescription
usdnumberUSD per 1 BCH.
source"oracle" | "coingecko"Which source produced this reading.
oraclePubkeystringCompressed secp256k1 pubkey of the price oracle. Present when source === "oracle".
messageTimestampnumberOracle message timestamp in unix seconds. Present when source === "oracle".
signedMessageHexstringHex-encoded oracle message. Present when source === "oracle".
signatureHexstringHex-encoded oracle signature over signedMessageHex. Present when source === "oracle".
updatedAtnumberServer unix milliseconds when this reading was fetched.
cachedFornumberMilliseconds until the in-memory cache expires.
When source === "oracle", the response includes the signed message hex and signature, so integrators can re-verify the reading on chain (for example via @generalprotocols/price-oracle) instead of trusting the relay or the FlowGuard backend. The oracle message layout is little-endian, 32-bit fields:
BytesField
[0..4]messageTimestamp (unix seconds)
[4..8]messageSequence (monotonic per oracle)
[8..12]priceSequence (price-update counter)
[12..16]priceValue (price in cents, USD cents per BCH)

Errors

{
  "error": "price_unavailable",
  "message": "Could not retrieve a BCH/USD reading from any source. Please retry shortly."
}
Returned as HTTP 502 when both the oracle relay and CoinGecko fail or time out.

Example

curl -s https://api.flowguard.cash/api/price/bch-usd | jq

GET /api/status

Component-health snapshot that drives the public Status page at flowguard.cash/status. No process internals, no internal URLs, no raw row counts. Safe to expose to the open internet. The response is cached in memory for 10s and served with Cache-Control: public, max-age=10.

Request

GET /api/status
No query parameters. No headers required.

Response

{
  "updatedAt": "2026-06-11T12:00:00.000Z",
  "refreshIntervalSeconds": 30,
  "overall": "operational",
  "network": {
    "name": "mainnet",
    "isMainnet": true,
    "displayName": "BCH Mainnet",
    "testnetWarning": false
  },
  "chain": {
    "height": 901234,
    "ageSeconds": null,
    "latencyMs": 312,
    "recentHeights": [901223, 901224, 901225, 901226, 901227, 901228, 901229, 901230, 901231, 901232, 901233, 901234],
    "error": null
  },
  "components": [
    {
      "id": "api",
      "name": "API",
      "group": "API",
      "status": "operational",
      "description": "api.flowguard.cash - backend REST surface",
      "latencyMs": null,
      "uptime90d": null,
      "lastIncidentAt": null
    }
  ],
  "summary": {
    "operational": 9,
    "degraded": 0,
    "outage": 0
  },
  "incidents": []
}

Top-level fields

FieldTypeDescription
updatedAtstring (ISO-8601)When this snapshot was built.
refreshIntervalSecondsnumberSuggested polling interval for clients.
overallHealthRoll-up health, see below.
networkobjectWhich BCH network this deployment targets.
chainobjectChain tip probe via Electrum, plus a 12-block sparkline.
componentsPublicComponent[]Per-component health, see below.
summaryobjectCounts of operational, degraded, and outage components.
incidentsarrayRecent incidents. Empty until the incidents store is wired up.
overall and per-component status use distinct vocabularies:
overallWhen
operationalAll components green.
degradedOne or more components degraded, none in outage.
partial_outageExactly one component in outage.
major_outageTwo or more components in outage.
maintenanceAt least one component in maintenance, none worse.
unknownNo components reported.
Component statusMeaning
operationalHealthy.
degradedReachable but unhealthy, or upstream reported degraded / manual / unknown.
outageUnreachable, HTTP 5xx, or upstream reported critical / unreachable.
maintenanceComponent is in a planned maintenance window.
unknownNo probe yet, or upstream reported not_configured.

Components

The components array always includes these entries, in this order:
idgroupWhat is probed
apiAPIThe backend REST surface itself. Reported operational if this response was served.
frontend_appFrontendHEAD https://app.flowguard.cash.
docsDocsHEAD https://docs.flowguard.cash.
explorerExplorerHEAD https://explorer.flowguard.cash.
bch_networkBCH NetworkBCH chain tip via Electrum (mainnet or chipnet).
databaseDatabaseSELECT 1 against the primary application database.
supabase_vaultDatabaseManaged secret storage. Reported unknown until a server-side probe exists.
indexerWorkersCovenant address indexing worker, sanitized from INDEXER_STATUS_URL.
executorWorkersNot currently operated. Recipients claim via UI. Will return operational when a hosted executor exists.
blockchain_monitorWorkersIn-process vault balance refresher. Reported unknown until liveness instrumentation lands.
transaction_monitorWorkersOn-chain transaction confirmation watcher. Reported unknown until liveness instrumentation lands.
cycle_unlock_schedulerWorkersGovernance cycle unlock scheduler. Reported unknown until liveness instrumentation lands.
Each PublicComponent has the shape:
FieldTypeDescription
idstringStable identifier for the component.
namestringDisplay name.
group"API" | "Frontend" | "Docs" | "Explorer" | "BCH Network" | "Workers" | "Database"UI grouping.
statusComponentStatusPer-component health, see vocabulary above.
descriptionstringShort, public-safe description.
latencyMsnumber | nullProbe latency in milliseconds, when measurable.
uptime90dnumber | null90-day uptime estimate. null until the component samples store exists.
lastIncidentAtstring | nullISO timestamp of the most recent incident affecting this component.
Remote worker payloads (indexer) are sanitized before re-emission. Only the upstream service.status field is mapped through normalizeStatus. Hostnames, queue depths, signing-key flags, and other internals are dropped.

Network and chain

{
  "network": {
    "name": "chipnet",
    "isMainnet": false,
    "displayName": "BCH Chipnet",
    "testnetWarning": true
  },
  "chain": {
    "height": 234567,
    "ageSeconds": null,
    "latencyMs": 412,
    "recentHeights": [234556, 234557, 234558, 234559, 234560, 234561, 234562, 234563, 234564, 234565, 234566, 234567],
    "error": null
  }
}
FieldTypeDescription
network.name"mainnet" | "chipnet"Which BCH network this deployment targets, resolved from BCH_NETWORK or NETWORK.
network.isMainnetbooleanConvenience flag.
network.displayNamestringHuman-readable name, for example BCH Mainnet.
network.testnetWarningbooleantrue on chipnet. Surface a banner, chipnet is not for production traffic.
chain.heightnumber | nullLatest block height, or null if the Electrum probe failed.
chain.ageSecondsnumber | nullAge of the tip in seconds. Reserved for a future per-block timestamp probe.
chain.latencyMsnumber | nullElectrum probe latency.
chain.recentHeightsnumber[]Synthetic 12-point sparkline, newest last. Real per-block timestamps will move to /api/status/network/bch in a later phase.
chain.errorstring | nullProbe error message, when applicable.

Errors

{
  "updatedAt": "2026-06-11T12:00:00.000Z",
  "refreshIntervalSeconds": 30,
  "overall": "unknown",
  "error": "Failed to build public status"
}
Returned as HTTP 500 if the status snapshot cannot be built at all. Individual component failures are reflected as outage or unknown inside components, not as a top-level error.

Example

curl -s https://api.flowguard.cash/api/status | jq '.overall, .summary'

Status page

The marketing site renders this payload at flowguard.cash/status. The page polls /api/status on the interval suggested by refreshIntervalSeconds.

GET /api/status/incidents

Placeholder feed for the public Status page. Returns an empty list until the incidents store lands.

Request

GET /api/status/incidents

Response

{
  "incidents": [],
  "note": "Incidents API not yet backed by a persistent store. Returns an empty list."
}
Cached with Cache-Control: public, max-age=60.