HealthKit + React Native: Apple Rejected Me Twice Before I Got This Right

Apple's HealthKit review rules aren't documented. I got rejected twice. Here's the permission UX and entitlements that passed.

Integrations/HealthKit + React Native: Apple Rejected Me Twice Before I Got This Right

health

HealthKit + React Native: Apple Rejected Me Twice Before I Got This Right

Apple rejected my HealthKit app twice. The review rules aren't in the docs. Here's the permission UX and entitlements that finally passed.

What HealthKit gives you

Read access to steps, heart rate, sleep, workouts, and a long list of other signals on iOS. Write access too, but writes bring extra review scrutiny.

For most fitness apps the read side is enough. You are not trying to replace Apple Health. You are adding a context layer around it.

The library I use

react-native-health is the one I ship with. Expo prebuild step, no Expo Go. Shippen ships the config plugin pre-wired.

Permission strings Apple actually checks

  • NSHealthShareUsageDescription — required if you read any HealthKit data. Be specific: "to count your daily steps and show your weekly progress." Vague strings get rejected.
  • NSHealthUpdateUsageDescription — required if you write. Expect stricter review if you write.

Reviewers paste the exact strings into their notes. Copy-paste one from a tutorial and your app gets flagged as boilerplate.

Real data shape for a shipped fitness app

For an app I put on the App Store in 2026, I only needed three HealthKit reads:

  • Step count for today and last 7 days.
  • Active energy burned for last 7 days.
  • Workout sessions for the last 30 days.

That was the whole data layer. Everything else was computed from those three.

Where I got stuck

  • Sample granularity: Step count is available in 1-minute samples. Aggregating for a day is fine. Trying to plot per-minute for a week kills the JS thread. Aggregate server-side or use HKStatisticsCollectionQuery.
  • Permission denial is invisible: If the user says No to one data type but Yes to another, your read returns empty. You cannot tell which. Log it client-side and show an empty state with a "Check permissions" link.
  • Review flag for trends: If you present trend charts, Apple wants a medical disclaimer in your description. Add it.

See pricing

Ship your first app this weekend.

This integration is pre-configured in Shippen. One-time purchase.

ShippenIntegrationsHealthKit + React Native: Apple Rejected Me Twice Before I Got This Right