Create a Referral via API

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


Overview

This page is the developer companion to the Outbound Referral UI walkthrough. It documents the request payload for one endpoint:

POST /org/{orgId}/cosell/referral
  • Auth: API key (Authorization header). See Authentication.
  • Query param: forceCreate (boolean, optional). When true, the referral is saved in Fours 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).

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 (to resubmit, send the referral back to this endpoint with its id — see Response & next steps).

The envelope

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

{
  "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 */ }
}

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

partnerSend the opportunity underBody type
AWSinfo.aceOpportunityV2AWS Partner Central opportunity
AZUREinfo.createMicrosoftReferralRequestMicrosoft Partner Center referral
GCPinfo.gcpOpportunityV2Google Cloud opportunity

Two tiers of “required”

Throughout this page, required fields fall into two groups:

  • Required by Fours — missing/invalid values return a 400 before anything reaches the cloud partner. These are the hard blockers.
  • Required by the cloud partner — Fours may accept the payload, but AWS/Microsoft/Google will reject it. Fours’ 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:

{
  "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 Fours

Field (under info.aceOpportunityV2)Rule
Customer.Account.IndustryNon-empty; from the AWS industry list
Customer.Account.CompanyNameNon-empty (truncated to 120 chars)
Customer.Account.WebsiteUrlValid URL — waived only when NationalSecurity is "Yes"
Customer.Account.Address.CountryCodeISO 3166-1 alpha-2
Customer.Account.Address.PostalCodeMust match the country’s postal pattern
Customer.Account.Address.StateOrRegionRequired only when CountryCode is US
PrimaryNeedsFromAwsArray, at least one value. See AWS field options
Project.CustomerBusinessProblemNon-empty, at least 20 characters (over 2000 is truncated)
RelatedEntityIdentifiers.SolutionsArray of your AWS Solution IDs, at least one. See Where Solution IDs come from
LifeCycle.TargetCloseDateYYYY-MM-DD, subject to the close-date policy below

Conditionally blocked by Fours

These are rejected only when present and invalid. Omit one entirely and Fours’ validator passes — then AWS rejects the submission and the referral lands in CREATE_FAILED. Send them.

FieldRule when present
Project.CustomerUseCaseMust be a valid use-case value
Project.DeliveryModelsRejected only if every value is invalid; otherwise invalid entries are dropped
Project.ExpectedCustomerSpend[0].AmountMust parse as a number and be >= 0

Also required by AWS (Fours does not block these)

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

FieldNotes
OpportunityTypeYou provide it: Net New Business | Flat Renewal | Expansion. Silently cleared if invalid, not rejected
Project.TitleYou provide it
Project.SalesActivitiesFours defaults if omitted
OriginYou provide it: Partner Referral (the only valid value for Catalog: AWS)
Marketing.SourceFours fills (None)
PartnerOpportunityIdentifierFours sets it to the referral ID

So beyond Fours’ hard-blocked list, the fields you must supply for AWS to accept are Origin, OpportunityType, Project.Title, Project.CustomerUseCase, Project.DeliveryModels, and Project.ExpectedCustomerSpend[0].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.

The TargetCloseDate policy

A past close date is not simply rejected. Fours decides per case, so a recently-slipped opportunity still goes through while a stale one is surfaced instead of being quietly laundered into a future date:

LifeCycle.TargetCloseDateWhat happens
Missing or unparseableRejected
More than 30 days in the pastRejected as stale
In the past, but within the last 30 daysAuto-pushed forward to today + 30 days
Today or in the futureKept, reformatted to YYYY-MM-DD

Where Solution IDs come from

AWS has no solution-lookup endpoint (unlike Azure). Your Solution IDs are synced from ACE onto the integration itself — read them from GET /org/{orgId}/integration/AWS/ACE:

  • info.awsAceIntegration.offeringsV2[] — each entry is { id, type, title }; id is what goes in Solutions
  • info.awsAceIntegration.offerings[] — the older flat array of id strings

The same response carries info.awsAceIntegration.catalog, which tells you whether you are pointed at AWS (production) or Sandbox.

Auto-filled / normalized by Fours

  • 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 to ["Initialized discussions with customer"] when empty or when every value is invalid.
  • NationalSecurity defaults to "Yes" when Industry is "Government" and you left it blank or sent something other than "Yes"/"No". An explicit "No" is preserved.
  • LifeCycle.Stage is cleared if it isn’t a valid stage. Project.CompetitorName, Customer.Account.Duns (9 digits) and Customer.Account.AwsAccountId (12 digits) are cleared if invalid.
  • Project.AdditionalComments and LifeCycle.NextSteps are truncated to 255 characters.
  • OpportunityTeam members with no usable email are dropped. Customer Contacts are not dropped — an unusable email or phone is just blanked.
  • OpportunityTeam[0] defaults to BusinessTitle: "PartnerAccountManager" and OpportunityTeam[1] to "OpportunityOwner". The PartnerAccountManager also gets a default phone number if theirs is missing or unusable.

AWS field options

PrimaryNeedsFromAws — at least one. Any Co-Sell - * value asks AWS for help; Do Not Need Support from AWS Sales Rep files the opportunity without it.

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 · Do Not Need Support from AWS Sales Rep

OpportunityType — Net New Business · Flat Renewal · Expansion

Project.DeliveryModels — SaaS or PaaS · BYOL or AMI · Managed Services · Professional Services · Resell · Other

Project.SalesActivities — Initialized discussions with customer · Customer has shown interest in solution · Conducted POC / Demo · In evaluation / planning stage · Agreed on solution to Business Problem · Completed Action Plan · Finalized Deployment Need · SOW Signed

LifeCycle.Stage — Prospect · Qualified · Technical Validation · Business Validation · Committed · Launched · Closed Lost

Customer.Account.Industry — Aerospace · Agriculture · Automotive · Computers and Electronics · Consumer Goods · Education · Financial Services · Gaming · Government · Healthcare · Hospitality · Life Sciences · Manufacturing · Marketing and Advertising · Media and Entertainment · Mining · Non-Profit Organization · Energy - Oil and Gas · Other · Energy - Power and Utilities · Professional Services · Real Estate and Construction · Retail · Software and Internet · Telecommunications · Transportation and Logistics · Travel · Wholesale and Distribution

Project.CustomerUseCase — AI Machine Learning and Analytics · Archiving · Big Data: Data Warehouse / Data Integration / ETL / Data Lake / BI · Blockchain · Business Applications: Mainframe Modernization · Business Applications & Contact Center · Business Applications & SAP Production · Centralized Operations Management · Cloud Management Tools · Cloud Management Tools & DevOps with Continuous Integration & Continuous Delivery (CICD) · Configuration, Compliance & Auditing · Connected Services · Containers & Serverless · Content Delivery & Edge Services · Database · Edge Computing / End User Computing · Energy · Enterprise Governance & Controls · Enterprise Resource Planning · Financial Services · Healthcare and Life Sciences · High Performance Computing · Hybrid Application Platform · Industrial Software · IOT · Manufacturing, Supply Chain and Operations · Media & High performance computing (HPC) · Migration / Database Migration · Monitoring, logging and performance · Monitoring & Observability · Networking · Outpost · SAP · Security & Compliance · Storage & Backup · Training · VMC · VMWare · Web development & DevOps

For CountryCode (ISO 3166-1 alpha-2) and the AwsProducts list, see the AWS CreateOpportunity API reference.

Example payload (AWS)

This mirrors the field set the Fours Console submits (the Share with AWS form), so it includes the Fours-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 Fours fills. Treat the AWS reference as the source of truth for what AWS will accept.

{
  "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": "[email protected]", "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": "2027-06-30",                   // required; YYYY-MM-DD — see "The TargetCloseDate policy" above
        "NextSteps": "Schedule joint architecture review"  // optional (<= 255 chars)
      },

      "RelatedEntityIdentifiers": {
        "Solutions": ["S-0123456"],                        // required, >= 1 — from GET /org/{orgId}/integration/AWS/ACE
        "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": "[email protected]", "Phone": "+14155550100", "BusinessTitle": "PartnerAccountManager" },
        { "FirstName": "Jordan", "LastName": "Lee", "Email": "[email protected]", "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 — Fours 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 Fours

Field (under info.createMicrosoftReferralRequest)Rule
nameDeal name, non-empty
details.closingDateTimeUTC datetime (YYYY-MM-DDTHH:MM:SSZ), today or future
details.dealValueNumber > 0
details.currencyISO 4217 code (defaults to USD if blank)
customerProfile.address.countryISO 3166-1 alpha-2 (defaults to US if blank)
team[]At least one member, each with email, firstName, lastName, phoneNumber
details.requirements.solutions[].idAt least one solution (for Private / IPCosell deals)
details.requirements.additionalRequirements.attributes[]One SolutionArea and one matching Conversation attribute; plus CustomerMarketplaceIntent for Private/IPCosell. See Field options

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).

Fours auto-sets type, status, substatus and dealType, and auto-fixes missing phone numbers.

Field options

dealType

Fours derives this for you — an invitation asking Microsoft for help makes it IPCosell, no invitation makes it Private — so you only need to send it to choose ServicesCosell.

ValueLabel in the consoleRequiresSilently removed
PrivatePrivatesolutions[], CustomerMarketplaceIntentPartnerRole
IPCosellIP Co-sellsolutions[], CustomerMarketplaceIntentPartnerRole
ServicesCosellService Co-sellPartnerRole (solutions[] optional)CustomerMarketplaceIntent

assistanceRequestCode

Set on each invitations[] entry. Anything other than NoHelpRequired turns the referral into a co-sell.

ValueMeaning
NoHelpRequiredNo help required at this point of time
WorkloadSpecificValuePropositionWorkload-specific value proposition
CustomerTechnicalArchitectureCustomer technical architecture
ProofOfConceptOrDemoProof of concept / Demo
QuotesOrLicensingQuotes / Licensing
PostSalesCustomerSuccessPost-sales customer success
GeneralOrOtherGeneral or other

SolutionArea and Conversation

Send both as entries in details.requirements.additionalRequirements.attributes[], where id is the display string below — not a GUID. Microsoft validates the pair, so a valid conversation under the wrong solution area is rejected.

SolutionAreaValid Conversation values
AI Business SolutionsAI-ready productivity and security for every employee
Agentify your business processes
AI in the flow of human ambition
Cloud and AI PlatformsModernize with confidence
Build a unified governed data and AI estate
Amplify your intelligence
Ubiquitous Innovation
Microsoft ServicesAccelerate AI Transformation with Microsoft Services
SecurityAI-ready productivity and security for every employee
Establish a trusted and secure platform for AI
Windows and DevicesAI Transformation with Surface and Copilot

CustomerMarketplaceIntent

Required for Private and IPCosell. If you omit it or send an unrecognized value, Fours defaults it to HaveNotDecided rather than rejecting the referral.

ValueLabel in the console
YesYes
NoNo
HaveNotDecidedHave not decided

PartnerRole

Required for ServicesCosell only, and removed from other deal types.

Adoption and change management · Business strategy · Deployment services · Managed services · Presales envisioning · Proof of concept · Solution design · Transaction

currency and country

details.currency is an ISO 4217 code and customerProfile.address.country is an ISO 3166-1 alpha-2 code, both validated against Microsoft’s picklists. An unrecognized value is not an error — Fours falls back to USD and US respectively. For the full lists see the Microsoft “Create a referral” reference.

Example payload (Azure, independent / no Microsoft help)

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

{
  "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": "[email protected]", "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": "2027-06-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 — see "Field options" above
              { "type": "SolutionArea", "id": "Cloud and AI Platforms" },
              { "type": "Conversation", "id": "Modernize with confidence" },
              { "type": "CustomerMarketplaceIntent", "id": "HaveNotDecided" }
            ]
          }
        }
      }
    }
  }
}

