Funding Machine subscriber opportunity sync
Target and activation boundary
Source agency:TY8NPnDY2A1uP5yZ8YKJ. Destination: My Funding Machine,
ReoQmuh4ooNuHeE5stlj. These are pinned in code. All mirror tables are keyed by
the destination locationId; source identity is a separate sourceLocationId.
Only internal Convex maintenance functions and a disabled cron can access them.
There is deliberately no browser API, operator-facing roster endpoint, or health
dashboard in V1.
Implementation approval covers the additive schema, scheduler, and code. This
does not activate production. Deployment, production owner confirmations,
pipeline/field creation, and enabling live writes need the named production
authorization. Do not use a credit pull or a payment write to validate this sync.
Read-only inspection on September 25, 2026 found:
- Destination OAuth works for location, pipeline, field, opportunity, and payment subscription reads. Use its own installation token, not the agency token.
- Existing pipelines:
3. FM Client Onboarding,Onboarding, andRetention. None is a dedicated subscriber pipeline. Leave them unchanged. - Multiple opportunities per contact are already enabled.
- The eight sync fields below do not exist yet.
- The refreshed agency list contained 220 records, 95 Active (the earlier export had 93). Source counts are observations, not a fixed enrollment manifest.
Destination configuration
After the production configuration checkpoint, create Funding Machine Subscribers with exactly these stage names: Active, Trialing, Past Due, Paused, Canceled. Use the CRM pipeline UI; the installed official SDK exposes pipeline reads but no pipeline creation method. Runtime lookup resolves the unique pipeline and stage IDs within the pinned destination. Create these opportunity custom fields in that destination. Exact names and types are validated on every run. Do not reuse the existingProduct Location ID
field from other workflows.
The settings check requires
allowDuplicateOpportunity=true because one owner
may have multiple businesses. It does not change that setting automatically.
Review existing workflow triggers for these new records before activation. The
sync never sends an email/message or enrolls a contact in a workflow itself.
Read-only preview and owner confirmation
Run commands against the intended deployment. Commands below omit--prod on
purpose. Only add it for explicitly authorized production operations. All new
functions are internal; deploying them is a separate step from checking out code.
userId:null with a new note to revoke a confirmation. Re-run the preview
after confirmations. Main-owner changes that need a different destination
primary contact remain exceptions until staff relink the same opportunity.
The documented Update Opportunity API has no contactId update field.
Enable and inspect
After reviewing the preview and obtaining production activation approval, setSUBSCRIBER_SYNC_ENABLED=true in the intended Convex deployment. This setting is
not a Next.js setting. Missing or any other value keeps the scheduler disabled.
start defaults to preview unless dryRun:false is explicit, and live mode still
requires the deployment switch. recentRuns reports cursor/queue length and
synced/needsReview/skipped counts. state shows mapped opportunity IDs, last
attempt, last full sync, and per-account issues. roster includes its observation
time. Restrict these outputs to staff because they contain customer information.
First observe an authorized run and inspect destination readbacks before
describing the automation as live. New enrollment is Active-only. Once managed,
all five supported stages reconcile, including reactivation. Opportunity
lifecycle status is preserved; new opportunities start open.
The next scheduled discovery runs every six hours. A crashed worker’s run can
resume through start after its 15-minute lease expires, which exceeds Convex’s
10-minute action lifetime. Concurrent starts reuse the one active destination
run. Only one worker owns it at a time; creates have durable intents written
before the external request.
Failure handling and recovery
- Incomplete/changing source pagination stops discovery before queuing writes. Discovery failures are visible in Convex logs. Unknown source statuses and missing listings are per-account exceptions, never inferred cancellations.
- Watchlist IDs
q3gEsVFOc126Rln8a3FL,Exq0dCONAQ7BcjcFzFTs, andlVHjDVx6cf3pi9R30VNdwere visible in CRM Active but absent from the earlier API export. Discovery retains them even before they have a mapping. If they appear later, normal source checks apply. Clear Trac’s Setup Pending is not proof of an active billable subscription. - A failed roster read preserves the last roster and count. A missing owner blocks new opportunity creation. For an existing opportunity, known stage/name and billing fields may update while owner review remains visible.
- Exact
priceIdmatching is required. V2 prices are dollars; V1 prices are cents. Missing units, unknown currency/interval, or historical prices absent from the catalog remain exceptions. No guessed fallback price is written. - The SaaS API does not provide billing dates/contact snapshots. V1 reads the
exact payment subscription under the destination
altId, verifies its ID and tenant, and reads its billing contact separately. Unavailable payment details preserve existing fields, keep the last full sync timestamp unchanged, and flag the account. The next date is the payment subscription period end unless it is scheduled not to renew. Unsupported payment shapes remain exceptions. - A missing/moved/mismatched mapped opportunity is never recreated or moved back automatically. Duplicate source IDs or duplicate exact-email contacts stop that account for review. A provider search failure is never an empty set.
- Create timeout/crash recovery searches the full destination inventory for the source ID, including other pipelines, and adopts only a unique matching opportunity in the subscriber pipeline. Pending contact creates similarly reconcile by exact destination email. If absent, the durable intent stays blocked. Inspect provider records/logs before a separately authorized manual repair; there is deliberately no blind retry/reset command.
- Primary-contact changes are a manual relink on the existing opportunity. Updating a source owner’s email does not silently overwrite a destination contact or create a replacement opportunity.
- Only sync-owned custom-field IDs are sent on updates. Notes, assignments, status, followers, monetary value, and unrelated fields are omitted.
Disable and resume
SetSUBSCRIBER_SYNC_ENABLED=false to stop new workers. An in-flight worker may
finish. A scheduled next worker closes the run as stopped. For an abandoned run,
after its lease expires:
start
with dryRun:false. Identity and unresolved-create safeguards survive stop/resume.

