Build on Trace.
Trace ships no connectors, and that is deliberate. The buyer already pays for a CRM, an FSM or an accounting package, and every one of those is a different system. Rather than maintain thirty integrations badly, Trace exposes one API and signed webhooks, and gets out of the way.
Two audiences share this surface: the Flutter capture app, which drains its offline queue into it, and whatever system you are wiring it to. They are the same endpoints on purpose โ anything the app can do, your integration can do.
Authentication
Bearer tokens with per-resource scopes and an expiry you choose.
API reference
Projects, photos, checklists, tasks, comments, reports.
Webhooks
Signed, retried with backoff, and muted after repeated failure.
Errors & limits
Every status code the API returns, and what to do about it.
Your first request
Create a read-only token under Settings โ Access tokens, then:
curl https://trace.foundrcode.com/api/v1/projects \
-H "Authorization: Bearer $TRACE_TOKEN" \
-H "Accept: application/json"
Every response is JSON, every list is paginated, and every timestamp is ISO 8601 in UTC. Nothing about the shape changes between the mobile app's requests and yours.
What is worth knowing up front
Uploads are idempotent
Every photo carries a local_capture_id generated on the device at the moment the shutter fires. Re-sending it returns the existing photo with duplicate: true and a 200 rather than creating a second row. A retry after a lost response is safe by construction.
GPS filing refuses to guess
A photo is auto-filed only when exactly one project is in range and the fix is good enough to mean it. Ambiguous, low-accuracy and out-of-range captures come back unassigned with a stated reason โ the API tells you why rather than picking.
Originals are never modified
Annotations are stored as a separate layer plus a flattened copy. The bytes that came off the camera stay exactly as they were, and the API can always hand you them.
Everything is scoped to one team
A token belongs to a team. There is no cross-tenant read, no account-wide listing, and no parameter that widens the scope.