Salesforce Integration Interview Questions: Inbound vs Outbound, API Types, Bi-directional & Best Practices
Salesforce Integration Interview Questions — Post 1: Integration Fundamentals
What is Integration, Inbound vs Outbound, Bi-directional, API Types, Methods & Patterns — Everything You Need for the First Round
| Without Integration | With Integration |
|---|---|
| Manual data re-entry between systems | Automatic real-time data sync |
| Data silos — each system sees partial picture | Unified 360° customer view |
| Delayed information — 1-2 day lag | Real-time or near-real-time data |
| Human errors during copy-paste | Automated, validated data transfer |
| Disconnected business processes | End-to-end automated workflows |
- ✅Eliminates duplicate data entry — data entered once, flows everywhere automatically
- ✅Enables cross-system business processes — Lead to Order to Invoice in one flow
- ✅Gives sales reps real-time visibility into ERP, payments, and delivery status
- ❌Integration is NOT just about moving data — it's about connecting business processes
- ❌Wrong integration pattern = data corruption, duplication, and performance issues
| Need | Example |
|---|---|
| Data Sync | Account data synced between Salesforce and ERP |
| Process Integration | Order approved in SF → auto-created in BC |
| UI Integration | ERP live data shown on Salesforce record page |
| Analytics Integration | Salesforce data fed to Power BI / Tableau |
Without integration: Sales team entered orders in Salesforce, finance team re-entered in Business Central manually — errors, delays, 2-day lag. With integration: Order created and approved in Salesforce → auto-pushed to BC → invoice generated → status synced back to SF. Manual entry completely eliminated.
- 🔥Integration is not optional in enterprise — every org connects to something
- 💡Always mention business value, not just technical — interviewers love this
- 💡Types: data sync, process integration, UI integration, analytics integration
- 💡Salesforce provides multiple methods — REST, SOAP, Bulk, Platform Events, MuleSoft
| Aspect | Inbound | Outbound |
|---|---|---|
| Who Initiates | External system | Salesforce |
| Salesforce Role | Server (API Provider) | Client (API Consumer) |
| What SF Does | Exposes an endpoint | Calls an external endpoint |
| Tools Used | @RestResource, webService keyword | HttpRequest, Named Credentials |
| Remote Site Settings | ❌ Not needed (SF is server) | ✅ Required (or Named Credential) |
| Auth Needed | External caller needs OAuth token | SF needs credentials to call out |
| Real Example | IndiaMART pushes leads into SF | SF pushes Order to Business Central |
- ✅Inbound = you build and expose the API — you control the contract
- ✅Outbound = you consume the API — the external party controls the contract
- ✅Inbound auth = external caller must present valid OAuth token to Salesforce
- ✅Outbound auth = Salesforce stores credentials securely in Named Credentials
- ❌Outbound callout cannot happen directly in trigger — needs async context (Queueable)
- ❌Direction has nothing to do with real-time vs async — both can be either
IndiaMART → Salesforce = Inbound (they call our @RestResource endpoint, we exposed the API, they push lead data in). Salesforce → Business Central = Outbound (we call their BC API using Named Credentials from a Queueable class, we push order data out).
- 🔥Always say "from Salesforce's perspective" — direction is always relative to SF
- 💡Inbound = expose API; Outbound = consume API — simple rule to remember
- 💡Named Credentials = best practice for outbound auth — never hardcode credentials
- 💡Trigger + outbound callout = always use async — Queueable or @future(callout=true)
| Direction | Example |
|---|---|
| SF → External (Outbound) | Order confirmed in SF → pushed to BC |
| External → SF (Inbound) | BC updates invoice status → synced back to SF |
| Both happening = Bi-directional ✅ | SF ↔ BC full sync |
| Field | Owner (Source of Truth) | Rule |
|---|---|---|
| Order Status | Business Central | BC always wins, SF is read-only for this field |
| Customer Name | Salesforce | SF always wins, BC follows |
| Invoice Number | Business Central | BC generates, SF stores for reference |
| Shipping Address | Salesforce | SF wins, BC syncs from SF |
- ✅Requires field-level source of truth mapping — not just object level
- ✅Bypass flags (like
BC_Sync_In_Progress__c) prevent infinite trigger loops - ✅Idempotency key ensures same message processed twice = no duplicate records
- ✅Middleware (MuleSoft, Azure) handles this better than point-to-point for complex scenarios
- ❌Without loop prevention — triggers fire indefinitely, hitting governor limits
- ❌Source of truth must be defined before any code is written — not after
Salesforce ↔ Business Central is fully bi-directional. SF Order confirmed → Queueable pushes to BC (Outbound). BC updates invoice status → calls SF @RestResource to update order (Inbound). Used BC_Sync_In_Progress__c bypass checkbox to prevent the trigger loop. BC owns: Invoice No, Payment Status. SF owns: Customer info, Line Items.
- 🔥Loop prevention = #1 concern in bi-directional — always mention it first
- 💡Source of truth = field by field, not just object level — shows depth
- 💡Idempotency — same message processed twice should not cause duplicate records
- 💡Middleware (MuleSoft) manages conflict resolution better for complex multi-system scenarios
| Method | Direction | Best For |
|---|---|---|
| REST API | Both | Modern lightweight integrations, mobile apps |
| SOAP API | Both | Legacy enterprise systems requiring XML/WSDL |
| Bulk API 2.0 | Both | Large data volumes — millions of records |
| Streaming API / CDC | Outbound (push) | Real-time notifications to external subscribers |
| Platform Events | Both | Async pub-sub, cross-org, decoupled architecture |
| Apex HTTP Callout | Outbound | Custom outbound integrations with business logic |
| @RestResource (Apex REST) | Inbound | Custom inbound endpoints with custom logic |
| MuleSoft / Middleware | Both | Complex multi-system enterprise integrations |
| Salesforce Connect | Inbound (virtual) | External data without storage — External Objects |
| Outbound Messaging | Outbound | Workflow-triggered SOAP messages to external |
| ETL Tools (Data Loader) | Both | Batch data migration and periodic bulk sync |
| External Services | Outbound | Declarative REST integration for admins — no Apex |
| Scenario | Best Method |
|---|---|
| External app calls SF to create records | REST API / @RestResource |
| SF pushes data to ERP on record change | Apex HTTP Callout in Queueable |
| Load 1 million records from legacy system | Bulk API 2.0 |
| Notify external system of every SF change | Change Data Capture (CDC) |
| Real-time pub-sub across org boundary | Platform Events |
| Show ERP data live on SF page (no storage) | Salesforce Connect |
| Complex routing between 5+ systems | MuleSoft |
- ✅No single "best" method — always say "depends on use case"
- ✅Bulk API for volume, REST for modern, SOAP for legacy, Platform Events for decoupled async
- ✅MuleSoft for complex multi-system — hub-and-spoke vs spaghetti point-to-point
- ❌Using REST API for bulk operations (1M+ records) = wrong choice — use Bulk API
- ❌Polling when webhooks are available = inefficient — prefer event-driven
BC sync → Apex HTTP Callout (outbound, custom logic). IndiaMART leads → Scheduled polling + @RestResource (inbound). Annual product data migration → Data Loader (Bulk API) for 25,000+ items. If we integrated 5 systems simultaneously → MuleSoft to avoid maintaining 5 separate codebases.
- 🔥Listing all methods + knowing WHEN to use each = strong candidate signal
- 💡REST API is the default modern choice — always start here, move to others for specific needs
- 💡Platform Events is the modern standard for async — replacing old Outbound Messaging
- 💡Salesforce Connect = no storage — data always live from source, end in __x
| API | Purpose | Protocol |
|---|---|---|
| REST API | CRUD on standard/custom objects | HTTP + JSON |
| SOAP API | CRUD via XML — legacy systems | SOAP + XML |
| Bulk API 2.0 | Process large data sets (millions) | HTTP + CSV/JSON |
| Metadata API | Deploy/retrieve org metadata | SOAP |
| Tooling API | Dev tools, code coverage, debug | REST |
| Streaming API / CDC | Real-time push notifications | CometD |
| Apex REST | Custom business logic endpoints | HTTP + JSON |
| Apex SOAP | Custom SOAP endpoints | SOAP + XML |
| Code | Meaning | Action |
|---|---|---|
| 200 OK | Success | Process response |
| 201 Created | Record created | Use returned ID |
| 400 Bad Request | Your data is wrong | Fix payload — don't retry |
| 401 Unauthorized | Invalid/expired token | Refresh token, retry once |
| 403 Forbidden | No permission | Fix permissions — don't retry |
| 404 Not Found | Endpoint wrong | Fix URL — don't retry |
| 429 Rate Limited | Too many requests | Wait + retry with backoff |
| 500 Server Error | Their problem | Retry up to 3 times |
| 503 Unavailable | Service down | Queue + retry later |
- ✅API = the contract between systems — endpoint, method, request, response
- ✅Salesforce is both API provider (inbound) and API consumer (outbound)
- ✅REST API uses HTTP verbs: GET (read), POST (create), PUT/PATCH (update), DELETE
- ❌4xx errors = client's fault (your code/data); 5xx = server's fault (their system)
- ❌Never retry 4xx — fix the data first; always retry 5xx with backoff
BC exposes a REST API. The API contract (what fields to send, what URL, what auth) was shared by the BC team as a Postman collection. We built Apex HTTP Callouts based on that contract. When BC returned 400 — it meant our payload was wrong. When they returned 503 — their server was down, we queued and retried after 30 minutes.
- 🔥Know 4xx vs 5xx — 4xx = your fault, don't retry; 5xx = their fault, retry
- 💡REST is stateless — each request carries all needed information, no session state
- 💡Always use HTTP verbs correctly — POST for create, PATCH for partial update, PUT for full replace
- 💡API versioning (/v59.0/) matters — always specify version to avoid breaking changes
| Feature | REST API | SOAP API | Bulk API 2.0 | Streaming API |
|---|---|---|---|---|
| Protocol | HTTP | SOAP/XML | HTTP | CometD |
| Format | JSON / XML | XML only | CSV / JSON | JSON |
| Best For | General CRUD | Legacy systems | Large volumes | Real-time push |
| Records Per Call | 200 (composite: 500) | 200 | 150 million+ | N/A (push) |
| Direction | Both | Both | Both | Outbound push |
| Speed | Fast | Slower | Slow (async) | Real-time |
| Async? | ❌ Sync | ❌ Sync | ✅ Always async | ✅ Push model |
| Contract | Optional (Swagger) | Mandatory WSDL | Job-based | CometD channel |
| Type | Channel | Use Case |
|---|---|---|
| PushTopic | /topic/MyPushTopic | Monitor SOQL-based record changes (legacy) |
| Platform Events | /event/My_Event__e | Custom business events — preferred |
| Change Data Capture | /data/AccountChangeEvent | Field-level changes for full sync |
| Generic Streaming | /u/MyChannel | Custom non-record notifications |
- ✅REST = default choice for all modern integrations — fast, lightweight, JSON
- ✅Bulk API = only option for 100k+ records — async job-based processing
- ✅Streaming API = only option for real-time push (no polling needed)
- ✅SOAP = when 3rd party mandates WSDL contract — use WSDL2Apex to generate stub classes
- ❌Platform Events preferred over PushTopics for new development — PushTopics are legacy
- ❌All four require OAuth 2.0 + Connected App for external access
REST API — BC daily order sync (few hundred orders, custom logic needed). Bulk API — Annual product catalogue migration (25,000+ items via Data Loader). Platform Events (Streaming) — Real-time order status from external system. SOAP API — Legacy government compliance system that only supports WSDL — used WSDL2Apex to generate stub classes.
- 🔥REST = modern default; Bulk = volume; Streaming = real-time push; SOAP = legacy — memorize this
- 💡CDC (Change Data Capture) = field-level change tracking — best for full external sync
- 💡Bulk API barely counts against daily API limit vs REST — huge advantage for large operations
- 💡Replay ID in Streaming API — catch missed events from last 72 hours — shows depth
| Aspect | Real-time | Batch / Scheduled |
|---|---|---|
| Trigger | Event-driven (record save, approval) | Time-driven (every hour, nightly) |
| Delay | Seconds | Minutes to hours |
| Volume per run | Low (1-200 records) | High (thousands to millions) |
| Use case | Order confirmed → push to ERP | Nightly product sync, monthly report |
| SF Tool | Queueable, @future, Platform Events | Batch Apex, Scheduled Flow, ETL |
| Governor limits | Per-transaction limits apply | Fresh limits per batch chunk |
| Error handling | Per-record — retry queue | Batch error report — reprocess failures |
| Complexity | Higher — race conditions, retries | Lower — simpler error handling |
- ✅Real-time = critical data (payment, order) — user/system expects immediate response
- ✅
Batch = non-critical or high-volume data — nightly sync, report generation - ✅Batch gets fresh governor limits per chunk — handles millions of records safely
- ✅Near-real-time (Platform Events) = middle ground — seconds delay, decoupled
- ❌Real-time for everything = hits callout limits fast (100 per transaction)
- ❌Batch for critical data = business can't wait hours for payment confirmation
Three sync strategies used simultaneously: Real-time — Order Confirmed → Queueable pushes to BC immediately (critical). Near-real-time — BC invoice status update → Scheduled every 15 minutes (important but not critical). Batch — Product catalogue sync → Scheduled nightly at 2AM (25,000+ items, non-critical timing).
- 🔥Match strategy to business criticality — not technical preference
- 💡Delta sync = only process changed records (LastModifiedDate) — reduces both real-time and batch load
- 💡Batch Apex size 10 for callout-heavy batches — 10 records × 10 callouts = 100 limit safe
- 💡Platform Events = best of both — near-real-time AND decoupled AND durable 72hr replay
| # | Practice | Why It Matters |
|---|---|---|
| 1 | Always use Named Credentials | No hardcoded secrets — security standard |
| 2 | Never mix DML + Callout in same transaction | Apex throws CalloutException — use async |
| 3 | Log every integration transaction | Debug production issues in minutes, not hours |
| 4 | Classify errors (4xx vs 5xx) | Don't retry bad data — fix it; retry server errors |
| 5 | Use Idempotency Keys | Prevents duplicate records on retry |
| 6 | Always set request timeout | Prevent hanging transactions (max 120s) |
| 7 | Bulkify outbound callouts | Stay within 100 callout per transaction limit |
| 8 | Cache OAuth tokens | Reduce from 2 callouts to 1 — performance |
| 9 | Delta sync — only changed records | Reduces 50,000 calls to 50 — dramatic improvement |
| 10 | Mock callouts in test classes | Code coverage + reliable CI/CD pipeline |
- ✅Named Credentials = secrets encrypted, URL centralized, auth auto-injected
- ✅Queueable = solves DML+callout restriction AND gives retry capability AND monitoring
- ✅Integration_Log__c = persistent, queryable, dashboardable audit trail for every callout
- ✅Idempotency key (Order.Id + timestamp) = same request twice = no duplicate in external system
- ❌Hardcoded tokens in Apex or Custom Labels = visible to all admins = security red flag
- ❌No error logging = production incidents take hours to debug instead of minutes
All BC integrations follow all 10 practices: Named Credentials (encrypted), Queueable async (solves DML restriction), Integration_Log__c for every transaction, retry max 3 for 5xx errors, idempotency key = Order Id + timestamp, 120s timeout, delta sync using LastModifiedDate (reduced API calls from 500/day to 20/day), token cached in Protected Custom Setting.
- 🔥Mention at least 5 practices — async, logging, Named Credentials, bulkify, error classification
- 💡"No secrets in code" — instant security signal that impresses senior interviewers
- 💡Idempotency is advanced — mentioning it separates junior from senior candidates
- 💡Circuit breaker pattern = senior-level — prevents hammering a failing external system