# Integration

Set up Fours to manage your Google Cloud Marketplace and Producer Portal on your behalf — listings, private offers, entitlements, and metering, all from one place.

---

## Overview

To sell on Google Cloud Marketplace, your organization must join [Google Cloud Partner Network](https://partners.cloud.google.com) and be approved as a [Google Cloud Marketplace vendor](https://cloud.google.com/marketplace/docs/partners/offer-products#vendor-agreement). See Google's [requirements for your organization](https://cloud.google.com/marketplace/docs/partners/get-started#requirements_for_your_organization) for the full list.

Once you're an approved vendor and the integration is in place, Fours can manage product listings, private offers, entitlements, and usage metering on your behalf.

Fours authenticates to your GCP project using [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation). The Fours AWS account is configured as an external identity provider in a Workload Identity Pool inside your project, which is authorized to impersonate a service account you create for Fours. No long-lived keys are exchanged.

## Onboarding journey

| # | Step | Who does it |
| - | --- | --- |
| 1 | Become a Google Cloud Marketplace Vendor | You + Google |
| 2 | Prepare your GCP project for Fours | You |
| 3 | Link the service account inside your Producer Portal | You |
| 4 | Set up the reports storage bucket | You |
| 5 | Create the integration in the Fours Console | You |

After onboarding you can edit, delete, or run multiple integrations. See [Manage your integration](#manage-your-integration) below.

## Step 1: Become a Google Cloud Marketplace vendor

Before Fours can manage your marketplace, your business must be an approved Google Cloud Marketplace vendor with access to the Producer Portal.

**Prerequisites**

- A registered legal business entity
- A Google Workspace or **Cloud Identity** account
- Your product passes Google's **Solution Architecture Validation**
- Agreement to Google's **Marketplace Vendor Agreement (MVA)**

1. **Set up a GCP Organization.** If you don't have one, create it in the [Google Cloud Console](https://console.cloud.google.com/). This requires a Google Workspace or Cloud Identity account. (On a free trial you can create a project without an Organization.)
2. **Register on Partner Hub.** Go to [Partner Hub](https://partners.cloud.google.com), enroll under the **Build** engagement model, then under **View tasks → Partner tasks** click **Initiate onboarding your product to Marketplace**. Confirm your organization meets Google's [vendor requirements](https://cloud.google.com/marketplace/docs/partners/get-started#requirements_for_your_organization) and is a member of Google Cloud Partner Network.
3. **Accept the Marketplace Vendor Agreement (MVA).** Review the [MVA](https://cloud.google.com/terms/marketplace-vendor-agreement?hl=en), then accept it in Partner Hub. You must be a **Partner Admin** to accept it.
4. **Complete Solution Validation.** Google reviews your architecture to confirm your product is deployable on GCP. Submit Google's [Solution Validation Form](https://docs.google.com/forms/d/e/1FAIpQLSesllyRR-HvLFZthYA8Cv4nQRUTOthHGgs-76DY9o2IntUL3A/viewform) with:
   - **Architecture diagram** — legible, with GCP icons; shows where resources run (GCP, on-prem, or other clouds), customer vs. partner tenancy, and all GCP services used.
   - **Infrastructure estimate** — from the GCP Pricing Calculator, matching your diagram (Single-Tenant and Multi-Tenant models if applicable).
   - **Sales projections** — estimated Gross Transaction Value (GTV) for Year 1 and Year 3.

   :::tip
   Use the [Architecture Diagram Cheatsheet](https://googlecloudcheatsheet.withgoogle.com/architecture) to build your diagram.
   :::
5. **Enable the Producer Portal.** Create a GCP project named `companyname-public`, then submit the [Marketplace Producer Portal Enablement Form](https://docs.google.com/forms/d/e/1FAIpQLSfddn4mwKnqtLNQ-m7IgRZ-bgTz4BOsrEDWCf3XBjc_ogKNnA/viewform). Once approved, you get access to the [Google Cloud Producer Portal](https://console.cloud.google.com/producer-portal) in your project, where you create your listing and manage versions, billing, and pricing.

To create the `companyname-public` project you need the `resourcemanager.projects.create` permission (in the **Project Creator** role). In the console, open **Manage Resources**, select your organization, and click **Create Project**. See [Creating and managing projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).

![GCP Manage Resources page for creating a new project](images/gcp-marketplace-onboarding-playbook-1.png)

Enter a project name, choose a billing account, and select a parent organization or folder — or choose "No organization" to create it at the top level — then click **Create**.

![GCP new project details form](images/gcp-marketplace-onboarding-playbook-2.png)

:::info
Google's marketplace service accounts also need specific roles on your project. The Fours [setup script in Step 2](#step-2-prepare-your-gcp-project-for-fours) grants these for you, so you don't need to configure them by hand.
:::

## Step 2: Prepare your GCP project for Fours

You have two options to provision the service account, IAM roles, and Workload Identity Pool that Fours needs:

- **Option A — Run the setup script** (recommended). One script in Cloud Shell does everything.
- **Option B — Set up manually** through the GCP console.

Pick one. Both produce the same result.

### Option A: Run the setup script (recommended)

Open [Cloud Shell](https://console.cloud.google.com/?cloudshell=true) in the GCP project you want to integrate, then paste and run the script below.

```bash
#!/bin/bash
# Set up the GCP resources required for the Suger integration.
# Safe to re-run: idempotent guards skip resources that already exist.
set -euo pipefail

SERVICE_ACCOUNT_NAME="suger-integration"

PROJECT_ID=$(gcloud config get-value project 2>/dev/null || true)
if [[ -z "$PROJECT_ID" ]]; then
  echo "ERROR: No active GCP project. Run: gcloud config set project YOUR_PROJECT_ID" >&2
  exit 1
fi

PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" --format="value(projectNumber)")
SERVICE_ACCOUNT_EMAIL="${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"

# 1. Enable required APIs (idempotent).
gcloud services enable \
  iam.googleapis.com \
  cloudresourcemanager.googleapis.com \
  iamcredentials.googleapis.com \
  sts.googleapis.com \
  servicecontrol.googleapis.com \
  cloudcommerceconsumerprocurement.googleapis.com \
  servicemanagement.googleapis.com \
  serviceusage.googleapis.com

# 2. Create the Suger service account (skip if it already exists).
gcloud iam service-accounts describe "$SERVICE_ACCOUNT_EMAIL" >/dev/null 2>&1 \
  || gcloud iam service-accounts create "$SERVICE_ACCOUNT_NAME" \
       --display-name="Suger Integration Service Account"

# 3. Grant the service account the IAM roles it needs (idempotent).
for ROLE in \
  roles/editor \
  roles/servicemanagement.admin \
  roles/servicemanagement.serviceController \
  roles/commerceproducer.admin \
  roles/consumerprocurement.entitlementManager \
  roles/consumerprocurement.orderAdmin \
  roles/commercepricemanagement.privateOffersAdmin \
  roles/pubsub.editor \
  roles/iam.serviceAccountTokenCreator
do
  gcloud projects add-iam-policy-binding "$PROJECT_ID" \
    --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
    --role="$ROLE" \
    --condition=None >/dev/null
done

# 4. Create the Workload Identity Pool and add the Suger AWS account as a provider
#    (skip each if it already exists).
gcloud iam workload-identity-pools describe suger-wip \
    --location=global >/dev/null 2>&1 \
  || gcloud iam workload-identity-pools create suger-wip \
       --location=global \
       --description="Suger Workload Identity Pool"

gcloud iam workload-identity-pools providers describe suger \
    --location=global \
    --workload-identity-pool=suger-wip >/dev/null 2>&1 \
  || gcloud iam workload-identity-pools providers create-aws suger \
       --location=global \
       --workload-identity-pool=suger-wip \
       --account-id=SUGER_AWS_ACCOUNT_ID

# 5. Allow the Suger backend services to impersonate the service account (idempotent).
#    Each binding names a specific AWS assumed-role that a Suger service pod runs as,
#    so no other identity in Suger's AWS account can complete the token exchange.
for SUGER_ROLE in partner-service marketplace-service workflow-service
do
  gcloud iam service-accounts add-iam-policy-binding "$SERVICE_ACCOUNT_EMAIL" \
    --member="principalSet://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/suger-wip/attribute.aws_role/arn:aws:sts::SUGER_AWS_ACCOUNT_ID:assumed-role/$SUGER_ROLE" \
    --role="roles/iam.workloadIdentityUser" >/dev/null
done

# 6. Grant the Suger support user the roles needed to assist with marketplace operations
#    (idempotent).
for ROLE in \
  roles/viewer \
  roles/commerceproducer.admin \
  roles/commercepricemanagement.privateOffersAdmin \
  roles/servicemanagement.admin
do
  gcloud projects add-iam-policy-binding "$PROJECT_ID" \
    --member="user:gcpdev@suger.io" \
    --role="$ROLE" \
    --condition=None >/dev/null
done

# 7. Grant Google's marketplace service accounts the roles required by GCP Marketplace
#    (idempotent).
for BINDING in \
  "group:cloud-commerce-marketplace-onboarding@twosync-src.google.com|roles/editor" \
  "group:cloud-commerce-marketplace-onboarding@twosync-src.google.com|roles/servicemanagement.admin" \
  "serviceAccount:cloud-commerce-producer@system.gserviceaccount.com|roles/servicemanagement.configEditor" \
  "serviceAccount:cloud-commerce-saastester@system.gserviceaccount.com|roles/commerceproducer.viewer" \
  "serviceAccount:cloud-commerce-procurement@system.gserviceaccount.com|roles/serviceusage.serviceUsageAdmin" \
  "serviceAccount:cloud-commerce-procurement@system.gserviceaccount.com|roles/servicemanagement.serviceController" \
  "serviceAccount:cloud-commerce-procurement@system.gserviceaccount.com|roles/servicemanagement.admin"
do
  MEMBER="${BINDING%|*}"
  ROLE="${BINDING#*|}"
  gcloud projects add-iam-policy-binding "$PROJECT_ID" \
    --member="$MEMBER" \
    --role="$ROLE" \
    --condition=None >/dev/null
done

# Print the values you'll need when you create the integration in Suger Console.
echo "PROJECT_ID:            $PROJECT_ID"
echo "PROJECT_NUMBER:        $PROJECT_NUMBER"
echo "Workload Identity Pool: suger-wip"
echo "AWS Provider ID:       suger"
echo "Service Account Email: $SERVICE_ACCOUNT_EMAIL"
```

:::tip
`SUGER_AWS_ACCOUNT_ID` is the external identity Fours uses to impersonate your service account. Contact [support@suger.io](mailto:support@suger.io) for the Fours AWS Account ID, then substitute it in the script before you run it.
:::

**Save the five values printed at the end** — you'll paste them into the Fours Console in Step 5.

#### Also required: Billing Account Viewer at the organization level

So Fours can auto-validate billing account IDs when creating private offers and resale (CPPO) offers, also grant the service account `Billing Account Viewer` at the **GCP organization** level (the script only operates at the project level):

```bash
gcloud organizations add-iam-policy-binding ORG_ID \
  --member="serviceAccount:suger-integration@PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/billing.viewer"
```

This requires a user with `Organization Administrator` access. Find your `ORG_ID` with `gcloud organizations list`.

### Option B: Set up manually

If you prefer to click through the console, here are the same steps in detail.

1. **Create a service account.** Follow Google's [guide](https://cloud.google.com/iam/docs/service-accounts-create) and name it `suger-integration`. Grant it these roles in the **GCP project**:
   - Project Editor (or Viewer)
   - Commerce Producer Admin
   - Commerce Price Management Private Offers Admin
   - Consumer Procurement Entitlement Manager
   - Consumer Procurement Order Administrator
   - Pub/Sub Editor
   - Service Account Token Creator
   - Service Controller
   - Service Management Administrator

   And at the **GCP organization** level:
   - Billing Account Viewer

2. **Enable the required APIs.** Use this [quick link](https://console.cloud.google.com/apis/enableflow?apiid=iam.googleapis.com,cloudresourcemanager.googleapis.com,iamcredentials.googleapis.com,sts.googleapis.com,servicecontrol.googleapis.com,cloudcommerceconsumerprocurement.googleapis.com,servicemanagement.googleapis.com,serviceusage.googleapis.com) to enable all eight at once:
   - Identity and Access Management (IAM) API
   - Cloud Resource Manager API
   - IAM Service Account Credentials API
   - Security Token Service API
   - Service Control API
   - Cloud Commerce Consumer Procurement API
   - Service Management API
   - Service Usage API

3. **Create a Workload Identity Pool** named `suger-wip`. See Google's [guide](https://cloud.google.com/iam/docs/workload-identity-federation).

4. **Add the Fours AWS account as an Identity Provider** in the pool. Contact [support@suger.io](mailto:support@suger.io) for the Fours AWS Account ID. Name the provider `suger`.

   > <img src="https://user-images.githubusercontent.com/98442625/186757882-15d0b202-cb99-46ac-8b23-dd41ccea3ea8.png" style="width:80%;display:inline;margin:0 auto;border-radius:10px;box-shadow: 5px 5px 5px #eee" alt="Add Identity Provider screenshot" />

5. **Authorize the pool to impersonate the service account.** Open the Workload Identity Pool, click **GRANT ACCESS**, select the `suger-integration` service account, and save.

   > <img src="https://user-images.githubusercontent.com/98442625/186767825-89b3fa06-a301-429a-a40d-a80f6ce58a25.png" style="width:100%;display:inline;margin:0 auto;border-radius:10px;box-shadow: 5px 5px 5px #eee" alt="Grant access to service account screenshot" />

   When the dialog appears, select the `suger` Identity Provider.

   > <img src="https://user-images.githubusercontent.com/98442625/209737493-e200e675-3906-4d12-97a8-acddd02412c2.png" style="width:50%;display:inline;margin:0 auto;border-radius:10px;box-shadow: 5px 5px 5px #eee" alt="Select identity provider dialog" />

6. **Grant Google's marketplace service accounts** the roles below on your **GCP project**:
   - `cloud-commerce-marketplace-onboarding@twosync-src.google.com` — Project Editor + Service Management Administrator
   - `cloud-commerce-producer@system.gserviceaccount.com` — Service Config Editor
   - `cloud-commerce-saastester@system.gserviceaccount.com` — Commerce Producer Viewer
   - `cloud-commerce-procurement@system.gserviceaccount.com` — Service Controller + Service Usage Admin + Service Management Administrator

   `cloud-commerce-procurement@system.gserviceaccount.com` also needs **Service Consumer** at the **service** level for each of your product services. Run this once per product service after publishing:

   ```bash
   gcloud endpoints services add-iam-policy-binding \
     "{your-product-service-id}.endpoints.{your-gcp-project-id}.cloud.goog" \
     --member='serviceAccount:cloud-commerce-procurement@system.gserviceaccount.com' \
     --role='roles/servicemanagement.serviceConsumer'
   ```

7. **Grant the Fours support user (`gcpdev@suger.io`)** the roles below on your **GCP project**. These let Fours support inspect Producer Portal, reports, and settings when helping you troubleshoot — Option A's setup script grants them automatically, so Option B must do the same:
   - Viewer
   - Commerce Producer Admin
   - Commerce Price Management Private Offers Admin
   - Service Management Administrator

   Or run these commands:

   ```bash
   for ROLE in \
     roles/viewer \
     roles/commerceproducer.admin \
     roles/commercepricemanagement.privateOffersAdmin \
     roles/servicemanagement.admin
   do
     gcloud projects add-iam-policy-binding "$PROJECT_ID" \
       --member="user:gcpdev@suger.io" \
       --role="$ROLE"
   done
   ```

## Step 3: Link the service account in Producer Portal

The IAM roles from Step 2 cover Google Cloud, but Producer Portal also needs the service account linked inside its own UI. Open [Producer Portal](https://console.cloud.google.com/producer-portal) and follow Google's [backend integration guide](https://cloud.google.com/marketplace/docs/partners/integrated-saas/backend-integration) to authorize `suger-integration@{PROJECT_ID}.iam.gserviceaccount.com` for:

- Partner Procurement API integration
- Cloud Pub/Sub integration
- Service Control API integration (only required if your product reports usage)

## Step 4: Set up the reports storage bucket

Fours reads your GCP Marketplace revenue and usage reports from a Cloud Storage bucket. Follow Google's [reports setup guide](https://cloud.google.com/marketplace/docs/partners/reports/set-up-reports) to create and configure the bucket. Keep the bucket name handy — you'll enter it in the next step.

:::info
When configuring the destination, under Reports to export, make sure to select the **Detailed disbursements** checkbox specifically. This is a separate report type from the basic Disbursements report and isn't selected by default, skipping it means revenue and disbursement data won't have the detailed breakdown Fours needs to reconcile properly.


![GCP detailed disbursements checked](images/gcp-detailed-disbursment-checked.png)
:::

## Step 5: Create the integration in Fours Console

Open the [integrations page](https://console.suger.io/settings?tab=integrations) in Fours Console, click **CONNECT** next to Google Cloud, and fill in the form using the values from the earlier steps:

| Field | Value |
| --- | --- |
| **GCP Project ID** | `PROJECT_ID` from the script output |
| **GCP Project Number** | `PROJECT_NUMBER` from the script output |
| **Workload Identity Pool ID** | `suger-wip` |
| **Identity Provider ID** | `suger` |
| **Service Account Email** | `suger-integration@{PROJECT_ID}.iam.gserviceaccount.com` |
| **Marketplace Partner/Provider ID** | The Partner/Provider ID assigned when your business is approved for Producer Portal. Often the same as your Project ID. |
| **Report Bucket Name** | The Cloud Storage bucket from Step 4 |

Save the integration. Fours immediately starts syncing products and offers from your Producer Portal.

## Listing stages and approval timelines

Once you're integrated, Fours handles most of the technical and administrative work of listing your SaaS product on GCP Marketplace. Listing moves through four stages, each with its own Google approval time.

> **Estimated total time to go live:** ~3–4 weeks

### 1. Product listing details

Submit your product name, logo, description, support and sales contacts, URLs, and keywords in the [GCP Producer Portal](https://console.cloud.google.com/producer-portal).

**Approval time:** 3–4 business days

### 2. Pricing model

Choose your pricing model (flat-rate, usage-based, and so on) and define metrics. To offer a free trial, follow Google's [trial software guidance](https://docs.cloud.google.com/marketplace/docs/partners/integrated-saas/select-pricing#offering-trial-software), which links to the current intake form.

**Approval time:** 3–4 business days

### 3. Technical integration

Link service accounts and enable the Partner Procurement API, Cloud Pub/Sub, and (optionally) the Service Control API; set up SSO or login URLs using Fours' endpoints; and grant the required IAM roles. Steps 2–3 above cover the Fours side of this work.

**Approval time:** ~1 week

### 4. Billing integration

Google reviews your service account setup, entitlement flow, and metering requirements.

**Approval time:** 1–2 weeks

When all four stages are approved, Fours syncs the listing and its status becomes **Public**.

:::info
**Consumption tracking (optional).** If your solution includes a data plane in the customer's project, apply for a **Consumption Label** through Google's [Partner Consumption Tracking](https://docs.cloud.google.com/marketplace/docs/partners/integrated-saas/partner-consumption-tracking) guide, which links to the current Partner Consumption Tracking Initiative form, and implement tracking via Terraform, CLI, or API.
:::

| Stage | Estimated approval time |
| --- | --- |
| Listing details | 3–4 business days |
| Pricing review | 3–4 business days |
| Technical integration | ~1 week |
| Billing integration | 1–2 weeks |

---

## Manage your integration

### Edit integration

You can update an existing integration at any time:

- **Enable Entitlement End Soon Notification** — when on, choose a window of 10–60 days. Fours will send an initial notification when an entitlement is approaching its end, followed by reminders every 5 days. Configure recipients via the [email notification guide](https://doc.fours.com/settings/email-notification/#configuration) using the scope `END_SOON.ENTITLEMENT`.
- **Enable Marketplace** — when on, Fours syncs products and private offers from Producer Portal.
- **Enable PrivateOffer API** — when on, Fours syncs your catalog and your plain private offers through Google's Commerce Producer API instead of the browser-driven path.
- **Enable Resale** — when on, Fours syncs reseller private offer plans for this project's organization.

:::info
Make sure the Fours service account has the right permissions before enabling these flags.
:::

#### About Enable PrivateOffer API

The API path is the more direct integration with Google, but it does not yet cover every offer type. With the toggle on:

| Offer type | Path used |
| ---------- | --------- |
| Products and plain private offers | Commerce Producer API |
| Replacement (amendment) offers | Commerce Producer API |
| Reseller authorizations (`CPPO_OUT`) | Browser-driven path (unchanged) |

Reseller authorizations are the one exclusion — Google's SDK does not support them yet, so they keep working exactly as before and you don't need to change how you create them.

Two things change once replacement offers run through the API. Google checks *before* creating anything whether the replacement is allowed and which offer it must replace, so a replacement that would have failed later is now refused up front with a specific explanation and nothing is created — see [Why a replacement offer was refused](/gcp-marketplace/create-private-offer/#why-a-replacement-offer-was-refused). And a coterm-aligned replacement on a standard billing interval must carry a duration rather than an end date — see [Coterm and standard billing intervals](/gcp-marketplace/create-private-offer/#coterm-and-standard-billing-intervals).

Cancelling an offer (**Cancel**) and extending its expiry date (**More actions → Extend Expiry Date**) follow the toggle's **current** setting, whatever created the offer. With the toggle on, Fours cancels and extends an offer through the API once it has recorded the offer's Google ID — including an offer created on the browser-driven path, and one someone built in Producer Portal that Fours picked up by syncing. An offer without a recorded Google ID goes to the browser-driven path, and so does every reseller authorization.

```d2
direction: right
action: "Cancel or extend\nan offer"
resale: "Reseller\nauthorization?" { shape: diamond }
toggle: "Enable PrivateOffer API\non right now?" { shape: diamond }
named: "Google ID recorded\nfor the offer?" { shape: diamond }
api: "Commerce Producer API"
browser: "Browser-driven path"
action -> resale
resale -> browser: "yes"
resale -> toggle: "no"
toggle -> browser: "off"
toggle -> named: "on"
named -> api: "yes"
named -> browser: "no"
```

:::warning Turning the toggle off
The browser-driven path cannot cancel or extend an offer that was created through the API or picked up by its sync. While the toggle is off, **Cancel** and **Extend Expiry Date** fail for those offers, and cloning one with **Cancel the existing offer at the publishing of this offer** leaves the original live. Turn the toggle back on to manage them again.
:::

When the offer detail page shows a **GCP Data Source** row, it records the path Fours used to create the offer — use it to check whether a particular offer went through the API or the older path. An offer Fours picked up by syncing, rather than created, may not show the row. Either way, the row does not decide how the offer is cancelled or extended.

![Enable Marketplace and Resale](./images/gcp_enable_marketplace_resale.jpg)

With the toggle on, Fours imports your private offers from Google through the API. Two settings in the integration's edit dialog control how far back that import reads:

- **Private Offer Sync Start Date** — how far back the first, full import reaches. Leave it empty for the default of two years.
- **Private Offer Full Sync Done** — Fours turns this on once a full import completes; from then on, each sync reads only offers that changed in the last 7 days. Turn it off to run a fresh full import from the start date — that is how offers Fours skipped get imported, such as offers for a product you onboarded after they were last changed. Fours turns it back on when the import finishes.

### Delete integration

You can delete a GCP integration like any other. **Deletion is immediate and permanent** — there is no recovery window. Re-creating the integration later starts fresh.

### Run multiple integrations

You can connect multiple GCP Marketplace integrations under a single Fours organization. Each one operates independently.

1. Create a new Fours organization in the Fours Console and wait for it to be approved.
2. Set up the second GCP Marketplace integration inside the new organization.
3. Email [support@suger.io](mailto:support@suger.io) with **both** the new and the old Fours organization IDs. Support will merge them — keeping the original organization and removing the new one — while preserving both GCP integrations under the original.

:::tip
- Once set up, both integrations appear on the Fours Console integration page and can be edited or deleted independently.
- Private offer creation, usage reporting, and revenue reports work identically across the Fours web console, Salesforce app, and HubSpot app. Fours routes each request to the right integration automatically.
:::

## Grant additional access to the Fours support team

The GCP Marketplace API doesn't yet cover every operation. To let the Fours support team help with operations the API can't perform, grant the **Fours support user account** these IAM roles on your **GCP project** (the setup script already grants the first four):

- Viewer
- Commerce Producer Admin
- Commerce Price Management Private Offers Admin
- Service Management Administrator
- Consumer Procurement Entitlement Manager
- Consumer Procurement Order Administrator

If you also want Fours to support resale offer discounts (CPPO), grant the support user these roles at the **GCP organization** level:

- Commerce Business Enablement Configuration Admin
- Commerce Business Enablement Reseller Discount Admin
- Commerce Producer Admin

:::tip
Email [support@suger.io](mailto:support@suger.io) to get the Fours support user account email address.
:::

## Troubleshooting

**`gcloud auth activate-service-account` fails with "domain not allowed".**
Your GCP organization restricts which identities can be added via the `iam.allowedPolicyMemberDomains` org policy. Ask your Org Admin to allow the `suger.io` domain, or run the setup from a project that isn't subject to that policy.

**`Permission 'iam.serviceAccounts.getAccessToken' denied on resource`.**
The Workload Identity Pool hasn't been granted permission to impersonate the service account. Re-run step 5 of the setup script (or the equivalent manual step) to bind `roles/iam.workloadIdentityUser` to the principal set for the pool.

**`Error 403: The caller does not have permission, forbidden`.**
The Marketplace Partner/Provider ID configured on the Fours integration doesn't match the one assigned in Producer Portal. Open the integration's edit dialog and correct the Partner ID.

**Private offers are missing after you onboard a product (Enable PrivateOffer API on).**
Fours skips an offer whose product is not in Fours yet, and once the first full import is done it reads only offers changed in the last 7 days — so offers for a product you onboarded later may not come in on their own. Edit the integration and turn **Private Offer Full Sync Done** off (set **Private Offer Sync Start Date** first if the offers are more than two years old). Fours runs a fresh full import and turns the switch back on when it finishes. See [About Enable PrivateOffer API](#about-enable-privateoffer-api).

**Cancelling or extending a GCP offer fails after you turned Enable PrivateOffer API off.**
The browser-driven path cannot service an offer that was created through the API or picked up by its sync. Edit the integration, turn **Enable PrivateOffer API** back on, and cancel or extend the offer again. See [About Enable PrivateOffer API](/gcp-marketplace/integration/#about-enable-privateoffer-api).

**Fours fails to sync entitlements from GCP Marketplace.**
The Fours service account is missing from one of the technical integration sections of your product listing. Open Producer Portal → your product → Technical Integration and confirm `suger-integration@{PROJECT_ID}.iam.gserviceaccount.com` is linked under Partner Procurement API, Cloud Pub/Sub, and (for usage-based products) Service Control API.

## Key resources

- [Get started on GCP Marketplace](https://cloud.google.com/marketplace/docs/partners/get-started)
- [Initiate product onboarding](https://cloud.google.com/marketplace/docs/partners/offer-products#initiate-onboarding)
- [Partner Hub portal](https://partners.cloud.google.com/?hl=en)
- [Report types](https://docs.cloud.google.com/marketplace/docs/partners/reports/report-types)
