# Create a Referral via API

Build and submit an outbound co-sell referral to AWS, Microsoft (Azure), or Google Cloud (GCP) directly through the Suger API.

---

## Overview

This page is the developer companion to the [Outbound Referral](/cosell/cosell-outbound) UI walkthrough. It documents the request payload for one endpoint:

```
POST /org/{orgId}/cosell/referral
```

- **Auth:** API key (`Authorization` header). See [Authentication](/get-started).
- **Query param:** `forceCreate` (boolean, optional). When `true`, the referral is saved in Suger even if it fails validation or the partner rejects it, so you can fix and resubmit later. Default `false`.
- **Response:** `200` with an `OperationExecutionDetails` object (contains the `workflowID` of the submission). On validation failure you get `400` with an `info` array of per-field errors (see [Validate first](#validate-first)).

One endpoint serves all three clouds. The cloud is chosen by the top-level `partner` field, and the partner-specific opportunity goes in a matching slot under `info`. **Submission is automatic** — the create workflow fires immediately and pushes the referral to the partner. Do **not** call a sync afterwards for the initial submit. The resulting status is `PENDING_CREATE` on success or `CREATE_FAILED` if the partner API rejects it (resubmit by calling this endpoint again).

:::note
If your org has the **referral approval process** enabled and the referral is not yet approved, a brand-new referral is saved as `DRAFT` and the workflow does **not** fire until it is approved in the Suger Console.
:::

## The envelope

Every request body has the same outer shape, regardless of cloud:

```jsonc
{
  "partner": "AWS",                        // "AWS" | "AZURE" | "GCP"
  "salesforceOpportunityId": "0065g...",   // optional: link to a CRM opportunity
  "salesforceAccountId": "0015g...",       // optional: link to the CRM account
  "info": {
    // exactly one slot, matching `partner` — see table below
  },
  "metaInfo": { /* optional */ },
  "approvalInfo": { /* optional, for the approval workflow */ }
}
```

:::note[Linking to Salesforce]
`salesforceOpportunityId` and `salesforceAccountId` are optional — set them to associate the referral with a CRM record so it shows up linked in the Suger Console and stays in sync. If you provide `salesforceOpportunityId` but leave `salesforceAccountId` blank, Suger automatically derives the account from that opportunity. Set `salesforceAccountId` explicitly only when you want to control or override which account is linked. This applies to all three clouds.
:::

The partner-specific opportunity lives in a different `info` slot for each cloud:

| `partner` | Send the opportunity under | Body type |
|---|---|---|
| `AWS`   | `info.aceOpportunityV2`              | AWS Partner Central opportunity |
| `AZURE` | `info.createMicrosoftReferralRequest`| Microsoft Partner Center referral |
| `GCP`   | `info.gcpOpportunityV2`              | Google Cloud opportunity |

:::note[Azure: what you send vs. what you get back]
On **create** you send `info.createMicrosoftReferralRequest`. Suger converts it internally and persists it as `info.microsoftReferralSet`, so `GET` responses return the referral under `microsoftReferralSet` — not `createMicrosoftReferralRequest`. Always build the create payload with `createMicrosoftReferralRequest`.
:::

### Two tiers of "required"

Throughout this page, required fields fall into two groups:

- **Required by Suger** — missing/invalid values return a `400` *before* anything reaches the cloud partner. These are the hard blockers.
- **Required by the cloud partner** — Suger may accept the payload, but AWS/Microsoft/Google will reject it. Suger's auto-enrich and auto-fix features try to fill some of these; the authoritative list is each cloud's own API reference, linked per section.

## Validate first

Before creating, dry-run the payload against the partner schema:

```
POST /org/{orgId}/cosell/referral/validate
```

Send the same envelope you would `POST` to `/referral`. A failing response returns the field-level errors so you can correct the payload without creating a `CREATE_FAILED` record:

```jsonc
{
  "code": "BAD_REQUEST",
  "message": "failed to validate ...",
  "info": [
    { "field": "customer.account.industry", "message": "'Industry vertical' is required" },
    { "field": "relatedEntityIdentifiers.solutions", "message": "'Solutions' is required" }
  ]
}
```

---

## AWS

Send the opportunity under `info.aceOpportunityV2`. Field keys use **PascalCase** (e.g. `Customer`, `LifeCycle`), matching the AWS Partner Central Selling API.

### Required by Suger

| Field (under `info.aceOpportunityV2`) | Rule |
|---|---|
| `Customer.Account.Industry` | Non-empty; from the AWS industry list |
| `Customer.Account.CompanyName` | Non-empty (truncated to 120 chars) |
| `Customer.Account.WebsiteUrl` | Valid URL — waived only when `NationalSecurity` is `"Yes"` |
| `Customer.Account.Address.CountryCode` | ISO 3166-1 alpha-2 |
| `Customer.Account.Address.PostalCode` | Must match the country's postal pattern |
| `Customer.Account.Address.StateOrRegion` | Required **only when `CountryCode` is `US`** |
| `PrimaryNeedsFromAws` | Array, at least one value |
| `RelatedEntityIdentifiers.Solutions` | Array of your AWS Solution IDs, at least one |
| `LifeCycle.TargetCloseDate` | `YYYY-MM-DD`, must be a future date |

### Also required by AWS (Suger does not block these)

Suger's validator passes **without** these, but they are flagged `requiredForCreation` in the AWS ACE schema — **AWS rejects the submission without them**, so Suger accepts the payload and the AWS step then fails as `CREATE_FAILED`. The example below includes all of them:

| Field | Notes |
|---|---|
| `OpportunityType` | You provide it: `Net New Business` \| `Flat Renewal` \| `Expansion` |
| `Project.Title` | You provide it |
| `Project.CustomerBusinessProblem` | You provide it (20–2000 chars) |
| `Project.CustomerUseCase` | You provide it (valid use-case value) |
| `Project.DeliveryModels` | You provide it (e.g. `SaaS or PaaS`) |
| `Project.ExpectedCustomerSpend` | You provide `Amount`; Suger fills `CurrencyCode`/`Frequency`/`TargetCompany` |
| `Project.SalesActivities` | Suger defaults if omitted |
| `Origin` | You provide it: `Partner Referral` (the only valid value for `Catalog: AWS`) |
| `Marketing.Source` | Suger fills (`None`) |
| `PartnerOpportunityIdentifier` | Suger sets it to the referral ID |

So beyond Suger's hard-blocked list, the fields *you* must supply for AWS to accept are `Origin`, `OpportunityType`, `Project.Title`, `Project.CustomerBusinessProblem`, `Project.CustomerUseCase`, `Project.DeliveryModels`, and `Project.ExpectedCustomerSpend.Amount`. The create path runs `ValidateAndAIFix`, which only repairs fields that are *present but invalid* within a fixed allowlist — it does **not** invent missing ones, and `Solutions` / `TargetCloseDate` aren't auto-fixable at all. The authoritative list is the [AWS CreateOpportunity reference](https://docs.aws.amazon.com/partner-central/latest/APIReference/API_CreateOpportunity.html).

### Auto-filled / normalized by Suger

- `Catalog` — set from your connected AWS integration (`AWS` or `Sandbox`). Don't send it.
- `Project.ExpectedCustomerSpend[0]` — the first entry's `Frequency`→`Monthly`, `CurrencyCode`→`USD`, `TargetCompany`→`AWS` are always overwritten (AWS only accepts these for this object). You supply `Amount`.
- `Marketing.Source` defaults to `"None"`; `Project.SalesActivities` defaults if empty.
- `NationalSecurity` is forced to `"Yes"` when `Industry` is `"Government"`.
- Contacts/team without a valid email are dropped; the first `OpportunityTeam` member defaults to `BusinessTitle: "PartnerAccountManager"`.

`PrimaryNeedsFromAws` values: `Co-Sell - Architectural Validation`, `Co-Sell - Business Presentation`, `Co-Sell - Competitive Information`, `Co-Sell - Pricing Assistance`, `Co-Sell - Technical Consultation`, `Co-Sell - Total Cost of Ownership Evaluation`, `Co-Sell - Deal Support`, `Co-Sell - Support for Public Tender / RFx`, or `Do Not Need Support from AWS Sales Rep`.

For the full list of valid `Industry`, `CountryCode`, `CustomerUseCase`, and `DeliveryModels` values, see the [AWS CreateOpportunity API reference](https://docs.aws.amazon.com/partner-central/latest/APIReference/API_CreateOpportunity.html).

### Example payload (AWS)

This mirrors the field set the Suger Console submits (the *Share with AWS* form), so it includes the Suger-required fields, the fields AWS needs to accept the referral, and the common optional fields. It is **not** the bare validator minimum (see the two lists above). Comments mark `// required`, `// optional`, and which fields Suger fills. Treat the [AWS reference](https://docs.aws.amazon.com/partner-central/latest/APIReference/API_CreateOpportunity.html) as the source of truth for what AWS will accept.

```jsonc
{
  "partner": "AWS",
  "salesforceOpportunityId": "0065g00000XXXXXAAA",   // optional: link to the CRM opportunity
  "salesforceAccountId": "0015g00000YYYYYAAA",        // optional: auto-derived from the opportunity if omitted
  "info": {
    "aceOpportunityV2": {
      "Origin": "Partner Referral",          // required (only valid value for Catalog: AWS)
      "OpportunityType": "Net New Business",  // required: Net New Business | Flat Renewal | Expansion
      "NationalSecurity": "No",               // optional ("Yes"/"No"); forced "Yes" when Industry = "Government"

      "Customer": {
        "Account": {
          "CompanyName": "Acme Robotics Inc",            // required
          "Industry": "Software and Internet",            // required (valid Industry value)
          "WebsiteUrl": "https://www.acmerobotics.com",   // required (waived only if NationalSecurity = "Yes")
          "Duns": "123456789",                            // optional (9 digits)
          "AwsAccountId": "123456789012",                 // optional (12 digits)
          "Address": {
            "CountryCode": "US",                           // required (ISO 3166-1 alpha-2)
            "StateOrRegion": "California",                 // required when CountryCode = "US"
            "City": "San Francisco",                       // optional
            "PostalCode": "94105",                         // required
            "StreetAddress": "123 Market St"               // optional
          }
        },
        "Contacts": [                                       // customer contact(s)
          { "FirstName": "Dana", "LastName": "Cruz", "Email": "dana.cruz@acmerobotics.com", "Phone": "+14155550123", "BusinessTitle": "VP Engineering" }
        ]
      },

      "PrimaryNeedsFromAws": ["Co-Sell - Deal Support"],  // required, >= 1

      "Project": {
        "Title": "Acme migration to AWS",                  // required
        "CustomerBusinessProblem": "Acme needs to migrate its on-prem fleet platform to AWS to cut latency and scale globally.", // required, 20-2000 chars
        "CustomerUseCase": "Migration / Database Migration", // required (valid use-case value)
        "DeliveryModels": ["SaaS or PaaS"],                // required: SaaS or PaaS | BYOL or AMI | Managed Services | Professional Services | Resell | Other
        "SalesActivities": ["Initialized discussions with customer"], // Suger defaults this if omitted
        "ExpectedCustomerSpend": [
          { "Amount": "5000" }                             // required; Suger sets CurrencyCode=USD, Frequency=Monthly, TargetCompany=AWS
        ],
        "CompetitorName": "",                              // optional
        "ApnPrograms": [],                                 // optional
        "AdditionalComments": "Joint GTM with the AWS account team." // optional (<= 255 chars)
      },

      "LifeCycle": {
        "TargetCloseDate": "2026-09-30",                   // required; future date, YYYY-MM-DD
        "NextSteps": "Schedule joint architecture review"  // optional (<= 255 chars)
      },

      "RelatedEntityIdentifiers": {
        "Solutions": ["S-0123456"],                        // required, >= 1 (your AWS Solution IDs)
        "AwsProducts": ["AmazonBedrock"]                   // optional (values from the AWS products list)
      },

      "OpportunityTeam": [                                  // your team (partner side); members without an email are dropped
        { "FirstName": "Sam", "LastName": "Patel", "Email": "sam.patel@yourcompany.com", "Phone": "+14155550100", "BusinessTitle": "PartnerAccountManager" },
        { "FirstName": "Jordan", "LastName": "Lee", "Email": "jordan.lee@yourcompany.com", "Phone": "+14155550101", "BusinessTitle": "OpportunityOwner" }
      ],

      "Marketing": { "Source": "None" }                    // Suger fills "None"; if set to a real source, also provide CampaignName / Channels / UseCases / AwsFundingUsed
    }
  }
}
```

> `Catalog` and `SoftwareRevenue` are intentionally omitted — Suger sets `Catalog` from your AWS integration and controls `SoftwareRevenue` based on your partner program. `PartnerOpportunityIdentifier` is set to the referral ID for you.

---

## Azure (Microsoft)

Send the opportunity under `info.createMicrosoftReferralRequest`. Field keys use **camelCase**.

### Required by Suger

| Field (under `info.createMicrosoftReferralRequest`) | Rule |
|---|---|
| `name` | Deal name, non-empty |
| `details.closingDateTime` | UTC datetime (`YYYY-MM-DDTHH:MM:SSZ`), today or future |
| `details.dealValue` | Number > 0 |
| `details.currency` | ISO 4217 code (defaults to `USD` if blank) |
| `customerProfile.address.country` | ISO 3166-1 alpha-2 (defaults to `US` if blank) |
| `team[]` | At least one member, each with `email`, `firstName`, `lastName`, `phoneNumber` |
| `details.requirements.solutions[].id` | At least one solution (for `Private` / `IPCosell` deals) |
| `details.requirements.additionalRequirements.attributes[]` | One `SolutionArea` and one matching `SolutionPlay` attribute; plus `CustomerMarketplaceIntent` for `Private`/`IPCosell` |

### Co-sell vs. independent

A referral is treated as a **co-sell** (Microsoft is asked to help) when it carries an invitation with `organizationId: "msft"` and an `assistanceRequestCode` other than `NoHelpRequired`. For co-sell referrals you must **also** provide a customer contact: at least one `customerProfile.team[]` entry with `email`, `firstName`, `lastName`, `phoneNumber` (and its email domain must differ from your partner team's domains).

`dealType` values: `Private` (no Microsoft help), `IPCosell` (default when Microsoft help is requested), `ServicesCosell`. `assistanceRequestCode` values: `NoHelpRequired`, `WorkloadSpecificValueProposition`, `CustomerTechnicalArchitecture`, `ProofOfConceptOrDemo`, `QuotesOrLicensing`, `PostSalesCustomerSuccess`, `GeneralOrOther`. Suger auto-sets `type`, `status`, `substatus`, and `dealType`, and auto-fixes missing phone numbers.

For the valid `SolutionArea`/`SolutionPlay` combinations, currency and country lists, see the [Microsoft "Create a referral" reference](https://learn.microsoft.com/en-us/partner-center/developer/create-a-referral).

### Example payload (Azure, independent / no Microsoft help)

This mirrors the field set the Suger Console submits. Comments mark `// required` / `// optional` and which fields Suger fills.

```jsonc
{
  "partner": "AZURE",
  "salesforceOpportunityId": "0065g00000XXXXXAAA",   // optional: link to the CRM opportunity
  "salesforceAccountId": "0015g00000YYYYYAAA",        // optional: auto-derived from the opportunity if omitted
  "info": {
    "createMicrosoftReferralRequest": {
      "name": "Acme – Azure migration",                // required (deal name)
      "externalReferenceId": "0065g00000XXXXXAAA",      // optional: your CRM record id
      "team": [                                         // required: >= 1 partner contact, each with email/firstName/lastName/phoneNumber
        { "firstName": "Sam", "lastName": "Patel", "email": "sam.patel@yourcompany.com", "phoneNumber": "+14155550100", "title": "Partner Account Manager" }
      ],
      "customerProfile": {
        "name": "Acme Robotics Inc",                    // optional
        "address": {
          "country": "US",                               // required (ISO 3166-1 alpha-2; Suger defaults "US")
          "city": "San Francisco",                       // optional
          "region": "CA",                                // optional
          "postalCode": "94105"                          // optional
        }
      },
      "details": {
        "closingDateTime": "2026-09-30T23:59:59Z",       // required (UTC; today or future)
        "currency": "USD",                               // required (ISO 4217; Suger defaults "USD")
        "dealValue": 50000,                              // required (> 0)
        "notes": "Joint migration opportunity.",         // optional
        "requirements": {
          "solutions": [{ "id": "your-solution-id" }],   // required (>= 1) for Private / IPCosell deals
          "additionalRequirements": {
            "attributes": [                               // required
              { "type": "SolutionArea", "id": "Cloud and AI Platforms" },
              { "type": "SolutionPlay", "id": "Migrate and Modernize Your Estate" },
              { "type": "CustomerMarketplaceIntent", "id": "HaveNotDecided" }
            ]
          }
        }
      }
    }
  }
}
```

> Suger sets `type`, `status`, `substatus`, and `dealType` for you and auto-fixes missing phone numbers — don't send those.

To request Microsoft co-sell help, add an `invitations` entry and a customer contact (the customer contact is **required** once Microsoft help is requested):

```jsonc
"invitations": [
  { "organizationId": "msft", "organizationName": "Microsoft", "assistanceRequestCode": "ProofOfConceptOrDemo" }
],
"customerProfile": {
  "address": { "country": "US" },
  "team": [                                              // required for co-sell: >= 1 customer contact
    { "firstName": "Dana", "lastName": "Cruz", "email": "dana.cruz@acmerobotics.com", "phoneNumber": "+14155550200" }
  ]
}
```

---

## GCP (Google Cloud)

Send the opportunity under `info.gcpOpportunityV2`. Field keys use **camelCase**.

GCP has **two opportunity types**, selected by the top-level `opportunityType` field:

- **Regular** — `opportunityType` is `REGULAR` (or omitted / `TWO_TIER`). A standard resell/services opportunity.
- **ISV Solution Connect** — `opportunityType` is `ISV_SOLUTION_CONNECT`. An ISV solution deal, with its own `isvSolutionConnectInfo` block.

The two types share a customer block but differ in which qualification and product fields are required.

### Required for both types

| Field (under `info.gcpOpportunityV2`) | Rule |
|---|---|
| `opportunityInfo.partnerEntity` | Format `partners/{id}` |
| `customerInfo.customerDetails.organizationName` | Non-empty |
| `customerInfo.customerDetails.domain` | Valid domain |
| `customerInfo.customerDetails.address.regionCode` | ISO 3166-1 alpha-2 |
| `customerInfo.customerDetails.address.postalCode` | Required for most countries (US: `12345` or `12345-6789`) |
| `customerInfo.customerDetails.industry` | From the GCP industry list |
| `customerInfo.customerDetails.employeeCount` | Integer > 0 |
| `customerInfo.contact.givenName`, `.familyName`, `.email` | All required |
| `customerInfo.region` | One of `ANZ`, `CEE`, `DACH`, `FRANCE`, `INDIA`, `JAPAN`, `LATAM_BRAZIL`, `LATAM_SPANISH_SPEAKING`, `NE`, `NORTH_AMERICA`, `OTHER_ASIA_PACIFIC`, `SEEMEA`, `UK_AND_I` |
| `qualificationInfo.contractLengthMonths` | Integer 1–96 |
| `qualificationInfo.estimatedCloseDate` | `{ year, month, day }`, future date |
| `qualificationInfo.dealSize.currencyCode` | `USD` for GCP/Google Maps product categories |
| `qualificationInfo.dealSize.units` | Positive integer **as a string**, e.g. `"50000"` |
| `qualificationInfo.legalLanguageAccepted` | Must be `true` (GCP requirement) |

### Required for Regular only

| Field | Rule |
|---|---|
| `opportunityInfo.productCategory[0]` | From the GCP product-category list (e.g. `GCP_COMPUTE`, `GCP_AI`, `GOOGLE_MAPS`) |
| `qualificationInfo.operationType` | `NEW`, `RENEWAL`, `ADD_ON`, `EXPANSION` |
| `qualificationInfo.quantity` | Integer ≥ 1 |
| `qualificationInfo.budget` | `EXACT_BUDGET_GIVEN`, `BUDGET_EXISTS_NOT_SPECIFIED`, `CONFIRMED_NO_BUDGET`, `REFUSE_TO_DISCLOSE` |
| `qualificationInfo.authority` | `CLEARLY_IDENTIFIED_PROCESS`, `CONFIRMED_NO_AUTHORITY_DECIDED`, `VAGUE_UNDERSTANDING`, `DONT_KNOW` |
| `qualificationInfo.need` | `CLEAR_NEED`, `COMPELLING_NEED`, `NO_NEED` |
| `qualificationInfo.timeline` | `SPECIFIC_DECISION_DATES_GIVEN`, `VAGUE_DECISION_DATES_GIVEN`, `CONFIRMED_NO_DECISION_DATE`, `REFUSED_TO_GIVE_DATE` |
| `qualificationInfo.decisionPhase` | `FINAL_DECISION`, `TRIAL_OR_PILOT`, `INFORMATION_GATHERING` |

### Required for ISV Solution Connect only

| Field | Rule |
|---|---|
| `opportunityInfo.productFamily[0]` | `GOOGLE_CLOUD_PLATFORM` or `GOOGLE_WORKSPACE` |
| `opportunityInfo.description` | Non-empty |
| `isvSolutionConnectInfo.contractVehicle` | `CLOUD_MARKETPLACE`, `PARTNER_CONTRACT`, `UNKNOWN` |
| `isvSolutionConnectInfo.deliveryModel` | `DATA_TO_CUSTOMER_BIGQUERY`, `VM_ON_CUSTOMER_TENANCY`, `SAAS_ON_GOOGLE_CLOUD`, `OTHER_DELIVERY_MODEL` |
| `isvSolutionConnectInfo.supportLevel` | `TECH`, `TRANSACTION`, `UPSELL_RENEW_CROSS_SELL`, `ALIGN_SALES_ACCOUNT`, `ALREADY_CONTACT`, `OTHER_SUPPORT_LEVEL` |

For the full `industry`, `productCategory`, currency, and region lists, see the [Google Cloud opportunities API reference](https://docs.cloud.google.com/channel/docs/reference/rest/v1alpha1/opportunities).

### Example payload (GCP — Regular)

```jsonc
{
  "partner": "GCP",
  "salesforceOpportunityId": "0065g00000XXXXXAAA",   // optional: link to the CRM opportunity
  "salesforceAccountId": "0015g00000YYYYYAAA",        // optional: auto-derived from the opportunity if omitted
  "info": {
    "gcpOpportunityV2": {
      "opportunityType": "REGULAR",                    // REGULAR | TWO_TIER | ISV_SOLUTION_CONNECT
      "opportunityInfo": {
        "partnerEntity": "partners/123456",            // required (partners/{id})
        "productCategory": ["GCP_COMPUTE"],            // required (>= 1; e.g. GCP_AI, GCP_ANALYTICS, GCP_DATABASES)
        "displayName": "Acme Corp – GCP Compute",      // optional (auto-generated if omitted)
        "confidential": false                          // optional
      },
      "customerInfo": {
        "customerDetails": {
          "organizationName": "Acme Corporation",      // required
          "domain": "acme.com",                        // required
          "industry": "SOFTWARE",                      // required (GCP industry value)
          "employeeCount": 500,                        // required (> 0)
          "address": { "regionCode": "US", "postalCode": "94043" }  // required (regionCode; postalCode for most countries)
        },
        "contact": {
          "givenName": "John", "familyName": "Doe", "email": "john.doe@acme.com",  // required
          "phone": { "e164Number": "+14155550123" }    // optional
        },
        "region": "NORTH_AMERICA"                       // required (GCP sales region)
      },
      "qualificationInfo": {
        "operationType": "NEW",                         // required: NEW | RENEWAL | ADD_ON | EXPANSION
        "quantity": 1,                                  // required (>= 1)
        "contractLengthMonths": 12,                     // required (1–96)
        "dealSize": { "currencyCode": "USD", "units": "50000" },        // required (USD for GCP; units as a string)
        "estimatedCloseDate": { "year": 2026, "month": 9, "day": 30 },  // required (future)
        "budget": "EXACT_BUDGET_GIVEN",                 // required
        "authority": "CLEARLY_IDENTIFIED_PROCESS",      // required
        "need": "CLEAR_NEED",                           // required
        "timeline": "SPECIFIC_DECISION_DATES_GIVEN",    // required
        "decisionPhase": "FINAL_DECISION",              // required
        "legalLanguageAccepted": true,                  // required (must be true)
        "publicSector": false,                          // optional
        "msspDeal": false                               // optional
      }
    }
  }
}
```

### Example payload (GCP — ISV Solution Connect)

```jsonc
{
  "partner": "GCP",
  "salesforceOpportunityId": "0065g00000XXXXXAAA",   // optional: link to the CRM opportunity
  "salesforceAccountId": "0015g00000YYYYYAAA",        // optional: auto-derived from the opportunity if omitted
  "info": {
    "gcpOpportunityV2": {
      "opportunityType": "ISV_SOLUTION_CONNECT",       // required for ISV
      "opportunityInfo": {
        "partnerEntity": "partners/123456",            // required (partners/{id})
        "productFamily": ["GOOGLE_CLOUD_PLATFORM"],    // required for ISV: GOOGLE_CLOUD_PLATFORM | GOOGLE_WORKSPACE
        "description": "Deploying our real-time analytics SaaS on GCP for the customer."  // required for ISV
      },
      "customerInfo": {
        "customerDetails": {
          "organizationName": "TechCorp Inc",          // required
          "domain": "techcorp.io",                     // required
          "industry": "FINANCIAL_SERVICES",            // required
          "employeeCount": 2000,                       // required
          "address": { "regionCode": "GB", "postalCode": "SW1A 1AA" }  // required
        },
        "contact": {
          "givenName": "Jane", "familyName": "Smith", "email": "jane.smith@techcorp.io",  // required
          "phone": { "e164Number": "+442071234567" }   // optional
        },
        "region": "UK_AND_I"                            // required (GCP sales region)
      },
      "qualificationInfo": {
        "contractLengthMonths": 24,                     // required (1–96)
        "dealSize": { "currencyCode": "USD", "units": "250000" },       // required
        "estimatedCloseDate": { "year": 2026, "month": 6, "day": 30 },  // required (future)
        "legalLanguageAccepted": true                   // required (must be true)
      },
      "isvSolutionConnectInfo": {
        "isvSolutionConnectDeal": true,                 // required for ISV
        "contractVehicle": "CLOUD_MARKETPLACE",         // required for ISV
        "deliveryModel": "SAAS_ON_GOOGLE_CLOUD",        // required for ISV
        "supportLevel": "TECH",                         // required for ISV
        "customerContactRequested": false               // optional
      }
    }
  }
}
```

> ISV Solution Connect does **not** require the qualification fields (`operationType`, `budget`, `authority`, `need`, `timeline`, `decisionPhase`, `quantity`, `productCategory`) that a Regular opportunity does — Suger's validator only enforces those for Regular. Google's API is the final authority; see the reference linked above.

---

## Response & next steps

A successful create returns `OperationExecutionDetails`, including a `workflowID` of the form `org/{orgId}/cosell/referral/{referralId}/create` — the `{referralId}` segment is the new referral's ID.

- The referral lands in `PENDING_CREATE` while the submission workflow runs, then moves to the partner's accepted state — or `CREATE_FAILED` if the partner API rejects it. Resubmit by calling `POST .../cosell/referral` again with the corrected payload.
- Do **not** call sync for the initial submit — submission is automatic.
- To edit a referral later, use `PATCH /org/{orgId}/cosell/referral/{referralId}`, then sync the change to the partner.

## Updating a referral

`PATCH /org/{orgId}/cosell/referral/{referralId}` edits a referral. By default the partner-specific update validator runs and an outbound sync to the partner is started.

- **Query param:** `isLinkageUpdate` (boolean, optional, default `false`). When `true`, only the CRM-linkage fields — `salesforceOpportunityId`, `salesforceAccountId`, `hubspotDealId`, `dynamics365OpportunityId` — are persisted; the partner-opportunity content in the body is ignored, and the update validator and outbound sync are **skipped**. Sending all four empty unlinks the referral.
- Use it for a pure CRM **link or unlink** (e.g. attaching a referral to a Salesforce opportunity/account), so the linkage is saved even when the referral's partner-opportunity state would otherwise fail validation — for example an AWS referral already at the *Committed* stage. Honored for **AWS** and **GCP**; for **Azure** and **Suger** the flag is ignored and the normal update path is used.

## Call it from Salesforce (Apex)

If you use the **Suger Connector** managed package for Salesforce, you can create a referral from Apex without writing your own HTTP callout — call the packaged method with the same payload shape described above (note the `Suger.` namespace prefix):

```java
Map<String, Object> referral = new Map<String, Object>{
  'partner' => 'AWS',
  'salesforceOpportunityId' => opp.Id,         // optional: link to the CRM opportunity
  'salesforceAccountId' => opp.AccountId,       // optional: auto-derived from the opportunity if omitted
  'info' => new Map<String, Object>{
    'aceOpportunityV2' => new Map<String, Object>{
      'Origin'          => 'Partner Referral',   // required
      'OpportunityType' => 'Net New Business',    // required
      'NationalSecurity' => 'No',                 // optional
      'Customer' => new Map<String, Object>{
        'Account' => new Map<String, Object>{
          'CompanyName' => 'Acme Robotics Inc',          // required
          'Industry'    => 'Software and Internet',       // required
          'WebsiteUrl'  => 'https://www.acmerobotics.com',// required
          'Duns'        => '123456789',                   // optional
          'AwsAccountId' => '123456789012',               // optional
          'Address'     => new Map<String, Object>{
            'CountryCode' => 'US',                          // required
            'StateOrRegion' => 'California',                // required for US
            'City' => 'San Francisco',
            'PostalCode' => '94105',                        // required
            'StreetAddress' => '123 Market St'
          }
        },
        'Contacts' => new List<Object>{
          new Map<String, Object>{ 'FirstName' => 'Dana', 'LastName' => 'Cruz', 'Email' => 'dana.cruz@acmerobotics.com', 'Phone' => '+14155550123', 'BusinessTitle' => 'VP Engineering' }
        }
      },
      'PrimaryNeedsFromAws' => new List<String>{ 'Co-Sell - Deal Support' },   // required
      'Project' => new Map<String, Object>{
        'Title' => 'Acme migration to AWS',                // required
        'CustomerBusinessProblem' => 'Acme needs to migrate its on-prem fleet platform to AWS to cut latency and scale globally.',  // required
        'CustomerUseCase' => 'Migration / Database Migration',  // required
        'DeliveryModels'  => new List<String>{ 'SaaS or PaaS' },// required
        'ExpectedCustomerSpend' => new List<Object>{ new Map<String, Object>{ 'Amount' => '5000' } },  // required (Amount)
        'SalesActivities' => new List<String>{ 'Initialized discussions with customer' }, // Suger defaults if omitted
        'AdditionalComments' => 'Joint GTM with the AWS account team.'  // optional
      },
      'LifeCycle' => new Map<String, Object>{
        'TargetCloseDate' => '2026-09-30',                 // required (future, YYYY-MM-DD)
        'NextSteps' => 'Schedule joint architecture review'// optional
      },
      'RelatedEntityIdentifiers' => new Map<String, Object>{
        'Solutions'   => new List<String>{ 'S-0123456' },  // required, >= 1
        'AwsProducts' => new List<String>{ 'AmazonBedrock' }// optional
      },
      'OpportunityTeam' => new List<Object>{                // your team (partner side)
        new Map<String, Object>{ 'FirstName' => 'Sam', 'LastName' => 'Patel', 'Email' => 'sam.patel@yourcompany.com', 'Phone' => '+14155550100', 'BusinessTitle' => 'PartnerAccountManager' },
        new Map<String, Object>{ 'FirstName' => 'Jordan', 'LastName' => 'Lee', 'Email' => 'jordan.lee@yourcompany.com', 'Phone' => '+14155550101', 'BusinessTitle' => 'OpportunityOwner' }
      },
      'Marketing' => new Map<String, Object>{ 'Source' => 'None' }  // Suger fills "None"
    }
  }
};

// forceCreate=false → fail fast on validation errors; true → save even if the partner rejects, to fix & resubmit
Object result = Suger.CosellApi.createCosellReferral(referral, false);
Map<String, Object> operation = (Map<String, Object>) result;
String workflowId = (String) operation.get('workflowID');
```

- Build `info.aceOpportunityV2` / `info.createMicrosoftReferralRequest` / `info.gcpOpportunityV2` as nested `Map<String, Object>` exactly as the JSON examples above show — the envelope is identical to the REST body.
- The method **makes an HTTP callout**, so it must run in a callout-allowed context: **not after DML in the same transaction**, and from a record-triggered Flow or trigger it must run **asynchronously** (Queueable or `@future(callout=true)`).
- The caller needs co-sell **write** permission for the partner; the Suger endpoint and authentication are handled by the package.
- To edit a referral, call `Suger.CosellApi.updateCosellReferral(referralId, referralData)`. For a pure CRM **link/unlink** (AWS/GCP), call `Suger.CosellApi.updateCosellReferralLinkage(referralId, referralData)` instead — it sends `isLinkageUpdate=true` so the linkage saves even when the referral's partner-opportunity state would fail validation (see [Updating a referral](#updating-a-referral)).

### From a Flow (no Apex)

You don't have to write Apex to submit a referral from a Flow. The package ships two invocable actions you can drop straight into Flow Builder:

- **Co-Sell (Fire and Forget)** — submits and returns immediately (no wait, no Salesforce write-back).
- **Co-Sell** — submits, waits for the create to finish, then backfills a Salesforce `Referral__c` record.

Each takes three inputs:

| Input | Required | Notes |
|---|---|---|
| **Partner** | Yes | `AWS`, `AZURE`, or `GCP`. |
| **Opportunity ID** | No | Builds the payload from a CRM opportunity via field mapping (the original behavior). |
| **Referral Payload (JSON)** | No | A hand-built payload — the **same envelope shown above**, as a JSON string. When set, the field-mapping preview is skipped and this payload is submitted as-is. |

Provide **one** of *Opportunity ID* or *Referral Payload (JSON)*. If both are set, the payload wins and the Opportunity ID is used only to link the referral to that CRM record.

Because creating a referral is an HTTP callout, place the action on a record-triggered Flow's **Run Asynchronously** path (a synchronous after-save path can't make the callout). Screen and autolaunched Flows can call it directly as long as no DML ran earlier in the transaction.

:::note
If you don't see the **Referral Payload (JSON)** input in Flow Builder, upgrade the Suger Connector package — it's available in recent versions. `createCosellReferral` itself is `@AuraEnabled` (not `@InvocableMethod`), so it isn't selectable in Flow directly; these two actions are the Flow entry points, or call it from your own Apex as shown above.
:::

## Full API reference

For the complete request/response schema and to try the endpoint, see [`POST /org/{orgId}/cosell/referral`](https://doc.suger.io/api/#tag/cosell/POST/org/{orgId}/cosell/referral) in the Suger API reference. The authoritative field definitions for each cloud are the partner references linked above:

- [AWS — CreateOpportunity](https://docs.aws.amazon.com/partner-central/latest/APIReference/API_CreateOpportunity.html)
- [Microsoft — Create a referral](https://learn.microsoft.com/en-us/partner-center/developer/create-a-referral)
- [Google Cloud — opportunities](https://docs.cloud.google.com/channel/docs/reference/rest/v1alpha1/opportunities)
