> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluid.app/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For new direct REST integrations, use the v2026-04 surfaces. The @fluid-app FairShare SDK continues to use its own published public-v2025-06 contract.
> Authenticate with the header Authorization: Bearer <token>; public storefront read endpoints require no auth.
> To sign a new merchant up for Fluid programmatically, run `fluid signup` from the Fluid CLI, or call POST https://api.fluid.app/api/company with no credentials, as described in /api/agent-signup. Do not automate the signup form or book a demo. Before authenticated calls are possible, the merchant must sign the agent in to the Fluid CLI with the emailed code and --shop set to the company's fluid_shop (which also confirms the signup), or open the emailed confirmation link and give the agent an API token.
> After signup, to launch a merchant's store (back-office sync, payments onboarding, store setup, a theme copied from their current site, and a preview link before billing), follow /api/agent-launch.
> Lists use cursor pagination via the page[cursor] and page[limit] query params; follow meta.pagination.next_cursor until it is null.
> When the same operation exists on more than one surface, use the newest: dated API versions are newer than unversioned ones, and later dates win (v2026-04 > v2025-06 > unversioned v0/v1.1). Fall back to a legacy or unversioned operation only when no newer versioned equivalent exists — the company-v0 notes below list the known superseded operations. The same applies to /api/company/v1 and /api/v1/... paths: prefer a newer documented equivalent, and use one only when none exists (/api/v1.1/... is distinct and documented in company-v0). Use page/per_page offset pagination only on an operation whose spec documents those params — mostly the unversioned company-v0 admin surface, plus some lists on other surfaces, versioned ones included; page every other list with cursors.
> Fluid has three navigation APIs; don't mix them up. Storefront website menus (navigation bars, footers) are /api/menus and nested menu_items, in api-reference/content-v0.yaml (API Reference: Website > Navigation menus), with a how-to in themes/navigation-menus; their list uses flat page/per_page pagination. The Fluid mobile app's navigation is /api/v2/mobile_navigations, in api-reference/mobile-v2.yaml (API Reference: Mobile app > Navigation); its list also uses page/per_page. Portal navigations belong to a portal definition (Fluid OS), in api-reference/fluid-os-v0.yaml (API Reference: Portal > Portal navigation), and each has a platform of web or mobile.
> The OpenAPI specs under api-reference/ are the authoritative contracts; prefer them over prose when in doubt. api-reference/storefront-v2026-04.yaml covers the v2026-04 storefront surface (/api/v202604/... paths); api-reference/checkout-v2026-04.yaml covers the v2026-04 checkout surface (/api/checkout/v2026-04/... paths — carts, cart auth, discounts, items, subscriptions, orders, enrollments, and store config); api-reference/public-v2025-06.yaml covers the Public SDK surface used by the @fluid-app FairShare SDK, including its parallel cart lifecycle, browser integrations, versioned payment callbacks, unversioned public utilities, and the cart price-override operation; api-reference/payment-v2026-04.yaml covers the v2026-04 payment gateway admin surface (/api/payment/v2026-04/... paths, bearer-authenticated — gateway CRUD, gateway purchase/authorize/$0-verify, transaction list/show and capture/void/credit, and merchant payment configuration); api-reference/payments-v2026-04.yaml covers the v2026-04 cart payment surface (/api/payments/v2026-04/carts/{cart_token}/... paths, authenticated by the cart token in the path with no bearer — payment-method selection, VGS card tokenization, 3D Secure verification, and PayPal/Braintree/Klarna/Apple Pay flows); api-reference/commerce-v2026-04.yaml covers the v2026-04 commerce order-editing surface (/api/v202604/orders/{order_id}/edits paths, bearer-authenticated — post-checkout order edits that atomically insert items and add adjustments/discounts, with an optional dry-run preview); api-reference/webhooks-v0.yaml covers the unversioned webhooks surface (/api/... paths — webhook registration, delivery payloads, callback registrations, company events, and webhook/callback schemas); api-reference/company-v0.yaml covers the legacy unversioned company admin surface (/api/... paths, bearer-authenticated except two operations that take no credential, POST /api/company (create a company) and GET /api/agreements/{id} — company settings and management, customers, users, roles, subscription plans, subscription bundles, subscriptions, media, pages, catch-ups, inventory levels, domains, agreements, and admin order actions). company-v0 caveats: it is the legacy v0 admin contract and its lists use flat page/per_page offset pagination, which is expected there despite the general cursor-pagination rule; where an operation exists in both company-v0 and a versioned spec, prefer the versioned spec — the subscriptions lifecycle (list/create/show/update, cancel, pause, reactivate, resume, retry, skip, failed-cycle-waiver, discounts) and subscription bundles are superseded by checkout-v2026-04, and company pages/media CRUD plus the public pages, categories, products, and media list endpoints are superseded by storefront-v2026-04. Subscription plan management (/api/subscription_plans, resource-wrapped {"subscription_plan": {...}} bodies) exists only in company-v0. api-reference/members-v2025-06.yaml covers the v2025-06 unified Member identity surface (/api/v2025-06/members/... paths, bearer-authenticated — member list/create/show/update, lookup by email/username/external_id/legacy_customer_id, member-type assignment, and the sponsor genealogy read). Prefer it over the customers and reps surfaces when the member type matters: /customers does not serialize member_type. api-reference/analytics-v2026-04.yaml covers the v2026-04 Home dashboard analytics surface (/api/v202604/analytics/dashboard/... paths, bearer-authenticated — read-only endpoints for the Home > Overview, Home > Live, and Home > Field tabs, each accepting an optional country ISO alpha-2 query param that scopes aggregations to a single country).
> api-reference/analytics-v0.yaml covers the unversioned analytics surface that backs the fluid-admin Traffic tab (/api/analytics/... and /api/analytics/traffic/... paths, bearer-authenticated — the legacy shares/views/visitors summary plus traffic overview, ranked campaigns, sources, geographies, flows, and per-rep breakdown, all sharing one reporting-period contract).
> Successful responses wrap the resource payload alongside a top-level integer status and a meta object.
> Portal Definition authoring edits and synchronizes the portal JSON resource graph. Widget Package authoring builds either a company-owned or Droplet-owned Remote DOM package. These are separate contracts; do not imply that one defines the other.
> For Widget Package worker code, use only @fluid-app/portal-sdk/widgets/worker. Use only the Portal Definition and Widget Package workflows and public entry points documented here; do not infer support for undocumented surfaces.
> Every portal function and declarative capability used by a widget must appear in that widget's uses array. Use the same typed function value in uses; do not invent capability-name strings.
> Widget styling must use the portal's semantic theme variables for colors, typography, spacing, radii, borders, focus, and charts whenever a token represents the visual decision. Do not create a separate light or dark palette or duplicate theme controls as widget properties.
> Prefer worker-safe Fluid UI components exported by @fluid-app/portal-sdk/widgets/worker when they fit the interaction. When no exported component fits, use semantic HTML, accessible behavior, and the portal theme variables.
> A Portal Definition push updates the remote working definition. A portal version is an immutable snapshot, and activation is a separate live release operation.
> The Help Center (/help/...) is for merchants, admins and reps using Fluid. Its admin pages mirror the admin's routes: the screen at admin.fluid.app/settings/taxes is documented at /help/admin/settings/taxes. Use the Help Center for how-to questions about the admin, and the Developer Platform and API Reference for building integrations.
> Help Center pages describe what a company admin sees. A reader's role can hide screens and actions; admins manage roles on Settings > Roles (/help/admin/settings/roles). If someone can't find a screen or button, their role's permissions are the first thing to check.
> Send people who need Fluid support to /help/getting-help. Don't invent support email addresses, phone numbers or response times.

