SOP-OB-002: Customer Onboarding — New ERP Integration Required (Full Path)
Version: 1.1 Owner: CS Lead + Engineering Lead Audience: Customer Success (CS), Engineering (ENG) Target timeline: 4–8 weeks (depending on ERP API complexity)
1. Purpose and Scope
Section titled “1. Purpose and Scope”This SOP governs onboarding for customers whose ERP is either:
- Not yet in the integration registry at all, or
- In the registry but not yet implemented (status
'beta'with aNotImplementedErrorin the factory, e.g., somedynamicsorsapvariants)
This path requires an engineering build sprint before full customer onboarding can proceed. To minimize elapsed time, provisioning work that does not depend on the integration being built starts immediately in parallel.
Not covered: If the customer’s ERP is already in the registry and the integration is implemented, use SOP-OB-001.
Role key:
| Abbreviation | Role |
|---|---|
| CS | Customer Success |
| ENG | Engineering / DevOps |
| CUST | Customer (their IT or admin contact) |
2. Structure: Two Parallel Tracks
Section titled “2. Structure: Two Parallel Tracks”Once the contract is signed, work splits into two tracks that run concurrently and merge when engineering signals “ready.”
Contract signed | +------------------------+ | | TRACK A TRACK B Engineering Build Pre-Provisioning (SOP-OB-003) (CS + ENG, no ERP needed) | | | ENG signals "ready" | +------------------------+ | Track Merge (Steps C1–C8) | UAT → Go-Live3. Prerequisites — Extended Intake Checklist
Section titled “3. Prerequisites — Extended Intake Checklist”All items from SOP-OB-001 Section 2, plus:
ERP API Discovery
Section titled “ERP API Discovery”- ERP vendor name, exact product name, and version
- Link to the vendor’s API documentation (or confirmed NDA for confidential docs)
- API type: REST/JSON, OData, SOAP/XML, JSON-RPC, direct database
- Authentication mechanism: Basic auth, OAuth2 (client credentials / auth code), API key, session cookie, token
- Sandbox / test environment credentials obtained and verified with
curlor Postman - API rate limits documented (requests/min, page size limits)
- Entities available via the API:
- Products / items (required)
- Customers / accounts (required)
- Shipping addresses / ship-to locations
- Cross-references / customer item aliases
- Ship-to links / customer–address relationships
- Orders and order lines (for write-back)
- Incremental sync mechanism available? (e.g.,
lastModifiedDatefilter, sequence number, change log endpoint) - Pagination approach: offset/limit, cursor-based, OData
$skip/$top
Legal and Security
Section titled “Legal and Security”- ERP vendor API terms of service reviewed (no restrictions on third-party automation)
- Customer has confirmed they are permitted to grant API access to ERP Unlocked
- NDA in place if vendor API docs are confidential
Engineering Scoping
Section titled “Engineering Scoping”- Rough scope estimate completed by ENG (days of engineering work)
- Timeline agreed with customer in writing — milestone-based, not a fixed go-live date
- Customer explicitly notified: go-live date is contingent on sandbox API access and successful test
4. Track A: Engineering Build
Section titled “4. Track A: Engineering Build”All Track A work follows SOP-OB-003 in detail. This section provides the project management checkpoints.
Step A1 — Engineering Scoping Call + Manual Discovery Owner: ENG + CUST IT
Schedule a 1-hour technical call with the customer’s IT or ERP admin contact. Because there is no Instance Explorer yet for this ERP, this call must gather the information the explorer would normally auto-detect.
Standard scoping outputs:
- Confirmed entity list for Phase 1 of the integration (products, customers, addresses, etc.)
- Auth mechanism confirmed and tested in sandbox with
curlor Postman - Sandbox credentials granted to ENG
- Blocker list documented (missing docs, no sandbox, rate limit concerns, SOAP/XML complexity)
- ENG produces a written scope estimate within 2 business days
Manual discovery — answers to gather (replace the Instance Explorer for this ERP):
- Which entity modules are licensed and API-accessible?
- Are there custom fields on customer, item, or order records? What are their names and types?
- What is the pricing model? (list price, customer-specific, volume tiers, third-party pricing engine such as RPM or Cavallo)
- Multi-company or multi-branch setup? Does order submission require a Branch or Company ID?
- Approximate record counts for products and customers (for sync time planning)
- API version and any known quirks (rate limits, null handling, non-standard date formats)
- Any known data quality issues (duplicate records, missing required fields, etc.)
Document findings in docs/erp/<slug>-discovery.md — this file becomes the seed for the Instance Explorer that will be built in SOP-OB-003.
Blockers must be resolved before engineering starts. A common blocker is a customer who has a sandbox environment in name only — verify that data in the sandbox is realistic (populated products, customers, etc.) before committing to the timeline.
Step A2 — Build the Integration Owner: ENG
Follow SOP-OB-003 in full. At minimum, the completed integration includes:
| Deliverable | Location |
|---|---|
| Registry entry | packages/integrations/src/registry/registry.ts |
| Python auth handler | apps/dagster/erp_pipeline/sources/<slug>/auth.py |
| Python HTTP client + DLT source | apps/dagster/erp_pipeline/sources/<slug>/ |
| Transformers (all entities) | apps/dagster/erp_pipeline/transformers/<slug>_*.py |
| Transformer registry | apps/dagster/erp_pipeline/transformers/registry.py |
| Sync orchestrator | apps/dagster/erp_pipeline/implementations/<slug>_sync_orchestrator.py |
| Factory registrations | erp_source_factory.py + erp-sync-factory.ts |
| Default capabilities | apps/dagster/erp_pipeline/capabilities.py |
Auth getter in erp_auth.py | apps/dagster/erp_pipeline/sources/erp_auth.py |
| Unit + integration tests passing | apps/dagster/tests/ |
| Integration docs | docs/erp/<slug>-integration.md |
Step A3 — Staging Deployment Owner: ENG
- Merge PR to
mainafter code review (use PR labelnew-erp-integration) - Confirm the Dagster staging environment picks up the new orchestrator
- Run one full sync against the customer’s sandbox ERP from staging
- Spot-check data quality: record counts match ERP admin UI within ~1%, field mapping correct for 10 sampled records
- Confirm no regressions on existing integrations (Prophet21, NetSuite test jobs still green)
ENG signals “ready” to CS — this is the Track Merge trigger. Send a Slack message in the customer’s internal channel with:
- Confirmation the staging sync passed
- The new ERP slug to use in connection setup
- Any known limitations to communicate to the customer
5. Track B: Pre-Provisioning (Runs in Parallel with Track A)
Section titled “5. Track B: Pre-Provisioning (Runs in Parallel with Track A)”These steps do not require the integration to be built. Start them immediately after contract signing.
Step B1 — Create Clerk Organization Owner: CS
Identical to SOP-OB-001 Step 1. Do this on Day 1 after contract signing.
Record the clerkOrganizationId. Do not invite users yet — wait until the integration is ready (Step C5).
Step B2 — Create Flagsmith Org Identity (Conservative) Owner: ENG
Create the Flagsmith identity using the clerkOrganizationId. Set conservative flags — disable anything that requires the integration:
erp_sync_enabled = false (enable in Step C4 after integration deployed)order_review_enabled = true (safe to enable now — UI only)pdf_extraction_enabled = true (ERP-agnostic, safe to enable now)email_intake_enabled = true (ERP-agnostic, safe to enable now)Step B3 — Set Up Email Intake Owner: CS + CUST
Email intake is ERP-agnostic — it can be configured, tested, and handed off to the customer before the ERP integration is built.
- Provision the customer’s dedicated inbound email address
- Send forward-rule setup instructions to CUST
- Verify receipt of a test email before Track Merge begins
This means by the time the integration is ready, the customer’s email flow is already working.
6. Track Merge: Combined Steps
Section titled “6. Track Merge: Combined Steps”After ENG signals “ready” (Step A3 complete):
Step C1 — Create ERP Connection Record Owner: ENG
Identical to SOP-OB-001 Step 2, using the new registry slug. Use the production credentials provided by CUST (not sandbox).
Step C2 — Test Connection Owner: ENG ⛔ Gate
Use the same request format as SOP-OB-001 Step 3: send integrationSlug and credentials (the production credentials from Step C1). If the test is run from the webapp UI, it uses the existing connection and connectionId instead of a raw body.
POST /api/integrations/connections/test{ "integrationSlug": "<slug>", "credentials": { <production credentials from Step C1> }}Expected response: { "success": true }. This must pass against the production ERP before proceeding.
Step C3 — Run Instance Explorer Owner: ENG 🔍
If the Instance Explorer was built as part of the integration (SOP-OB-003 Phase 5), run it now against the production connection:
# Via Dagster UI or direct call:orchestrator.run_instance_explorer(connection_id)# Profile saved to erp_connections.extra_config["tenant_capability_profile"]Compare the automated findings against the manual discovery from Step A1:
- Did the explorer find any additional custom fields not mentioned during scoping?
- Does the entity availability match what customer IT said was licensed?
- Does the record count match expectations (or is data much larger/smaller than anticipated)?
- Any unexpected pricing engines or multi-branch structure?
Document discrepancies. If the explorer surfaces something new (e.g., a third-party pricing engine the customer didn’t mention), flag it immediately — it may require development work before order write-back is safe.
If the Instance Explorer was not built yet (deferred to Phase 2 work): fall back to the manual discovery findings from Step A1 to inform capability overrides in the next step.
Step C4 — Configure Capability Overrides Owner: ENG
Use the defaults from capabilities.py for the new ERP type (set in SOP-OB-003 Phase 9), adjusted by explorer findings from Step C3 (or manual discovery from Step A1 if explorer not yet built).
The ENG who built the integration must brief CS on any capability limitations before this step.
Step C5 — Configure Extra Config Owner: ENG
Set extra_config as appropriate, including the tenant_capability_profile from Step C3 if the explorer ran successfully.
Step C6 — Enable Flagsmith Flags Owner: ENG
Update the Flagsmith org identity to enable erp_sync_enabled = true and any other flags that were deferred in Step B2.
Step C7 — Initial Data Sync Owner: ENG
Identical to SOP-OB-001 Step 9. Trigger the initial full sync via Dagster for the new connection.
Step C8 — User Invites → UAT → Go-Live Owner: CS + CUST
Identical to SOP-OB-001 Steps 10–14. The process is identical once the integration is live.
7. Decision Points
Section titled “7. Decision Points”Sandbox Not Available from ERP Vendor
Section titled “Sandbox Not Available from ERP Vendor”- Do not build write operations (order submission Temporal workflows) without sandbox access
- Read-only sync (Dagster pipeline) can be built against production ERP data in a non-destructive manner — GET operations only
- Communicate clearly in the contract: order write-back is deferred until sandbox access is confirmed
- Timeline: customer must provide sandbox within 30 days of contract signing or write-back is scoped to a Phase 2
ERP API Is SOAP/XML (Not REST)
Section titled “ERP API Is SOAP/XML (Not REST)”No existing connector uses SOAP/XML. Budget 2–3 additional engineering days for a custom XML client. Identify this in Step A1 and update the scope estimate before committing to a timeline.
Direct Database Access Only (No REST API)
Section titled “Direct Database Access Only (No REST API)”If the ERP has no external API and only exposes data via ODBC/JDBC or direct SQL:
- Use the
database_connector.pypattern fromapps/dagster/erp_pipeline/sources/prophet21/as the reference - Requires the customer to open a firewall port and provide database-level read credentials
- Budget 2–4 additional engineering days for the DB connector + schema discovery
- Coordinate security requirements with CUST IT carefully (principle of least privilege)
Customer Requests Order Write-Back Before Read Sync Is Complete
Section titled “Customer Requests Order Write-Back Before Read Sync Is Complete”Do not allow this. The order matching and fuzzy lookup logic depends on having a populated local product and customer dataset. If write-back is attempted before read sync is complete, order submission will fail or produce garbage matches. Enforce sequencing: read sync must show at least one successful completed run before any write operations are enabled.
Integration Scope Expands Mid-Build
Section titled “Integration Scope Expands Mid-Build”If the customer requests additional entities or capabilities that were not scoped in A1:
- Assess the impact to the timeline
- Get customer written acknowledgment of the revised timeline
- Do not delay go-live for out-of-scope requests — build them as Phase 2
8. Milestone Gates and Customer Communication
Section titled “8. Milestone Gates and Customer Communication”| Milestone | Owner | Customer Communication |
|---|---|---|
| Contract signed | CS | Kickoff email: welcome + estimated timeline + what we need from them |
| Intake complete + scope confirmed | CS + ENG | Timeline confirmation email + blocker/risk list |
| Sandbox access confirmed | CUST + ENG | ”Unblocked — engineering starting” notification |
| Staging sync validated | ENG | ”Ready for onboarding” email to CS; CS notifies customer |
| Initial prod sync complete | ENG | Invite users; schedule UAT call |
| UAT passed | CS + CUST | Go-live confirmation email + support info |
| 30-day check-in | CS | Proactive health check: sync status, order volume, any issues |
9. Rollback and Offboarding
Section titled “9. Rollback and Offboarding”If the Integration Build Is Abandoned
Section titled “If the Integration Build Is Abandoned”- Mark the registry entry
status: 'draft'inregistry.ts— prevents new connections - Remove the orchestrator from
ERPSourceFactory._SUPPORTED_ERP_TYPESif the ERP type will not be offered to other customers - Archive all engineering artifacts (branches, PRs, docs) — do not delete
- Follow SOP-OB-001 Section 6 for the customer provisioning rollback
If Go-Live Must Be Rolled Back
Section titled “If Go-Live Must Be Rolled Back”Same as SOP-OB-001 Section 6.