view .md
How to · Certify

Marketplace listing: from internal app to a public HubSpot Marketplace listing.

HubSpot Marketplace is a curated catalog and a real review, not a publish button. This page walks through every artifact a 2026 reviewer will actually open: the security questionnaire, the sensitive-scope justification, the platform-version requirement, the listing copy, and the five reasons most submissions get bounced. By the end you'll have a submission you can defend in writing.

Time
≈ 30 min
Outcome
A submission-ready HubSpot Marketplace listing: security questionnaire answered, sensitive-data scopes justified, supported-version requirement met, listing copy written, screenshots captured — with a realistic understanding of the review timeline (HubSpot targets up to 60 days from the time they share feedback) and the most common rejection reasons.
Prerequisites
  • A working HS-X project deployed to production (see /docs/guides/getting-started).
  • A HubSpot app already created in your developer account, with at least one paying or pilot install on a non-developer portal.
  • A public-facing privacy policy, terms of service, and support URL — these are required questionnaire fields, not nice-to-haves.
  • Roughly 30 minutes for reading and form-filling. Expect up to 60 days from the time HubSpot shares feedback as a separate budget.

Before you begin

The HubSpot Marketplace is a curated catalog. The team running it has the same incentive any app-store reviewer has: keep the catalog something the platform owner is proud to recommend. Getting listed is a review, not a publish, and the reviewer is a human who opens your install URL, clicks around, and reads your privacy policy. The clearer you make their job, the faster you get out of the queue.

There are five concerns the reviewer works through, in roughly this order. Get all five right and the review is short. Miss one and you bounce, usually with a one-line reason and a four-week wait before you can resubmit.

The five reviewer concerns, in order

  1. Security. OAuth handling, token storage, the scopes you ask for, and what happens when something goes wrong. The May 2026 update expanded the OAuth/token sections of the questionnaire and a lot of the new fields are about sensitive-scope justification.
  2. Reliability. Does the app stay up? Does it handle HubSpot's 429s gracefully? Does it degrade or just throw on a transient failure? Reviewers test this by installing on a clean portal and watching for visible errors during the first 24 hours.
  3. UX. Does install actually work? Does the app communicate state (loading, empty, error) instead of staring blankly at the user? Is there a path to uninstall and re-install without manual support?
  4. Accuracy. Does what the listing claims match what the app does? If your one-liner says "syncs Salesforce opportunities" and the reviewer can't find an opportunity sync inside the app within 60 seconds of installing, that's a rejection.
  5. Brand fit. Is the app something HubSpot is comfortable recommending? This is the soft criterion and the one most under-prepared founders skip. A perfectly secure app that overlaps 90% with HubSpot's native CRM is a harder sell than a perfectly secure app that fills an obvious gap.

The rest of this guide walks the five concerns in order, with the exact artifacts each one asks for.

What HS-X handles for you (so you can skip those sections)

HS-X auto-generates the OAuth install URL, handles BAD_REFRESH_TOKEN recovery with a re-install nudge, pins your manifest to a supported platform version, and routes 429s through a rate-limit-aware HTTP client. The reviewer-facing surface is still yours, but the load-bearing parts of "yes the OAuth flow works" are handled. The places you still have to write something yourself are the questionnaire answers, the scope justifications, and the listing copy — and those are exactly what the rest of this guide covers.

Pre-flight: from 'works on my portal' to OAuth-ready

Most pre-marketplace apps are subtly portal-coupled. They were built and tested on one developer portal, with one OAuth token, against one set of properties. The marketplace reviewer installs on a fresh portal with a different account topology, different custom properties, and a user role that may not match yours. Pre-flight is the exercise of making the app behave correctly under that mismatch.

Scope minimization

Ask for the narrowest scopes that let your features work, and nothing else. Reviewers explicitly look at the scope list on install and flag any scope whose use is not obvious from the listing description. A common 2026 rejection is "asks for crm.objects.contacts.write but the listing only describes a reporting feature."