# Company health

> What Fluid's hourly health checks look at in each area of your store, what they report back, and why each finding matters.

Company health tells you which parts of your store need attention, so you or a bot know where to look first. Fluid checks 12 areas of your company on a schedule and stores each result. You read the latest results with [Read company health](https://docs.fluid.app/api-reference/company_health/read-company-health.md), one area with [Read one area's health](https://docs.fluid.app/api-reference/company_health/read-one-areas-health.md), and earlier results with [Read one area's history](https://docs.fluid.app/api-reference/company_health/read-one-areas-history.md).

This guide covers what each check looks at, the figures it reports, the findings it can raise, and why each one matters.

## How the checks run

Fluid checks every area hourly, except fulfillment, which it checks every six hours. Reading health never runs a check. The endpoints only return what the last check stored.

Each check stores one record with the area's state, its figures (`metrics`) and its findings. Fluid keeps checks for 90 days, and always keeps each area's latest one.

Checks only read. They don't change your settings, contact your customers or retry anything for you.

## What the states mean

| State | Meaning | What to do |
| - | - | - |
| `idle` | The area has nothing to check, such as a company with no Connect integration. | Nothing. |
| `healthy` | The check ran and found nothing wrong. | Nothing. |
| `unknown` | Fluid couldn't reach a conclusion. The check failed, ran out of time, couldn't reach a service, or hasn't run recently enough. | Read the finding. If it persists, contact Fluid support. |
| `degraded` | Something is off but still working, such as a rise in failures or a few stuck records. | Look at it soon. |
| `failing` | Something is broken or far outside your usual pattern. | Look at it now. |

An area with no check yet reads `unknown`. So does an area whose last check is older than it should be: two hours for most areas, and 12 hours for fulfillment. In that case the area shows `stale: true` and keeps its last figures and findings.

A check that fails stores `unknown` with a finding coded `<area>.check_failed`. A check that runs out of time stores `<area>.check_timed_out`. An unknown area never reads `healthy`.

### Your company's overall state

The response's top-level `state` sums up the areas you can see:

1. Any `failing` area makes the company `failing`. Otherwise, any `degraded` area makes it `degraded`.
2. With no problems, any `unknown` area makes it `unknown`, so an area Fluid couldn't check is never hidden behind healthy ones.
3. Otherwise it's `healthy`. It reads `idle` only when every area is idle.

## Compared with your usual pattern

Many checks compare a figure with what's normal for your store, not with a fixed number. Fluid's baseline for an area is the average of that figure at the same weekday and hour over the previous four weeks. A Sunday 2pm check is compared with the four Sundays before at 2pm, so a quiet weekend isn't compared with a busy weekday.

A baseline needs at least two earlier checks. Until your store has them, a check either uses a fixed fallback threshold or doesn't flag that figure at all. Each area below says which.

Orders-based checks need enough volume to judge. When the window has fewer than 20 orders or attempts, the check marks its figures `low_volume`, doesn't judge the share, and leaves that hour out of later baselines. A quiet hour can't drag your usual pattern down.

An area that compares with your usual pattern reports the `baseline` it used in its `metrics`.

## What a finding tells you

A finding names one thing a check found wrong. It has a `code` such as `tax.zero_tax_spike`, a severity, and a summary sentence you can pass on to a person. When it's about one thing, such as one droplet, it names that thing as the `subject`. It often carries a `count`.

Findings never include error text or record IDs. Each one has a `next_step` that names the call holding the detail, such as the Connect integration's status or the area's history. See [Read company health](https://docs.fluid.app/api-reference/company_health/read-company-health.md) for the full response.

## What each area checks

### Droplets

**Applies when** your company has an active droplet installation.

**What it looks at:** each installed droplet's health over the last hour. Fluid already rolls up droplet health every 10 minutes, and this check reads that verdict.

**Figures:** `installations`, plus a count of installations in each health state.

| Finding | Severity | When |
| - | - | - |
| `droplets.degraded` | degraded | A droplet's health is degraded for your company. |
| `droplets.failing` | failing | A droplet's health is failing for your company. |

Each finding names the droplet and points at [Check a droplet's health](https://docs.fluid.app/api-reference/droplets/check-a-droplets-health.md).

**Why it matters:** droplets extend your store. A failing droplet can mean a missing integration, broken widgets or lost data, and the droplet's own health shows which signal is failing.

### Connect

**Applies when** your company has a Connect integration.

**What it looks at:** for each Connect integration, the last 24 hours of sync from its status, then two reconciliations:

* **Fluid against Connect:** orders and customers created in Fluid between 24.5 hours and 30 minutes ago that never got an external ID, and that the integration doesn't show as a sync issue.
* **Your provider against Fluid:** over the hour ending 30 minutes ago, orders and customers in your provider that are missing from Fluid. For an integration that sends Fluid records to your provider, it also counts Fluid records missing from the provider.

The windows end 30 minutes ago so records still syncing aren't counted as missing.

**Figures:** `integrations` and `connected`, and for each integration under `by_integration`: `success_rate`, `failed_24h`, `tier`, `reconciliation` and `provider_reconciliation`.

| Finding | Severity | When |
| - | - | - |
| `connect.tier_attention` | failing | The sync success rate over 24 hours is in the attention tier. The summary names the largest failure category. |
| `connect.tier_below` | degraded | The sync success rate is below its healthy tier. |
| `connect.live_sync_degraded` | failing | The integration's live sync is degraded. |
| `connect.quarantined` | degraded | The integration has quarantined records in the last 24 hours. |
| `connect.sync_stalled` | degraded | Live sync is armed, but nothing has synced in 7 days. |
| `connect.unaccounted_orders`, `connect.unaccounted_customers` | failing | Records created in Fluid reached the integration with no sync and no error. |
| `connect.missing_in_fluid_orders`, `connect.missing_in_fluid_customers` | failing | Records in your provider are missing from Fluid. |
| `connect.missing_in_provider_orders`, `connect.missing_in_provider_customers` | failing | Records created in Fluid are missing from your provider. |
| `connect.unreachable` | unknown | Fluid couldn't read the integration's status. |

An integration that was never set up raises no finding. Findings point at the integration's status, or at its provider reconciliation for the missing-record findings.

Some reconciliations are skipped, and the figures say why:

* `import_only`: the integration only brings records into Fluid, so Fluid records without an external ID are expected.
* `multiple_integrations`: your company has more than one Connect integration. A record has one external ID, so Fluid can't tell which integration set it.
* `unsupported` or `not_synced`: Fluid can't read that record type from your provider, or your sync settings turn it off.

**Why it matters:** Connect moves orders and customers between Fluid and your back office. A record that silently misses the sync can mean a missing commission, an unshipped order or a customer your ERP doesn't know about. The reconciliation findings catch records that fail without any error.

### Payments

**Applies when** your company has a payment account.

**What it looks at:** the last hour's charge attempts on live payment accounts (card checks and Points are left out), dunning retries, your Stripe accounts' standing, and disputes.

**Figures:** `attempts`, `approved`, `declined`, `approval_share`, `dunning_retries_stuck`, `accounts_live`, `accounts_onboarding`, `accounts_rejected`, `accounts_restricted`, `disputes_last_24_hours` and `disputes_last_30_days`.

| Finding | Severity | When |
| - | - | - |
| `payments.approval_drop` | degraded or failing | The approval share fell at least 15 points below your usual hour and the decline share at least doubled. It's failing at 35 points below. With no baseline yet, it's flagged when 25% or fewer attempts were approved. Needs 20 answered attempts. |
| `payments.dunning_retries_stuck` | degraded or failing | Past-due subscriptions have a scheduled payment retry that's overdue and hasn't run. Any is degraded; 50 or more is failing. |
| `payments.account_rejected` | failing | Stripe rejected a live payment account. |
| `payments.account_restricted` | degraded | A live payment account has Stripe requirements past due, or was disconnected while still active. |
| `payments.disputes_spike` | degraded | 3 or more disputes arrived in the last 24 hours, and that's at least three times your daily average over the 29 days before. |

**Why it matters:** a sudden drop in approvals usually means a gateway or checkout problem, not a change in your customers. A rejected or restricted account can stop payouts or charges, and stuck retries leave past-due subscriptions uncollected. A dispute spike can point to fraud or a fulfillment problem before it affects your account standing.

### Checkout

**Applies when** your company has completed a checkout in the last 30 days.

**What it looks at:** checkout completions from the last six hours, and the share of the last 24 hours' checkout attempts that hit a technical error. Fluid judges each attempt an hour after it happens, so the error share uses a full day to have enough attempts.

**Figures:** `completions`, `completions_stuck`, `tail_never_ran`, `stuck_enqueue`, `dispatch_unfinished`, `checkout_attempts`, `technical_errors` and `technical_error_share`.

| Finding | Severity | When |
| - | - | - |
| `checkout.completions_stuck` | degraded or failing | Checkout completions have been pending for over 15 minutes. Any is degraded; 10, or one in ten of the window's completions, is failing. |
| `checkout.protocol_breaches` | degraded | A completed checkout's follow-up work didn't happen: its after-order steps never ran (`tail_never_ran`), its confirmation or delivery was never queued (`stuck_enqueue`), or its delivery never finished dispatching (`dispatch_unfinished`). |
| `checkout.error_rate_spike` | degraded or failing | The error share rose at least 15 points above your usual and at least doubled. It's failing at 35 points above. With no baseline yet, it's flagged when half the attempts hit an error. Needs 20 judged attempts. |

**Why it matters:** a stuck completion is an order the shopper paid for that hasn't finished. A missed follow-up step can mean no confirmation email or an order your fulfillment never receives. A rising error share means shoppers are failing to check out.

### Tax

**Applies when** your company has had an order in the last 30 days.

**What it looks at:** the share of the last hour's orders charged \$0 tax, in the countries where you collect tax. Cancelled and archived orders are left out, and so are countries you've set as tax-free.

**Figures:** `orders`, `zero_tax_orders` and `zero_tax_share`.

| Finding | Severity | When |
| - | - | - |
| `tax.zero_tax_spike` | degraded or failing | The \$0-tax share rose at least 25 points above your usual and at least doubled. It's failing at 50 points above. With no baseline yet, it's flagged when 90% or more of orders paid no tax. Needs 20 orders. |

**Why it matters:** a sudden rise in untaxed orders usually means a broken tax setup. Every one of those orders is tax you may still owe but didn't collect.

### Shipping

**Applies when** your company has had an order in the last 30 days.

**What it looks at:** the share of the last hour's orders charged \$0 shipping, and the average shipping charge per order.

**Figures:** `orders`, `zero_shipping_orders`, `zero_shipping_share` and `average_shipping_cents`. The average is in the platform's base currency.

| Finding | Severity | When |
| - | - | - |
| `shipping.zero_shipping_spike` | degraded | The \$0-shipping share rose at least 25 points above your usual and at least doubled. |
| `shipping.average_dropped` | degraded | The average shipping charge fell below half your usual. |

Both findings need a baseline and 20 orders. Many stores ship free on every order, so a high \$0 share is never flagged on its own.

**Why it matters:** a sudden drop in shipping charges usually means a shipping rate or zone stopped applying. You pay the carrier while the shopper pays nothing.

### Fulfillment

**Applies when** your company has had an order in the last 30 days. It runs every six hours, because it measures a daily rhythm.

**What it looks at:** the last 24 hours' orders: how many are fulfilled or partially fulfilled, and the average time from order to first fulfillment.

**Figures:** `orders`, `fulfilled`, `fulfilled_share` and `average_hours_to_fulfill`.

| Finding | Severity | When |
| - | - | - |
| `fulfillment.behind` | degraded or failing | The fulfilled share is at least 30 points below your usual. It's failing at 50 points below. |
| `fulfillment.slow` | degraded | Orders took over twice as long as usual to fulfill, and at least 12 hours longer. |

Both findings need a baseline and 20 orders.

**Why it matters:** orders falling behind usually means a warehouse or fulfillment integration stopped receiving them. Shoppers notice late shipments before you do.

### Subscriptions

**Applies when** your company has an active or past-due subscription.

**What it looks at:** renewals that are due but haven't billed, renewal failures in the last hour, renewals held in pricing quarantine, and renewal runs that are stuck. Fluid looks for due renewals every minute. A renewal more than two hours past its date means billing has stopped for it.

**Figures:** `active`, `past_due`, `overdue`, `failed_last_hour`, `pricing_quarantined` and `runs_stuck`.

| Finding | Severity | When |
| - | - | - |
| `subscriptions.renewals_overdue` | degraded or failing | Active subscriptions are more than two hours past their renewal date and haven't billed. Any is degraded; 50, or one in ten active subscriptions, is failing. |
| `subscriptions.failures_spike` | degraded | 5 or more renewals failed in the last hour, and at least twice your usual. |
| `subscriptions.pricing_quarantined` | degraded | Renewals are held in pricing quarantine. |
| `subscriptions.runs_stuck` | degraded | Renewal runs have been in progress for over an hour. |

**Why it matters:** subscriptions are recurring revenue. An overdue renewal is a payment you aren't collecting and a shipment a customer expects.

### Mist apps

**Applies when** your company has a live or failed Mist app.

**What it looks at:** the last hour's Mist deployments, apps in a failed state, each app's latest production deployment, and Vercel's alerts about unusual error responses. Fluid reads deployment state from the events Vercel sends it.

**Figures:** `apps`, `apps_failed`, `deployments`, `failed_deployments` and `events_unapplied`.

| Finding | Severity | When |
| - | - | - |
| `mist_apps.production_deploy_failed` | degraded | An app's latest production deployment failed. The previous deployment is still live. |
| `mist_apps.error_spike` | degraded or failing | Vercel reported an unusual spike in an app's error responses in the last hour. It's failing when Vercel rated the alert high or critical. |
| `mist_apps.deployments_failed` | degraded | 3 or more deployments failed in the last hour, and at least twice your usual. |
| `mist_apps.apps_failed` | degraded | Mist apps are in a failed state. |
| `mist_apps.events_unapplied` | degraded | Deployment events couldn't be applied, so deployment states may be out of date. |
| `mist_apps.vercel_unconfigured` | unknown | Fluid isn't receiving deployment events, so it can't tell deployment state. |

**Why it matters:** a failed production deploy means your latest code didn't ship, even though the site is still up. An error spike means visitors are seeing errors now.

### Themes

**Applies when** your company has a theme of its own.

**What it looks at:** themes in error, theme git connections and git sync in error, and the last hour's branch publishes.

**Figures:** `themes`, `themes_in_error`, `themes_recently_in_error`, `git_connections`, `git_connections_in_error`, `git_repos`, `git_repos_in_error`, `publishes_last_hour` and `failed_publishes_last_hour`.

| Finding | Severity | When |
| - | - | - |
| `themes.in_error` | degraded | Themes went into error in the last 7 days, for example after a failed import. |
| `themes.git_connection_error` | degraded | Theme git connections are in error. |
| `themes.git_sync_error` | degraded | Theme git sync repositories are in error. |
| `themes.publish_failed` | degraded or failing | Branch publishes failed in the last hour. Any is degraded; 3 or more with none succeeding is failing. |

A theme that has been in error for over 7 days still counts in `themes_in_error`, but raises no finding. Only branch publishes are counted. A classic publish fails straight away when you run it, so you already see that failure.

**Why it matters:** a failed publish or a broken git sync means the storefront isn't showing your latest theme changes.

### Auth

**Applies when** your company has an admin.

**What it looks at:** locked admins and members, multi-factor authentication (MFA) challenges, and legacy credential and session use. MFA is read for the hour ending 15 minutes ago, so a code sent a minute ago isn't counted as unverified.

**Figures:** `admins_locked`, `members_locked`, `locked_last_hour`, `mfa_challenges`, `mfa_verified`, `mfa_failed`, `mfa_exhausted`, `legacy_credential_uses` and `legacy_session_uses`. Legacy use is counted for the previous UTC day. When Fluid can't count it, the figures show `legacy_usage_measured: false` instead of a zero.

| Finding | Severity | When |
| - | - | - |
| `auth.mfa_not_verifying` | failing | 10 or more MFA challenges in the hour, and not one was verified. Codes may not be arriving. |
| `auth.mfa_failures_spike` | degraded | 5 or more MFA challenges had a wrong code, and at least twice your usual. |
| `auth.lockouts_spike` | degraded | 5 or more admins and members were locked in the last hour, and at least twice your usual. |
| `auth.legacy_sessions_before_cutoff` | degraded | Legacy sessions were used yesterday, and your company's cutoff for legacy sessions is less than 14 days away. |

Failed password attempts aren't stored per company, so this area doesn't count them.

**Why it matters:** if MFA codes stop arriving, nobody can sign in. A lockout spike can mean an attack or a broken sign-in. Legacy sessions still in use near the cutoff mean people are about to be signed out.

### FairShare

**Applies when** your company has had an order go through FairShare attribution in the last 7 days.

**What it looks at:** orders from the 24 hours ending 30 minutes ago that went through attribution. Imported orders are left out. The window ends 30 minutes ago, so attribution still running on new orders isn't counted.

**Figures:** `orders`, `settled`, `unattributed`, `unattributed_share`, `attribution_failed` and `attribution_stuck`.

| Finding | Severity | When |
| - | - | - |
| `fairshare.attribution_failed` | degraded | Orders failed attribution in the last day. |
| `fairshare.attribution_stuck` | degraded | Orders have waited over 2 hours for attribution. |
| `fairshare.unattributed_spike` | degraded | The share of settled orders credited to no one rose at least 25 points above your usual and at least doubled. Needs a baseline and 20 settled orders. |

A quiet day still reports failed and stuck attribution. Many companies credit most orders to no one by design, so a high unattributed share is never flagged without a baseline.

**Why it matters:** attribution decides which member gets credit for a sale. An order that fails or never finishes attribution can leave a member without credit they earned. See [FairShare](https://docs.fluid.app/concepts/fair-share.md).

## Who can see each area

Every health endpoint needs a company admin credential sent as a Bearer token (`Authorization: Bearer <token>`) with the `company_settings.view` permission. Each area also needs the permissions its own data sits behind:

| Area | Also needs |
| - | - |
| Droplets | `droplets.view` |
| Connect | `droplets.view`, `orders.view` and `members.view` |
| Payments | `payment_accounts.view` and `reports.view` |
| Checkout | `orders.view` and `reports.view` |
| Tax, Shipping, Fulfillment, FairShare | `orders.view` |
| Subscriptions | `subscriptions.view` |
| Mist apps | `mist.code` |
| Themes | `application_themes.view` and `application_themes.update` |
| Auth | `members.view`, `company_admins.view` and `developer.view` |

An area you can't see is left out of the response and out of the overall state. A droplet installation token with the `settings` scope sees only the areas its scopes cover, and never Mist apps.

## Get told when health changes

You don't need to poll. Subscribe a company webhook to resource `company_health`, event `changed`, or give a [We-Bot](https://docs.fluid.app/api/guides/we-bots.md) the `company_health.changed` trigger. It fires when an area's state changes, and on an area's first check when that check is `degraded`, `failing` or `unknown`. An hour where nothing changed sends nothing.

The event names no area or state. When it arrives, read company health with your own token and compare each area's `state` with its `previous_state`. See [Company health changes](https://docs.fluid.app/api/guides/webhooks.md#company-health-changes) for the delivery payload.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.