HubSpot ↔ Oracle NetSuite
Closed in HubSpot. Billed in NetSuite. “Paid” in Slack.
Revenue teams work in HubSpot, finance works in NetSuite, and the moment that matters to both — the customer paying — usually reaches sales last. Deals close, someone recreates them as sales orders, and the account owner hears about payment from a spreadsheet, or doesn’t. PartnerMCP connects the three: a closed HubSpot deal becomes a NetSuite customer and sales order, billing status flows back to the deal, and when NetSuite applies the payment, the deal owner hears it in Slack.
You
“Whenever a deal closes in HubSpot, create the customer and sales order in NetSuite. When payment arrives, update HubSpot and notify the account owner in Slack.”
PartnerMCP· I will:
- Detect Closed Won deals in HubSpot — deal.
propertyChange on dealstage, checked against each pipeline’s won stage. - Match or create the customer in NetSuite with one upsert by external ID (eid:), keyed on the HubSpot company’s record ID.
- Create the sales order from the deal’s line items — entity, item, quantity, rate — with the deal’s record ID as its external ID.
- Monitor invoice and payment status in NetSuite with SuiteQL on lastmodifieddate.
- Update the HubSpot deal with the sales order number, invoice status and payment date.
- Notify the account owner in Slack with chat.
postMessage when the payment is applied — the deal’s HubSpot owner, matched by work email. - Retry temporary failures automatically, within NetSuite’s account concurrency and HubSpot’s 10-second limits.
- Send unresolved errors for review, with the NetSuite or HubSpot message attached.
- Deal · Closed Won — HubSpot: Trigger · webhooks
- Customer lookup — PartnerMCP: companies ⇄ customer
- Schema mapping — PartnerMCP: fields · products · prices
- Create / update customer — NetSuite: customer
- Create sales order — NetSuite: salesorder + item sublist
- Monitor order — PartnerMCP: invoice · payment
- Sync fulfillment — NetSuite: itemfulfillment
- Watch payment — NetSuite: invoice → customerpayment
- Update Deal — HubSpot: payment status
- Notify owner — Slack: Slack · chat.postMessage
What syncs, and which way.
Every record that moves between HubSpot and NetSuite: what starts it, and what it produces on the other side.
HubSpot to Oracle NetSuite:
Deal → salesorder- When
- deal.
propertyChange on dealstage, into a won stage - Result
- NetSuite sales order with the deal’s line items; its external ID is the deal’s record ID.
HubSpot to Oracle NetSuite:
Company → customer- When
- First closed deal for the company
- Result
- Customer upserted through eid:; NetSuite’s internal ID stored on the company.
Oracle NetSuite to HubSpot:
invoice → Deal- When
- SuiteQL poll finds an invoice created or changed for the order
- Result
- Invoice number and status on the deal.
Oracle NetSuite to HubSpot:
customerpayment → Deal + Slack- When
- Payment applied to the order’s invoice
- Result
- Paid date on the deal, and a Slack message to the deal owner with the amount and the invoice.
Oracle NetSuite to HubSpot:
inventoryitem → products- When
- Item changes in NetSuite, found with SuiteQL
- Result
- HubSpot products carry the NetSuite item reference in hs_
sku, so each line item maps to a real item.
Field by field.
Every mapping PartnerMCP proposes, with its transformation and confidence. Rules — keys, reconciliation, duplicate guards — carry no confidence: they’re decided and approved, not inferred.
companies.
hs_ object_ id to customer · eid:<record ID>
PUT creates or updates in one call
97% confidencecompanies.
name to customer.
companyName Trimmed to the field’s length
97% confidencecustomer · internal ID
to companies.
netsuite_ customer_ id (custom) Written back after the upsert
95% confidencedeals.
hs_ object_ id to salesorder · eid:<deal record ID>
Looked up before every create
RuleHubSpot can deliver the same event twice; the external ID makes the second one harmless.Associated company
to salesorder.
entity The customer’s internal ID
96% confidenceNetSuite fills many order fields from the entity.products.
hs_ sku (via line_ items. hs_ product_ id) to item.
items[]. item Resolved to the item’s internal ID
93% confidenceline_
items. quantity to item.
items[]. quantity Copied as-is
97% confidenceline_
items. price to item.
items[]. rate Or left to NetSuite’s pricing when finance owns price
86% confidencedeals.
amount to Sales order total — reconciled, not written
Compared after SuiteTax calculates tax
RuleSales order number
to deals.
netsuite_ order_ no (custom) Written back after create
96% confidencecustomerpayment · applied to the order’s invoice
to deals.
netsuite_ paid_ date (custom) Payment date and amount
93% confidencedeals.
hubspot_ owner_ id to Slack user (chat.
post Message) Owner matched to a Slack user by work email
90% confidenceWith no match, the message goes to a channel you choose.
Edge cases, handled.
What goes wrong between HubSpot and NetSuite in production, and what PartnerMCP does about it.
- 01
Won stages are per pipeline
HubSpot’s dealstage holds an internal ID, and each pipeline has its own. PartnerMCP reads the pipelines API and treats closed stages with probability 1.0 as won, so a second sales pipeline or a renamed stage doesn’t silently stop orders reaching NetSuite.
- 02
At-least-once webhooks
HubSpot sends up to 100 events per request, retries failures up to 10 times over 24 hours, makes no ordering promise and doesn’t guarantee that eventId is unique. PartnerMCP de-duplicates on the deal itself and looks for salesorder/eid:<deal ID> before creating anything.
- 03
NetSuite has no outbound webhooks
NetSuite doesn’t push changes out on its own. PartnerMCP polls with SuiteQL on lastmodifieddate by default; for faster updates it can deploy a SuiteScript User Event script that calls out after save, with the heavy work queued to a scheduled or map/reduce script so saves never wait on the network.
- 04
Paid means applied
A payment can cover part of one invoice or several invoices at once. PartnerMCP updates the deal when a payment is applied to the deal’s invoice, shows partial payments as partial and sends the owner one message per payment, never one per retry.
- 05
Fulfillment may create the invoice
Without Advanced Shipping, NetSuite combines fulfillment and invoicing: creating the item fulfillment also creates the invoice. With it, they are separate steps. PartnerMCP reads which way your account works before it maps billing status back to HubSpot.
- 06
A pool shared with everyone
Your NetSuite account has one concurrency limit for every integration — REST, RESTlets, SOAP and the AI Connector Service — so a busy sync can starve another. PartnerMCP stays inside the allocation set on its integration record and backs off instead of competing.
- 07
Slack is rate-limited too
chat.
postMessage generally allows about one message per second per channel, and Slack answers 429 with Retry-After beyond that. PartnerMCP spaces notifications, honors Retry-After and keys each message on the payment, so nobody gets the same “paid” twice.
Questions about HubSpot and NetSuite.
Does the account owner need to be in Slack?
No. If PartnerMCP can’t match the HubSpot deal owner to a Slack user by work email, it posts to a channel you choose — or skips the message — and the deal is updated either way.
Can we use HubSpot’s or NetSuite’s MCP servers?
Both exist: HubSpot’s remote MCP server, generally available since April 2026, and NetSuite’s AI Connector Service. They’re built for assistants working under a user’s permissions — the AI Connector’s SuiteQL tools are read-only, and it doesn’t accept the Administrator role. PartnerMCP runs the deal-to-cash flow on the REST APIs and webhooks, and can use either MCP server for conversational access.
How does it handle HubSpot’s API limits?
HubSpot private apps get 100 or 190 requests per 10 seconds depending on your tier, plus a daily limit that every app in the account shares; CRM search has its own limit of five requests per second. PartnerMCP reads and writes in batches by unique-identifier property and leaves headroom for your other apps.
How quickly does “paid” reach Slack?
As fast as the polling interval you choose for SuiteQL — or right after the payment is saved, if you let PartnerMCP deploy a SuiteScript User Event script in NetSuite that calls out.
Which NetSuite records does it touch?
It writes customers and sales orders and reads items, invoices and customer payments — through a dedicated role limited to those records, not an administrator.
Vendor documentation.
The public documentation behind the technical details on this page.
- HubSpot — deals API guidedevelopers.hubspot.com (opens the vendor’s site in a new tab)
- HubSpot — pipelines API guidedevelopers.hubspot.com (opens the vendor’s site in a new tab)
- HubSpot — webhooksdevelopers.hubspot.com (opens the vendor’s site in a new tab)
- HubSpot — API usage guidelines and limitsdevelopers.hubspot.com (opens the vendor’s site in a new tab)
- NetSuite — upsert with external IDsdocs.oracle.com (opens the vendor’s site in a new tab)
- NetSuite — creating a sales order over RESTdocs.oracle.com (opens the vendor’s site in a new tab)
- NetSuite — item fulfillment REST recorddocs.oracle.com (opens the vendor’s site in a new tab)
- NetSuite — concurrency governancedocs.oracle.com (opens the vendor’s site in a new tab)
- NetSuite — AI Connector Service FAQdocs.oracle.com (opens the vendor’s site in a new tab)
- Slack — Web API rate limitsdocs.slack.dev (opens the vendor’s site in a new tab)
Product names and logos are trademarks of their respective owners. Their use indicates compatibility only and does not imply endorsement or partnership.
§06Build
Build this integration.
Start from this plan, or change it in your own words. PartnerMCP builds it against your HubSpot and NetSuite: sandbox first, production when you approve.