Build custom mobile interface using FieldPulse API

We're evaluating building a stripped-down mobile interface for our technicians using the FieldPulse API — basically a custom PWA that hits the standard REST endpoints and renders what we need without the full native app experience.

Before I sink too much time into prototyping, has anyone actually gone down this road? Specifically curious about:

  • Offline behavior — does the API expose conflict resolution, or are we rolling our own sync logic?
  • Photo upload reliability over spotty cell — any gotchas with the multipart/form-data endpoints?
  • Real-time updates — polling /work_orders every 30s feels wrong. Webhooks to a mobile PWA seems awkward too.

I've got a basic proof-of-concept working for read-only views, but I'm hitting some friction around session handling that makes me wonder if this is a path FieldPulse actually supports or just tolerates.

YMMV obviously, but would love to hear from anyone who's shipped something like this to actual techs in the field.

  • Hey Devon — yeah, this is a pattern we see more than you'd think. The API absolutely supports it, though you're right to flag the gaps.

    Offline / Conflict Resolution

    No server-side conflict resolution exposed. You get updated_at timestamps on every record, so last-write-wins is your baseline. Worth noting: the native app uses a different sync protocol (not public) that handles this more elegantly. For a PWA, I'd recommend:

    // Store pending mutations with local timestamp
    const pending = {
      id: crypto.randomUUID(),
      entity: 'work_order',
      entity_id: 'wo_123',
      payload: { status: 'completed' },
      attempted_at: Date.now(),
      retry_count: 0
    };

    Then replay in order, checking updated_at on the server response to detect collisions.

    Photo Uploads

    The multipart endpoint is solid, but connection drops mid-upload are painful. We don't support resumable uploads (no range headers), so you're re-uploading the whole file. Pro tip: compress client-side aggressively. The native app downsamples to 1600px on the longest edge before upload — copying that behavior saves headaches.

    Real-Time

    Polling is honestly fine for most field workflows if you're smart about it. Cache aggressively, poll only when the app is foregrounded, and use since parameters:

    GET /work_orders?updated_since=2025-07-26T10:00:00Z&limit=50

    Webhooks to mobile are architecturally awkward unless you're running a backend that pushes to Firebase/APNs. If you've got that infrastructure, great. If not, polling keeps it simple.

    Re: session handling — are you using OAuth or API keys? OAuth refresh tokens can be finicky in a PWA context depending on your IdP's iframe policies. API keys are simpler but obviously less secure on a shared device.

    Happy to dig deeper on any of this. There's a longer writeup in the API docs that covers mobile-specific patterns.

  • Thanks Eli — super helpful framing. The collision detection approach is basically what I landed on, good to know I'm not missing some hidden server-side capability.

    On session handling: we're using OAuth with PKCE, and the refresh token dance in a service worker context is... not great. Safari in particular kills the SW after 7 days of no site interaction, which bricks the token refresh. We're looking at a hybrid model where the native app (if installed) handles auth and passes a short-lived API key to the PWA via deep link, but that's feeling pretty hacky.

    Curious if you've seen anyone solve this cleanly, or if we're just pushing against platform limitations here.

  • We've shipped a custom tech-facing PWA for ~60 users. Notes:

    • Conflict resolution: rolled our own with vector clocks. Overkill for most, but we needed merge semantics for checklist responses.
    • Photos: implemented chunked upload ourselves — split to 500KB chunks, POST to a lambda that reassembles and forwards to FieldPulse. Not elegant, eliminates the retry pain.
    • Auth: abandoned OAuth for this use case. API keys scoped per-technician, rotated weekly via automated job. Acceptable risk for our threat model.

    One gap worth flagging: work_order.notes doesn't surface read receipts, so concurrent editing is genuinely dangerous. We disabled inline editing and force append-only.

    Docs on API authentication are current as of last month. The mobile-specific section Eli mentioned is accurate.

  • Can you share the actual error on session handling? Specific flow and IdP would help.

    Also — what does your /work_orders response payload look like for a record with checklist data? Want to confirm you're expanding the right nested fields.

  • From a governance perspective, it is worth noting that API keys distributed to mobile devices introduce significant audit trail challenges. In our environment, any credential capable of mutating production data must originate from a managed identity provider with attributable session logging.

    We evaluated a similar PWA approach and ultimately architected a thin backend that holds credentials and exposes a narrower API surface to the mobile client. This adds operational complexity but satisfies our compliance requirements for data access attribution.

    If your organization is subject to SOC 2 or similar frameworks, I would recommend reviewing the credential storage and rotation provisions in your control matrix before proceeding with client-side key distribution.

  • Update: POC is live with three techs. Ended up with Leo's approach — lambda-based chunked upload, append-only notes, and API keys rotated weekly via GitHub Actions hitting the admin API.

    The OAuth/refresh token mess was a rabbit hole I didn't need. For our threat model (company-owned devices, no PII beyond names/addresses), the key approach is fine. Fatima's point about audit trails is well-taken — we're logging every mutation server-side before forwarding to FieldPulse, so we have attribution even if the key itself is shared.

    One actual bug I hit: the work_order.status_changed webhook fires before the checklist data is fully persisted, so if you're relying on webhooks to trigger sync, you get stale checklist payloads. Polling with updated_since is more reliable for now. I've opened a ticket, no ETA.

    Happy to share the lambda code if anyone wants it — DM me.