// hs-x.toml — declare scopes once, the manifest is generated from this.
[app]
name = "Acme Pipeline Reports"
scopes = [
  "crm.objects.contacts.read",
  "crm.objects.deals.read",
  // No write scopes. This is a reporting app.
]

If a feature inside your app needs a broader scope (say, the ability to update a deal stage from a custom card), declare it as an optional scope and gate the feature behind it. The reviewer sees a smaller required-scope list at install and a clearly named optional permission users opt into separately.

BAD_REFRESH_TOKEN recovery

HubSpot refresh tokens rotate. Tokens get revoked when a portal admin uninstalls and reinstalls, when a user is removed from a portal, or when HubSpot rotates the underlying app secret. Every production install hits this within the first few weeks. The reviewer will not test this directly, but they will install, uninstall, and reinstall on the same portal — and if your app crashes on the second install because it cached a stale token, that's an immediate bounce.

import { defineWorker } from '@hs-x/sdk';
 
export default defineWorker(({ worker }) => {
  worker.onTokenError(async ({ portalId, error, reauthUrl }) => {
    if (error.code === 'BAD_REFRESH_TOKEN') {
      // Mark the install dormant; surface a banner in the UI extension
      // that links the user to reauthUrl.
      await worker.installs.markStale(portalId, { reauthUrl });
    }
  });
});

The reauthUrl HS-X hands you is the full install URL with the original scopes pre-filled. Drop it into a Banner component on every UI extension and the user can self-recover without a support ticket.

Install URL builder and install error handling

A live install URL is required for submission. Build it from your app's client ID, scope list, and redirect URI — and confirm you're hitting HubSpot's current OAuth endpoints (the 2026 update migrated to the v3 OAuth endpoints; double-check the OAuth quickstart before pasting). Keep the URL's scope list in sync with hs-x.toml; the reviewer compares scope-list-on-install against listing-page-claim.

Design preview

A dedicated hs-x marketplace install-url subcommand is on the roadmap but not yet shipped. For now, assemble the URL by hand from the values in your app config, or copy the install URL HubSpot surfaces in the developer-portal app settings.

For install error handling, the rule is simple: if anything fails during the OAuth callback, show a page that names the error and links to your support URL. The most common bounce in this area is "install loop" — the OAuth callback throws, the user gets bounced back to the consent screen, they click approve again, the callback throws again. See step 6 for the fix pattern.