Fours 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):

"invitations": [
  { "organizationId": "msft", "organizationName": "Microsoft", "assistanceRequestCode": "ProofOfConceptOrDemo" }
],
"customerProfile": {
  "address": { "country": "US" },
  "team": [                                              // required for co-sell: >= 1 customer contact
    { "firstName": "Dana", "lastName": "Cruz", "email": "[email protected]", "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.partnerEntityFormat partners/{id}
customerInfo.customerDetails.organizationNameNon-empty
customerInfo.customerDetails.domainValid domain
customerInfo.customerDetails.address.regionCodeISO 3166-1 alpha-2
customerInfo.customerDetails.address.postalCodeRequired for most countries (US: 12345 or 12345-6789)
customerInfo.customerDetails.industryFrom the GCP industry list
customerInfo.customerDetails.employeeCountInteger > 0
customerInfo.contact.givenName, .familyName, .emailAll required
customerInfo.regionOne of ANZ, CEE, DACH, FRANCE, INDIA, JAPAN, LATAM_BRAZIL, LATAM_SPANISH_SPEAKING, NE, NORTH_AMERICA, OTHER_ASIA_PACIFIC, SEEMEA, UK_AND_I
qualificationInfo.contractLengthMonthsInteger 1–96
qualificationInfo.estimatedCloseDate{ year, month, day }, future date
qualificationInfo.dealSize.currencyCodeUSD for GCP/Google Maps product categories
qualificationInfo.dealSize.unitsPositive integer as a string, e.g. "50000"
qualificationInfo.legalLanguageAcceptedMust be true (GCP requirement)

Required for Regular only

FieldRule
opportunityInfo.productCategory[0]From the GCP product-category list (e.g. GCP_COMPUTE, GCP_AI, GOOGLE_MAPS)
qualificationInfo.operationTypeNEW, RENEWAL, ADD_ON, EXPANSION
qualificationInfo.quantityInteger ≥ 1
qualificationInfo.budgetEXACT_BUDGET_GIVEN, BUDGET_EXISTS_NOT_SPECIFIED, CONFIRMED_NO_BUDGET, REFUSE_TO_DISCLOSE
qualificationInfo.authorityCLEARLY_IDENTIFIED_PROCESS, CONFIRMED_NO_AUTHORITY_DECIDED, VAGUE_UNDERSTANDING, DONT_KNOW
qualificationInfo.needCLEAR_NEED, COMPELLING_NEED, NO_NEED
qualificationInfo.timelineSPECIFIC_DECISION_DATES_GIVEN, VAGUE_DECISION_DATES_GIVEN, CONFIRMED_NO_DECISION_DATE, REFUSED_TO_GIVE_DATE
qualificationInfo.decisionPhaseFINAL_DECISION, TRIAL_OR_PILOT, INFORMATION_GATHERING

Required for ISV Solution Connect only

FieldRule
opportunityInfo.productFamily[0]GOOGLE_CLOUD_PLATFORM or GOOGLE_WORKSPACE
opportunityInfo.descriptionNon-empty
isvSolutionConnectInfo.contractVehicleCLOUD_MARKETPLACE, PARTNER_CONTRACT, UNKNOWN
isvSolutionConnectInfo.deliveryModelDATA_TO_CUSTOMER_BIGQUERY, VM_ON_CUSTOMER_TENANCY, SAAS_ON_GOOGLE_CLOUD, OTHER_DELIVERY_MODEL
isvSolutionConnectInfo.supportLevelTECH, 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.

Example payload (GCP — Regular)

{
  "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": "[email protected]",  // 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)

{
  "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": "[email protected]",  // 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 — Fours’ 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. To resubmit, GET the referral, correct it, and POST it back to .../cosell/referral with the same id — Fours resubmits that referral in place. A body without the id creates a new referral instead.
  • Do not call sync for the initial submit — submission is automatic.
  • To edit a referral later, use PATCH /org/{orgId}/cosell/referral/{referralId}. The outbound sync to the partner starts automatically — do not call sync afterwards.

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 Fours the flag is ignored and the normal update path is used.

  • An AWS referral in CREATE_FAILED can’t be edited here. AWS never accepted it, so there is nothing to update: resubmit it instead, by sending it back to POST .../cosell/referral with the same id (see Response & next steps). The PATCH is refused with 400, and the referral is left unchanged:

    // excerpt of the 400 response
    "info": [
      { "field": "status", "message": "referral <referralId> failed to create (status CREATE_FAILED) and cannot be edited via update; fetch it with GetCosellReferral and resubmit it by calling CreateCosellReferral again with the same id" }
    ]

    A linkage-only update (isLinkageUpdate=true) is not affected.

Partial updates (merge=true, AWS only)

By default a PATCH body replaces the referral’s stored content, so every field has to be sent. Pass merge=true — as a query parameter or in the body — to patch only the fields you send instead. It is supported for AWS only, and the body must always carry "partner": "AWS".

  • What merge does with each field. A field you omit keeps its stored value, a field you send replaces it, and an explicit null clears it. The exceptions are info.aceOpportunityV2.lifeCycle.reviewStatus and lifeCycle.stage: they cannot be cleared, so sending either as null keeps its stored value rather than emptying it.
  • Objects vs. lists. Nested objects merge key by key; lists (such as contacts or solutions) are replaced whole, not merged — send the complete list when you change one entry.
  • What is preserved. Merging covers the referral’s top-level fields and info.aceOpportunityV2. Other info sub-documents — for example aceEngagementInvitation — are not preserved by an update.
  • When it is rejected with 400. For a non-AWS partner, when combined with isLinkageUpdate=true, and for an engagement-invitation accept/reject — send the full referral body for those.

The outbound sync to the partner still starts automatically after a merge update; do not call sync afterwards.

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):

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' => '[email protected]', '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' => '2027-06-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' => '[email protected]', 'Phone' => '+14155550100', 'BusinessTitle' => 'PartnerAccountManager' },
        new Map<String, Object>{ 'FirstName' => 'Jordan', 'LastName' => 'Lee', 'Email' => '[email protected]', '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 Fours 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).
  • updateCosellReferral calls the same PATCH endpoint, so it is refused for an AWS referral in CREATE_FAILED. To resubmit one, call Suger.CosellApi.createCosellReferral with the referral including its id.

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:

InputRequiredNotes
PartnerYesAWS, AZURE, or GCP.
Opportunity IDNoBuilds the payload from a CRM opportunity via field mapping (the original behavior).
Referral Payload (JSON)NoA 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.

Listing referrals

GET /org/{orgId}/cosell/referral lists both inbound and outbound referrals, with pagination, sorting, and a filter expression.

Filter syntax

Pass the filter in q. The default query syntax is lisp, so an expression looks like this:

q=(and (= partner "AWS") (= status "IN_REVIEW"))

The operators below cover the common cases. The filter language accepts more than these — negated forms such as not_like and not_between, array-membership operators, and dash-spelled aliases like not-in — so treat this as the working set rather than the complete grammar:

CategoryOperators
Comparison= · != · > · >= · < · <=
Set membershipin · not_in
Text matchinglike · ilike · contains · starts_with · ends_with
Null checksis_null · is_not_null
Rangebetween
Combiningand · or · not

Legal values for status are the Fours unified statuses, in UPPER_SNAKE_CASE: DRAFT, PENDING_CREATE, CREATE_FAILED, UPDATE_FAILED, IN_REVIEW, PENDING_ACCEPTANCE, ACTION_REQUIRED, ACTIVE, EXPIRED, CLOSED_WON, CLOSED_LOST, CLOSED_ERROR, and REJECTED.

Rows the list never returns

Two kinds of row are filtered out server-side, so you cannot retrieve them by asking for them:

ExcludedWhy
Any referral whose status is DELETEDDeleted referrals are hidden from every list.
partner=SUGER and status=DRAFTA Fours partner-to-partner draft is an inbound deal registration still awaiting your review, not a referral yet. It is excluded from this endpoint, from the dashboard, and from the commission ledger.

The SUGER + DRAFT exclusion is scoped to that exact pair. Azure has its own legitimate DRAFT flow, and Azure drafts are returned normally.

Full API reference

For the complete request/response schema and to try the endpoint, see Create Co-Sell Referral (POST /org/{orgId}/cosell/referral) in the Fours API reference. The authoritative field definitions for each cloud are the partner references linked above:

Spotted something wrong or out of date on this page? Tell us and we'll correct it.