Integration health: one board for every connection

Embed
Preview of the card
<a href="https://forumulate.com/guides/integration-health"><img src="https://forumulate.com/guides/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/36aa4df0-1e95-4cef-8ae9-795169441345/pages/63386ce8-c4dd-40cb-aacd-56126daa6740/social-card.svg?v=3e7ae33eec8b" alt="Integration health: one board for every connection" width="600" height="315"></a>

Once a product is wired in — domains, reader sign-in, consent, the rights executor, connectors, a status heartbeat, webhooks — each piece can break on its own, and each has its own panel. GET /orgs/{orgId}/integration-health reads all of them at once and says, for each, whether it works and what to do if it does not. Every link a check's docs field gives lands on the guide for that piece; this page is the one docs names for the board itself.

curl -s -H "Authorization: Bearer $FORUMULATE_TOKEN" \
  -H "Forumulate-Version: 2027-03-01" \
  https://forumulate.com/api/orgs/yourproduct/integration-health |
  jq -r '.checks[] | select(.ok == false) | "\(.id): \(.fix)"'

The organization is its slug or its id. The same answer is at GET /v1/integration-health?org=<slug-or-id>, the address our other products answer too, so a console that polls several of them uses one shape.

The answer

{
  "checks": [
    { "id": "domains.served", "ok": true, "detail": "…", "fix": "…", "docs": "https://forumulate.com/guides/custom-domains" },
    { "id": "consent.webhook_verified", "ok": false, "detail": "…", "fix": "…", "docs": "…", "hop": "auth" }
  ],
  "generatedAt": "2026-10-30T09:00:00.000Z"
}

Field

Meaning

id

Stable name of the check (list below).

ok

true healthy, false broken, null not configured — or the check could not finish within its 3-second budget. null is not a failure.

detail

What was seen, in a sentence or two. Never a secret or a full webhook URL.

fix

One sentence saying what to do.

docs

The guide for that piece.

hop

For a check that walks a path, where it broke: dns, tls, http, challenge or auth.

warning

true (with ok: true) when it works today but needs you soon — only credentials.expiring sets it. Absent otherwise.

The checks always come in this order:

id

What it looks at

domains.served

Every custom domain is verified, active and answering (up to five live domains are probed).

reader_auth.configured

Reader sign-in is set up; an OIDC issuer's discovery document is fetched (up to three).

consent.webhook_verified

Your consent platform's webhook has been received and its signature verified.

consent.identity_signing

The signed identity that ties a reader on your product to the same person on your pages.

executor.v2

The privacy-request executor is enabled and its key is in use.

sitemaps.ok

Each public space's sitemap is served.

canonical.ok

Canonical links name your address, not ours.

connectors.<provider>.kb_read

One per connector that reads a space as knowledge (connectors.kb_read when there is none).

credentials.expiring

API tokens, integration tokens and partner links that expire within 14 days — a warning, never false.

status.heartbeat_age

Your heartbeat monitors have pinged recently.

webhooks.failing

No outgoing webhook is failing.

doctor

The last outside check of your site (see forumulate doctor).

A provider whose only credentials are revoked integration tokens is not a knowledge consumer and gets no connectors.<provider>.kb_read row: revoking is how you retire one. An installed connector stays on the board, so a connector whose tokens are all expired or revoked still fails at auth.

Credentials expiring

credentials.expiring names every key that still works but stops within 14 days, soonest first: integration tokens and partner links of the organization, and the API tokens that can act on it (members' and service accounts' tokens not confined to another organization, and delivery keys confined to this one). A personal access token created without expiresInDays lives 90 days; an integration token at most a year. It is a warning (ok: true, warning: true), because nothing is broken yet. With nothing expiring it is ok: null.

You do not have to poll for it. Once per token, 14 days before it expires, we send pat.expiring or integration_token.expiring to your webhooks and e-mail the owner: a personal token's owner; for an integration token, whoever minted it (the organization's owners when that person has left); for a service-account token or a delivery key, the owners.

Nothing is written. The board reads what is stored; only live custom domains and OIDC discovery are fetched, through the same guarded fetcher every outbound call uses.

Who may read it

A token with the read scope, held by someone with org.manage_integrations, or a partner link holding health:read for this organization — see Partner links and token exchange. A partner link for another organization gets 403 wrong_organization; other integration tokens get wrong_audience.

When to read it

  • After forumulate apply, and after each manual step it lists (a DNS record, a proxy rule), until every check you configured is true.

  • After a deploy of your product: a changed proxy rule or a rotated secret shows here before a reader notices.

  • From your own monitoring, on a schedule.

The board does not suggest changes. One suggestion lives elsewhere: GET /orgs/{orgId}/reader-auth and the manifest plan answer recommendations, which holds reader_auth.use_atlas for an organization that uses Atlas but signs readers in another way (see Putting a product on Forumulate).

In the API

Every operation below is also reachable from the other surfaces without a dedicated command. forumulate api <Operation> calls it from the CLI, the JavaScript SDK has a typed method for each one (the last column names it; the Python and Go SDKs are generated from the same spec), and an agent reaches the organization-scoped ones through the MCP agent server — its api_* family tools, or call_api. Where a CLI command or a hand-made MCP tool exists too, the last column names it. Operation names link to the API reference.

Suite Integration Health

Operation

Request

What it does

Shortcuts

SuiteIntegrationHealth_get

GET /v1/integration-health

Check an organization’s integrations (/v1/ path)

client.suiteIntegrationHealth.get()

The Forumulate teamUpdated