Secrets handling (where the refresh token lives, who can read it, how it's rotated) is covered separately. The reviewer will ask in the questionnaire how you store tokens at rest — read How to · Secrets before you fill out step 2.

The security questionnaire

The questionnaire is the single longest artifact in the submission. The May 2026 update expanded the OAuth/token sections; the form spans data handling, access control, incident response, and sensitive-scope justification. Most are short text answers; a handful are essay-length and those are where reviewers spend their time. This section gives you concrete answers for the essay questions — not topics, the actual text you can paste in and adapt.

Data residency

The reviewer wants to know where data is processed, where it is stored, and whether a customer in the EU can install your app and have their data stay in the EU. With HS-X, the honest answer is: it's processed wherever the customer's Cloudflare account is, and stored wherever the customer's Cloudflare bindings live. This is a stronger answer than most apps can give.

"Customer data is processed on Cloudflare Workers running in the customer's own Cloudflare account, which the customer provisions during install. The processing region follows the customer's Cloudflare account region (na, eu, ap). No copy of customer data is stored on our infrastructure; all persistence (KV, D1, R2) is in customer-owned bindings. Logs that incidentally include record IDs are retained for 7 days in the same region and then deleted."

If you do hold any data centrally — even just an email address for billing — name it explicitly. Reviewers prefer one honest paragraph over a too-broad "no data is stored" claim that they can disprove with a single network request.

Deletion on uninstall

When a portal admin uninstalls your app, a common recommendation from the security questionnaire is to delete any data you hold about that portal promptly (teams often quote a 30-day ceiling as good practice). The reviewer will test this by installing on a test portal, populating data, uninstalling, and then asking you in writing whether the data is gone. Wire the deletion to the uninstall webhook, not to a nightly cron, so you can answer "deleted within 5 minutes."

export default defineWorker(({ worker }) => {
  worker.on('app.uninstalled', async ({ portalId }) => {
    await worker.kv.deleteByPrefix(`portal:${portalId}:`);
    await worker.d1.exec('DELETE FROM events WHERE portal_id = ?', [portalId]);
    await worker.installs.markDeleted(portalId);
  });
});

"On receipt of the app.uninstalled webhook from HubSpot, all data associated with the uninstalling portal is deleted from KV, D1, and R2 within five minutes. The portal's install record is marked deleted (not retained as a tombstone) and the audit log retains only the portal ID and deletion timestamp for 90 days for compliance purposes."

Breach notification SLA

A real number, in hours, not "as soon as practicable." The 2026 questionnaire flags soft language here. A common recommendation from the security questionnaire is 72 hours from confirmed breach to customer notification — it isn't an enumerated marketplace rule, but it's the bar most reviewers expect you to clear. Match it or beat it.

"In the event of a confirmed security breach affecting customer data, we notify affected customers via email to the portal admin and the support contact on file within 72 hours of confirmation, with a follow-up incident report within 7 days. The notification includes the scope of affected data, the timeline, the remediation steps taken, and a point of contact for follow-up questions."

Sensitive-scope justification

Step 3 covers this in full because it is the single most-rejected questionnaire section in 2026.

Sensitive-scope justification — the 2026 rule

Some OAuth scopes are flagged sensitive and require a written justification at submission. The exact list and the format HubSpot wants you to use both move around — check the current app marketplace listing requirements before you write yours, and treat that page as canonical.

The shape of a justification that tends to land: name the user-visible feature that requires the scope, then name the safeguards (what you write, when, what you don't touch, how conflicts resolve). Keep it specific. "We sync data" with no feature named or no conflict rule is the most common rewrite request.

What does not work

Do not bundle a sensitive scope into the required list "in case we need it later." The justification reviewer asks "what feature today uses this scope," and if the answer is "future roadmap," the listing is rejected. Add the scope when the feature ships, not before.

Listing copy: the four required artifacts

The listing page is your conversion surface. A reviewer reads it for accuracy. A prospective customer reads it for fit. The same copy has to satisfy both. Four artifacts are required, and each has a pattern that converts.

The one-liner (≤80 characters)

This is the headline next to your app icon in marketplace search results. The pattern that converts: a verb, a noun the user recognizes, and a payoff. Skip the company name, skip "the best," skip adjectives.

  • Bad: "Acme Tools — the best Salesforce integration for HubSpot users." (puffery, no payoff)
  • Better: "Sync Salesforce opportunities into HubSpot deals every 5 minutes."
  • Bad: "AI-powered conversation intelligence for revenue teams." (vague, no concrete output)
  • Better: "Score sales calls and write the summary into the contact timeline."

The description

Roughly 200–400 words, structured as: problem → who has it → what the app does in one sentence → how install works in three steps → who it integrates with. The reviewer is checking the third bullet against the actual install. The customer is reading the first two. Keep paragraphs short.

Sales teams using both Salesforce and HubSpot lose 2–3 hours a week
reconciling opportunity records between the two systems. If you've ever
emailed your ops lead to ask "is this deal in the right stage?", this app
is for you.
 
Acme Pipeline Sync mirrors Salesforce opportunities into HubSpot deals
every 5 minutes, with deterministic conflict resolution and a visible
audit log.
 
To install:
1. Click Install on this page and grant the requested scopes.
2. Connect your Salesforce account on the welcome screen.
3. Pick the Salesforce pipelines you want to mirror — done.
 
Works with: Salesforce Professional, Enterprise, and Unlimited editions.
Pulls opportunity, account, and contact records. Does not modify your
Salesforce data; writes only into HubSpot.

The install walkthrough

A linear, screenshot-backed walkthrough of the first 90 seconds after Install. Three to five screens, each with a one-sentence caption. Reviewers use this as the test script when they install your app — if step 4 of your walkthrough shows a "connect Salesforce" button and they can't find that button after Install, the listing fails accuracy review.

Screenshots and video

Three to six screenshots minimum, captured from a real portal with realistic data. Stock-looking screenshots — three contacts named "John Doe," empty pipeline columns, lorem-ipsum company names — are a common reason we see listings sent back ("screenshots not from a real portal"). Use a dev portal seeded with the kind of data your target customer would have. A 60–90 second video is optional but generally helps install conversion.

Design preview

An hs-x marketplace diff subcommand that compares your local marketplace.toml against the live draft is planned but not yet shipped. Today, hand-diff the listing form against your local copy before resubmitting.

The platform-version supported requirement

HubSpot's May 2026 changelog lists both 2025.2 and 2026.03 as currently supported platform versions for new listings — either one is fine, as long as you target a currently supported version. Older versions outside that supported set cannot be listed. The HS-X CLI defaults new projects to 2026.03.

Check your current version in hs-x.toml:

[platform]
version = "2025.2"   # supported
# version = "2026.03"  # also supported, and the HS-X default

Before you submit, confirm your last deploy ran against a currently supported version. HubSpot's supported platform versions page is the source of truth — re-check it when you submit, because the supported set rolls forward over time.

Multi-environment setup (which Cloudflare account ID and which HubSpot portal each platform version targets) is covered in How to · Environments. Get that wired before you submit, so the reviewer's test portal lands on your prod environment, not your dev.

Common rejection reasons and how to dodge them

Five reasons we commonly see listings sent back. Each one has a specific fix. Run through the table before you submit — most teams get bounced on something they could have caught in 20 minutes of self-review.

Common reason we seeWhat the reviewer sawThe fix
OAuth install loopClicked Install, granted scopes, callback threw, bounced back to consent. Tried twice. Gave up.Wrap the callback handler in a try/catch that renders a named error page with a support link. Use HS-X's worker.onInstallError hook (renders a default error page if you don't override it).
Sensitive scope unjustifiedA scope in the sensitive category was requested without a feature-specific justification, or the justification said "future use."Step 3. Justify per scope, name the feature, name the safeguards. If the feature is opt-in, declare the scope optional.
No uninstall data deletionInstalled, populated data, uninstalled, asked in writing whether data was deleted; answer was vague or "deleted within 30 days."Wire deletion to the app.uninstalled webhook, complete within 5 minutes, retain only a portal-ID tombstone. Quote the 5-minute number in the questionnaire.
Screenshots not from a real portalScreenshots showed "John Doe", empty pipelines, lorem-ipsum data.Use a dev portal seeded with realistic data. The reviewer compares screenshots against the live app on their test install — too much polish in the screenshot vs the install is also a flag.
Listing claim does not match feature surfaceOne-liner promised "Salesforce opportunity sync." Reviewer installed, couldn't find an opportunity sync inside the app within 60 seconds.The third bullet of your description (the "what the app does in one sentence") must point to a UI element the reviewer can find on first install. If it lives behind a settings toggle, name the toggle.

What happens after submission

HubSpot's listing-requirements doc states the review/feedback loop should take no more than 60 days from the time HubSpot shares feedback — expect up to that long, and longer when sensitive scopes are involved. You'll get one or two rounds of questions from the reviewer in writing — answer the same day if you can, because every reply restarts a multi-day clock on their side.

You can ship updates to the underlying app during review without resubmitting the listing, as long as you don't change the scope list or break the install walkthrough. Scope changes mid-review reset the security clock. Listing copy changes mid-review reset the accuracy clock. Save both for after approval.

Where next

  • How to · Billing — once the listing is live, wire usage-based or seat-based billing so installs actually generate revenue. HubSpot does not currently operate a marketplace billing system; you bring your own (Stripe, etc.) and the billing guide covers the wiring.
  • How to · Secrets — the questionnaire's "how do you store tokens at rest" section maps directly onto HS-X's secrets handling, and the answer is short if you've already read this guide.
  • How to · Environments — keeping a clean prod environment separate from your dev and staging portals is what lets the marketplace reviewer land on the right install without you scrambling at the last minute.