API reference

@fixback/expo reference

The complete API of @fixback/expo. For a narrative walkthrough, see the Expo & React Native guide.

Exports

tsx
import { FixbackProvider, useFixback, Fixback } from "@fixback/expo";// in a component:const { present, trackScreen } = useFixback();// or module-level, anywhere:Fixback.present();
ExportDescription
<FixbackProvider options={…}>Wrap your app once. Takes the options below.
useFixback()Hook returning status, canSubmit(), present(), trackScreen(name), and signIn() / signOut() / identity() / onIdentity(fn).
FixbackModule-level object: the same members as the hook (status reads live from the mounted provider) — call from anywhere.

Provider options

OptionDefaultWhat it does
keyThe Project's publishable key (required).
originOptional. The origin sent on every request. A native app sends no Origin header and ingest demands none, so omit it unless you want mobile reports to carry an origin — then allowlist the same value on the Project.
apiUrlhttps://api.fixback.devSelf-hosted Fixback API base.
enabledtrueMaster switch — false arms nothing and captures nothing.
releaseThe build identifier stamped on every capture and shown on the Issue. Not yet symbolicated on this platform — a React Native bundle map is not discovered by the uploader, and Hermes frames need handling the symbolicator does not do yet. Web and Node are unaffected.
environmentThe deploy environment (production, staging, …) stamped on every report.
returnUrlWhere a Connect returns — a custom scheme (myapp://fixback-connect) or a universal link your app handles. Its origin must be on the Project's allowed origins (add it under App link); a development build's exp:// URL is a separate origin and needs its own entry. It is also how a claimed invite reaches the app: with it set, the SDK redeems the code off the link your app was opened with. Without it, signIn is a no-op and inbound links are ignored.
hostIdentityA server-minted Host identity JWT — tier the user from your own backend without Connect.
anonymousIda persisted per-install idA stable id for an anonymous reporter, if you would rather supply your own.
captureserver config{ console?, network?, replay? } per-stream toggles. Console and network arm when the provider mounts, before the boot answer lands, so startup logging is in the trace; a stream the Project turns off is then uninstrumented and what it recorded is dropped. replay is the exception — it is off unless you set it (see below).
autoCapturetrueAutomatic uncaught-error reports.
screenshotstrueCapture a screenshot when the composer opens.
replayoffSession-replay tuning — { fps?, maxEdge?, frameQuality? }. Passing it also turns replay on; see below.
beforeSendReshape or drop (null) any report before transport.
scrubtrueThe built-in URL / PII scrubbers.
beforeBreadcrumbFilter / edit trace entries at the source.
shakeonThe shake gesture — see below.

shake options

Passed as shake: { … }. Set enabled: false to turn the gesture off entirely.

KeyWhat it does
enabledTurn the shake gesture on or off.
thresholdGThe acceleration (in g) that counts as a shake peak.
minPeaksHow many peaks make a deliberate shake.
windowMsThe window the peaks must fall within.
minGapMsMinimum gap between counted peaks.
cooldownMsHow long to wait before another shake can fire.
sampleIntervalMsAccelerometer sampling interval.

useFixback()

MemberDescription
statusThe live lifecycle state — idle, starting, ready, disabled. ready only once boot said a submission would be accepted.
canSubmit()Whether a submission would be accepted right now — the server's answer, so a gated Project needs no Gate logic in app code.
present()Open the feedback composer programmatically.
trackScreen(name)Record a navigation crumb; the active screen names the report's URL.
signIn()Start a Connect — open the platform's connect page in an in-app auth session and bind the Account. Resolves to the resulting identity.
signOut()Clear the Reporter session — revoke it and forget the token.
identity()The current identity — anonymous, or a connected Account with its tier.
onIdentity(fn)Subscribe to identity changes (boot, sign in, sign out); returns an unsubscribe. What keeps a settings row current, since signing in does not always change status.

Connect — reporting as an account

A Reporter is a Fixback Account. The composer's identity row shows “Anonymous · Sign in”; tapping it opens Fixback's connect page in an in-app auth session (Google, GitHub, Sign in with Apple, magic link) and returns through the returnUrl you declare in the provider options. The SDK stores the resulting Reporter session in Expo SecureStore and the composer then shows the Account and tier. A Member of the owning Org reports at the internal tier. On an Invited- or Internal-gated Project the shake gesture stays disarmed until a Connect makes the Account eligible — enter it with Fixback.signIn() from your own UI.

A Connect can also start outside the app. Someone invited to the Project claims the invite in their email, on Fixback's claim page, and is sent back through the same returnUrl carrying a one-time code. The SDK reads that code off the link the app was opened with — or one delivered while it is running — and signs them in as they arrive, so an invited tester needs no separate signIn(). It only ever acts on links whose origin matches your returnUrl, and redeems a given code once.

ts
// Connect the signed-in Account (e.g. from a settings row):await Fixback.signIn();   // opens the platform's connect page in an auth sessionFixback.identity();       // { status: "anonymous" } | { status: "connected", name, email, tier }Fixback.canSubmit();      // whether reporting is live for this Reporter, per bootawait Fixback.signOut();  // revokes the session and clears SecureStore

Session replay

Mobile replay is a buffered window of your app's screen — 30–60 seconds at one frame a second — encoded into a single H.264/MP4 when a report is sent, and played back in the Issue's Replay tab beside the merged console / network timeline. The encoder ships with the SDK as @fixback/expo-replay-encoder; you never install or call it yourself.

Two things are required, and both are deliberate:

  • You opt in, in code. Pass capture: { replay: true }, or simply a replay tuning object. The recording is not masked — it is the screen as your app drew it — so updating the SDK never starts one.
  • The Project enables replay in its capture settings. That toggle is the kill switch: with it off, nothing is recorded whatever your code asks for.

It also needs a development build. The encoder is native code, which Expo Go cannot load: run npx expo prebuild and build with EAS or locally. In Expo Go the SDK logs why and reports without replay — nothing breaks.

tsx
<FixbackProvider  options={{    key: "pk_…",    // Opt in — and enable replay for the Project in its capture settings.    capture: { replay: true },    // Optional tuning; passing this object is itself an opt-in.    replay: { fps: 1, maxEdge: 960 },  }}>  <App /></FixbackProvider>
KeyDefaultWhat it does
fps1Frames per second. Each step up multiplies both the per-second cost on the JS thread and the payload.
maxEdge960Longest edge of the encoded video in pixels. A smaller window is never scaled up.
frameQuality0.6JPEG quality of each captured frame, 0–1. The frames are an intermediate the encoder discards, so this trades capture cost against detail surviving into the video.