---
title: "Handle Provider Callback"
method: POST
path: "/health-providers/{provider}/callback"
tags: ["health-providers"]
---

# Handle Provider Callback

`POST /health-providers/{provider}/callback`

Handle OAuth callback from health provider.

The app should call this endpoint after receiving the OAuth callback
with the authorization code and state parameters. ``user`` may be
``None`` during first-time onboarding when the caller holds an
anonymous Firebase token — identity is resolved via
``_link_provider_identity``.

Flow:
1. Validate OAuth state
2. Delegate code exchange + token storage to alice
3. Resolve mapping via ``_link_provider_identity`` (branches on
   whether the provider identity is new, already-owned, a collision,
   or recoverable).

## Path parameters

- `provider` 'garmin' | 'whoop' | 'coros' | 'terra' | 'apple_health', required — Health data providers (OAuth connections).

## Query parameters

- `login_only` boolean — When true, return 404 if the provider identity does not already map to a User. Used by the mobile login flow to avoid auto-creating ghost accounts.

## Headers

- `x-device-timezone` string, nullable

## Request body

- HealthProviderCallbackRequest — Request with OAuth callback data.
  - `code` string, required — Authorization code from OAuth callback
  - `state` string, required — State parameter from callback

## Response `200`

Successful Response

- HealthProviderCallbackResponse — Response after a provider connect/callback or Apple Health register. ``result`` indicates the branch that ran: - ``connected``: a new ``HealthProviderConnection`` was created. - ``already_connected``: the caller already owns this provider identity. - ``recovered``: the provider identity maps to a different imperfect user (typical after a reinstall/new device). ``custom_token`` is set so the mobile client can ``signInWithCustomToken`` and adopt the existing user's Firebase UID.
  - `provider` 'garmin' | 'whoop' | 'coros' | 'terra' | 'apple_health', required — Health data providers (OAuth connections).
  - `provider_user_id` string, required
  - `permissions` string[], required
  - `status` 'active' | 'expired' | 'revoked' | 'error', required — Status of a health provider connection.
  - `result` 'connected' | 'already_connected' | 'recovered'
  - `custom_token` string, nullable

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/imperfect/apis/imperfect-api.md) · [All operations](https://skmtc.dev/imperfect/apis/imperfect-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/imperfect/imperfect-api/revisions/cc2293a44257/schema)
