Edit a deal-registration draft before confirming
PATCH https://api.suger.cloud/org/{orgId}/cosell/dealRegistrationDraft/{draftId}
Allowlist patch onto a partner=SUGER, status=DRAFT co-sell row (ISV review queue): only info.sugerOpportunity.customerInfo,.dealDetails,.type,.dealRole,.collaborationContext,.revenueShareTerms,.showDealValue,.team, and.dealRegistrationDraft.matchedPartnershipId are applied from the request body — every other field is ignored. `customerInfo` and `dealDetails` REPLACE the stored objects wholesale, so send every field you want kept, not just the changed one (read the draft first). Use this to fill in a draft's `missingFields`, correct extracted customer/deal fields, or attach the matched partnership before the ISV confirms it in the console. Returns 404 for a referral id that is not currently a SUGER draft. A non-empty dealRegistrationDraft.matchedPartnershipId must name an ACTIVE or PENDING partnership owned by this org. The response carries the updated draft and its remaining `missingFields`.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
orgId | path | string | yes | Organization ID |
draftId | path | string | yes | Deal Registration Draft ID (cosell referral ID) |
Request Body
Required. Content-Type: application/json · Schema: SugerOpportunity
SugerOpportunity fields:
| Field | Type | Required | Description |
|---|---|---|---|
acceptedDateTime | string | no | AcceptedDateTime is when the partner accepted. |
attributionRole | SugerAttributionRole | no | |
closedLostReason | string | no | ClosedLostReason is set when the ISV closes the deal as lost. |
collaborationContext | SugerCollaborationContext | no | |
commissionLifecycle | CommissionLifecycle | no | |
commissionPreview | SugerCommissionPreview | no | |
commissionsDisabled | boolean | no | Multi-partner attribution: the create API is single-partner (top-level partnerId + attributionRole + revenueShareTerms describe THE partner); additional partners join an existing engagement through the InviteCosellPartners endpoint (SugerCoSellPartnerInput body), each getting its own reseller copy. The per-engagement partner summary for the list table is response-level (ListCosellReferralsResponse.EngagementPartners, keyed by referral id) — never a field on this persisted struct. CommissionsDisabled snapshots, at create time, that the PRM Cosell Commissions feature was NOT in play for this deal — stamped true only when either party lacked the feature (the bilateral both-on check failed). Mirrored identically to both copies and immutable after create, so a later org-config flip never rewrites an in-flight deal. The zero value (false) is the safe default: legacy rows and any un-stamped row read as commissions active. Read via CommissionsActive; never the raw negative. When true, the commission surface (revenue-share terms, preview, lifecycle) is absent for the deal on both sides (PRM_COSELL_COMMISSIONS). |
conversations | array<SugerCosellConversation> | no | Conversations is the in-platform conversation thread surfaced on the co-sell detail page's Activity tab ( Component 5). Each entry is one message from a participant. Email replies are NOT stored here — those are queried separately via the auditing / notification-event APIs. This array is for in-platform conversation only. READ-ONLY on the write path: clients receive this on GET responses but MUST NOT modify it via PATCH. Direct changes via this field are rejected by the validator (CONVERSATION_DIRECT_EDIT). To add a message, send `newConversations` instead — the server stamps actor identity and appends. SHARED CROSS-COPY: like CommissionLifecycle, both copies of the engagement carry the same Conversations. The engagement-sync workflow propagates additions to the counterpart row so seller and partner always see the same thread. |
createdDateTime | string | no | CreatedDateTime is when this referral was created. |
customerInfo | SugerCustomerInfo | no | |
dealDetails | SugerDealDetails | no | |
dealRegistrationDraft | SugerDealRegistrationDraft | no | |
dealRole | SugerDealRole | no | |
declineReason | string | no | DeclineReason is set when the partner declines. |
direction | string | no | Direction is "Outbound" (ISV) or "Inbound" (partner). |
engagementId | string | no | EngagementID is a shared UUID linking the ISV's and partner's referral rows. |
expirationDateTime | string | no | ExpirationDateTime is when the co-sell expires if not accepted. |
externalReferenceId | string | no | ExternalReferenceID is the CRM opportunity ID or any external reference ID. |
matchedBuyerId | string | no | MatchedBuyerID is the identity.buyer record auto-matched to this co-sell's end customer by domain (CustomerInfo.Website → buyer info.companyInfo.emailDomain), set on the ISV's (outbound) copy. Drives the §3 CPPO↔co-sell linking and the "End Customer ✓ Matched" surface. Empty when no unambiguous buyer matched ( §2). |
newConversations | array<SugerCosellConversation> | no | NewConversations is the REQUEST-ONLY append channel for the in- platform conversation thread. Clients submit one or more new messages here on PATCH; the server stamps ID / actor identity / timestamp / source server-side, validates Body is non-empty, appends to Conversations, and clears NewConversations before persisting (the persisted shape never carries this field at the parent level). |
nextSteps | string | no | NextSteps is a per-party, free-form field describing the immediate next actions for this co-sell. Either party can edit their own copy; never synced across copies. |
onBehalfRegistration | SugerOnBehalfRegistration | no | |
partnerActionGrants | object | no | PartnerActionGrants records the one-click credentials issued to partners who DO have a console login — accept, close won, close lost, approve commission change. Same credential type and the same storage contract as the map above: hashes only, cleared on use, so what remains is an audit record rather than anything that can act. The shape is the whole difference between the two, and it is the semantic difference: a token is ONE credential per action, a grant is one per RECIPIENT per action, because the email that carries a grant is addressed to one person. Sharing a credential across a deal team would record every click under whoever the first address happened to be. A second field rather than a wider first one: widening would turn a JSON object into an array on every on-behalf row already in the database. Unlike PartnerActionTokens these authorize action on THIS row, and they do not stand alone: consuming one resolves IssuedToEmail to a Fours user and requires that user to hold an editing role in this row's organization. The credential says which action, on which row, offered to whom; the membership check says whether that person may perform it. Server-owned: create drops it from the request body and the update merge never copies it from a patch, so a client value can never be persisted — a stale echo from the console is simply ignored. |
partnerActionTokens | object | no | PartnerActionTokens records the one-click partner actions BEYOND registration — confirming Close Won and confirming payment receipt. It holds only the SHA-256 HASH of each credential, never the credential itself: the opaque token exists solely in the email sent to the partner, and is verified by hashing what the partner presents and comparing. The hash is cleared on use, so the entry that remains is an audit record (who it was issued to, when it expired, when it was consumed) rather than anything that can act. Reading this field grants no ability to perform the action. This is also why the public API schema description must not call these "credentials" — see SugerPartnerActionToken. Present only on on-behalf co-sells: an ordinary partner has a console login and gets a deep link instead, so no unauthenticated mutation credential is ever minted for them. A map rather than more fields on SugerOnBehalfConfirmation because that struct holds exactly ONE TokenHash, which cannot represent three actions outstanding at once. Keying by action is also what makes the credential action-scoped: a Close Won link cannot confirm a payment, because the dispatcher only applies the action whose hash matched. Server-owned, like OnBehalfRegistration — see rejectOnBehalfRegistrationEdit. |
partnerIds | array<string> | no | PartnerIds lists the Partnership ids, in this copy's own organization, of every counterparty partner in the engagement. On a seller's copy that is one id per participating partner, including partners invited after the co-sell was created; on a partner's copy it is the single partnership with the seller. Server-owned: values supplied by a client are ignored. |
partnerTeam | array<SugerTeamMember> | no | PartnerTeam is the people at the partner the co-sell was shared to, the partner champion first (as on SugerCoSellPartnerInput). Stored only on the partner's own copy, where it is also seated as Team. Server-owned after create: an update cannot change it. Empty on co-sells shared before the choice existed. |
publicRegistration | SugerPublicRegistration | no | |
recipientMode | SugerPartnerRecipientMode | no | |
revenueShareTerms | SugerRevenueShareTerms | no | |
showDealValue | boolean | no | ShowDealValue controls whether THIS copy's owner sees the full deal value. Per-partner and Seller-set (create/invite ShowDealValueToPartner, or the Seller's accept-time choice on reseller-initiated deals), it lives on each reseller (partner) copy like AttributionRole — a sharing control, NOT a commission term, so it exists independently of RevenueShareTerms and survives commissions-disabled deals. Never engagement-synced; server-set only (the generic referral PATCH ignores it). Pointer so nil ("not set" — default visible) is distinct from an explicit false ("hidden"); nil-or-true means visible. The read-path redaction (RedactHiddenDealValue / RedactHiddenDealValueForReferrals) clears the numeric deal-value fields on a Referrer copy when this is false. |
stage | string | no | Stage is the deal lifecycle stage. The vocabulary is SugerCosellStage — Title Case with spaces ("Pending", "Active", "In Discovery", "Proposal Sent", "Negotiating", "On Hold", "Won", "Lost"), NOT lowercase snake_case. Bulk imports can write anything, so readers must treat an unrecognised value as unknown rather than assume the enum. |
status | string | no | Status is the per-copy sharing state. The vocabulary is SugerReferralStatus — UPPER_CASE ("DRAFT", "PENDING_ACCEPTANCE", "ACTIVE", "REJECTED", "CLOSED_WON",...), NOT lowercase. Readers should compare against the typed constants. |
team | array<SugerTeamMember> | no | Team is this copy's own org team members. Each copy holds only its own members; a party sees counterpart teams via the engagement view (EngagementPartner.Team). |
type | string | no | Type is the opportunity type: "New Business", "Renewal", "Expansion", "Add On". |
updatedDateTime | string | no | UpdatedDateTime is when this referral was last updated. |
SugerCollaborationContext fields:
| Field | Type | Required | Description |
|---|---|---|---|
dealRole | SugerDealRole | no | |
invitedBy | SugerInvitedByInfo | no | |
notes | string | no | Notes are free-form notes from the originating party to the partner. |
partnerNeeds | array<string> | no | PartnerNeeds enumerates what the originating party needs from the partner. |
CommissionLifecycle fields:
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | no | Amount is the canonical commission the Payee earns, computed ONCE at initialization (PENDING) from the Revenue Share terms + Deal Value at Won. Frozen thereafter — later edits to terms or deal value do not recompute. This is what the Partner reads on the dashboard so the showDealValue toggle never gates them out of seeing their own pay. |
currency | string | no | Currency is the ISO-4217 currency for Amount. |
history | array<CommissionLifecycleEntry> | no | History is the append-only audit trail. Server-authoritative — clients never write to this field. |
note | string | no | Note is REQUEST-ONLY. See top-of-block comment for the protocol. Persisted shape always has Note empty at the parent level. |
proposedUpdate | CommissionUpdateProposal | no | |
requestActorOrgId | string | no | |
requestActorUserId | string | no | RequestActorUserID / RequestActorUserName / RequestActorOrgID are REQUEST-ONLY companions to Note. The HTTP route handler resolves the caller's identity from the auth context and stamps these BEFORE calling UpdateReferral. The validator copies them onto each new history entry it builds (excluding system-only revert entries), then the handler clears them before persisting. Persisted read responses NEVER carry non-empty values for these fields. This mirrors the request-only Note pattern rather than introducing a context-based user helper (which the codebase doesn't have today). |
requestActorUserName | string | no | |
state | CommissionLifecycleState | no |
SugerCommissionPreview fields:
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | no | Amount is the computed commission. 0 is a legitimate resolved value (Percentage=0, Fixed=0, or deal-below-MinDealValue); see ComputeCommissionValue for the resolution rules. |
currency | string | no | Currency is the ISO 4217 code paired with Amount. For Fixed Amount model this is ShareCurrency; for Percentage / TBD it rides the deal currency. |
guardrailReason | SugerCommissionGuardrailReason | no |
SugerCosellConversation fields:
| Field | Type | Required | Description |
|---|---|---|---|
authorEmail | string | no | email at post time |
authorId | string | no | identity.user.id |
authorName | string | no | display name at post time |
authorOrgId | string | no | org id of the posting side |
body | string | no | plain text; rendered as text on the frontend |
createdAt | string | no | |
id | string | no | UUID generated server-side. |
parentId | string | no | threading + Slack sync (all optional, zero migration): |
slackChannelId | string | no | which channel this thread lives in |
slackMessageTs | string | no | this message's ts; also dedups the inbound pull |
slackThreadTs | string | no | Slack sync coordinates, stamped by SyncOutbound after a successful mirror. A mirrored message lives in exactly one Slack channel (the engagement's shared partner channel), so a single set of scalars is sufficient. |
source | SugerCosellConversationSource | no | |
visibility | CosellConversationVisibility | no |
SugerCustomerInfo fields:
| Field | Type | Required | Description |
|---|---|---|---|
address | SugerAddress | no | |
companyName | string | no | |
country | string | no | Country is the ISO 3166-1 alpha-2 country code (e.g., "US", "CA", "GB"). |
industry | string | no | |
website | string | no |
SugerDealDetails fields:
| Field | Type | Required | Description |
|---|---|---|---|
closingDateTime | string | no | |
customerBusinessProblem | string | no | |
dealValueAmount | number | no | |
dealValueCurrency | string | no | DealValueCurrency is the ISO 4217 currency code (e.g., "USD", "EUR", "GBP"). |
deliveryModel | array<string> | no | |
name | string | no | |
targetCloseDate | string | no | |
useCase | string | no |
SugerDealRegistrationDraft fields:
| Field | Type | Required | Description |
|---|---|---|---|
askMessageIds | array<string> | no | AskMessageIDs is the subset of KnownMessageIDs that are OUR OWN outbound gap-filling asks (ActivityMaybeAskDealRegGaps), in send order. |
askRounds | integer | no | AskRounds counts how many gap-filling asks have been sent. ActivityMaybeAskDealRegGaps caps this at 2 so an unresponsive or endlessly-partial thread doesn't nag a partner forever. |
askedContacts | array<string> | no | AskedContacts is every recipient email a gap-filling ask has been sent to — a reply from any of them is accepted onto this draft's thread even when it doesn't equal SenderEmail. |
createdReferralId | string | no | CreatedReferralID is set when the ISV confirmed this draft (ConfirmDealRegistrationDraft) — the referral the thread now belongs to. Only ever set on a soft-deleted (status DELETED) draft row: a later reply on the same thread correlates to the draft by Message-ID as before, but is routed onto this referral's Activity timeline (recordInboundEmailForReferral) instead of resurrecting a new draft. |
extractedContacts | array<SugerDealRegistrationContact> | no | ExtractedContacts are the customer-side contacts the AI extraction ( slice 3, cosell/ActivityExtractDealRegistrationDraft) found in the source email. Surfaced on the ISV review screen for reference only — they are NOT auto-mapped onto the referral (neither SugerCustomerInfo nor SugerOpportunity has a customer-contacts field); an ISV who wants to act on one copies it in manually. |
extractionError | string | no | |
extractionStatus | string | no | PENDING | COMPLETED | FAILED |
knownMessageIds | array<string> | no | KnownMessageIDs is every Message-ID belonging to this draft's email thread — the originating email, every correlated reply, and every outbound gap-filling ask — used to correlate a newly inbound email to this draft via its In-Reply-To/References headers (recordDealRegistrationDraft's thread-correlation step). |
lastAskAt | string | no | LastAskAt is when the most recent gap-filling ask was sent. |
matchedPartnershipId | string | no | |
originatingMessageId | string | no | RFC 5322 Message-ID |
readyNotifiedAt | string | no | ReadyNotifiedAt stamps the one-and-only "ready to confirm" notification (ActivityNotifyDealRegReady). Non-nil means it has been sent — the notification must never repeat, or every later reply on the thread would re-send it. |
senderAuthTier | string | no | SenderAuthTier is stamped at draft creation — see SugerDealRegistrationDraftSenderAuthTier. |
senderEmail | string | no | |
senderName | string | no | |
slack | SugerDealRegistrationSlackSource | no | |
source | string | no | "EMAIL" |
sourceObjects | array<SugerDealRegistrationSourceObject> | no | SourceObjects is every email — the originating message plus every correlated follow-up reply — that has contributed extraction input to this draft, oldest first. |
suggestedConfirmationContact | PartnerChampionContact | no | |
threadParticipants | array<string> | no | ThreadParticipants is every To/Cc address on the draft's originating email, lowercased, excluding our own sesDomain addresses (the dealreg-<orgId>@ / cosell-<referralId>@ sinks themselves) — threadParticipantsFromEnvelope. This is the ISV member's per-deal trust grant: a reply from any of these addresses is accepted onto the thread as a follow-up (dealRegistrationFollowUpAuthorized) even though it isn't SenderEmail. Since restricted draft creation to ORG_MEMBER only, this is how a partner participates in a thread they could never have originated themselves — the ISV CCs (or TOs) them on the original email. |
SugerOnBehalfRegistration fields:
| Field | Type | Required | Description |
|---|---|---|---|
confirmation | SugerOnBehalfConfirmation | no | |
pendingPartnerInput | SugerCoSellPartnerInput | no | |
registeredByUserId | string | no | RegisteredByUserID is the ISV user who performed the registration. |
registeredByUserName | string | no | RegisteredByUserName is denormalized for display so the attribution line survives the user being removed and rendering needs no user lookup. Same rationale as SugerInvitedByInfo.OrganizationName. |
registrationSource | SugerRegistrationSource | no |
SugerTeamMember fields:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | no | |
name | string | no | |
role | string | no | Role is a system-set role (e.g., "Partner Manager"), not user-editable. |
title | string | no |
SugerPublicRegistration fields:
| Field | Type | Required | Description |
|---|---|---|---|
invitationId | string | no | InvitationID is the held PartnerInvitation raised for this submission, so accepting the co-sell can mark it accepted too. |
registeredAt | string | no | RegisteredAt is when the public form was submitted. |
submitterEmail | string | no | SubmitterEmail / SubmitterName identify who registered the deal via the public form (the partner-side contact). Display + audit only. |
submitterName | string | no |
SugerRevenueShareTerms fields:
| Field | Type | Required | Description |
|---|---|---|---|
clawbackWindowDays | integer | no | ClawbackWindowDays is the agreed grace period (in days) after the commission is paid during which the commission can be reversed if the deal churns. Zero/unset means "no clawback applies" — the Clawed Back state is unavailable on the lifecycle. When set (>0), the detail UI computes Clawback Expiry Date = PaymentDate + ClawbackWindowDays. |
commissionType | string | no | Referral Fee, Reseller Margin, Cosell Split, Finder Fee |
maxCap | number | no | MaxCap is the per-deal commission ceiling, snapshotted from the matching CommissionSetting at terms-agreed time. Pointer so nil ("no cap") distinguishes from an explicit cap of 0. ComputeCommissionValue clamps the computed commission to this value when set. |
minDealValue | number | no | MinDealValue is the per-deal threshold below which no commission is earned, snapshotted from the matching CommissionSetting at terms-agreed time. Pointer so nil ("no floor") distinguishes from an explicit 0. ComputeCommissionValue returns a $0 commission when DealValueAmount is below this floor; the lifecycle still runs so the audit trail records the closed-Won transition. |
paymentTrigger | string | no | On Close, On Invoice, On Payment, Custom |
revenueShareModel | SugerRevenueShareModel | no | |
revenueShareNotes | string | no | |
shareAmount | number | no | flat fee, used when model is "Fixed Amount" |
shareCurrency | string | no | ISO 4217, paired with ShareAmount |
sharePercentage | number | no |
Responses
200 — OK
Content-Type: application/json · Schema: DealRegistrationDraftResponse
DealRegistrationDraftResponse fields:
| Field | Type | Required | Description |
|---|---|---|---|
approvalInfo | ApprovalInfo | no | |
contactIDs | array<string> | no | ContactIds holds the value of the "contact_ids" field. |
creationRetryCount | integer | no | CreationRetryCount holds the value of the "creation_retry_count" field. |
creationTime | string | no | CreationTime holds the value of the "creation_time" field. |
direction | CosellreferralDirection | no | |
dynamics365OpportunityId | string | no | Dynamics365OpportunityID holds the value of the "dynamics365_opportunity_id" field. |
errorMessages | array<string> | no | ErrorMessages holds the value of the "error_messages" field. |
externalCreationTime | string | no | ExternalCreationTime holds the value of the "external_creation_time" field. |
externalId | string | no | ExternalID holds the value of the "external_id" field. |
externalLastUpdateTime | string | no | ExternalLastUpdateTime holds the value of the "external_last_update_time" field. |
hubspotDealId | string | no | HubspotDealID holds the value of the "hubspot_deal_id" field. |
id | string | no | ID of the ent. |
info | ReferralInfo | no | |
lastUpdateTime | string | no | LastUpdateTime holds the value of the "last_update_time" field. |
metaInfo | ReferralMetaInfo | no | |
missingFields | array<string> | no | MissingFields lists the partner-answerable facts the draft still lacks. Empty means nothing is left to ask the partner; the ISV may still have to supply confirm-time fields (deal type, delivery model, collaboration context, and revenue-share terms when commissions are enabled) in the console, so empty is not a promise that ConfirmDealRegistrationDraft will succeed. |
name | string | no | Name holds the value of the "name" field. |
organizationId | string | no | OrganizationID holds the value of the "organization_id" field. |
partner | CosellreferralPartner | no | |
partnerId | string | no | PartnerID holds the value of the "partner_id" field. |
partnerStatus | string | no | PartnerStatus holds the value of the "partner_status" field. |
salesforceAccountId | string | no | SalesforceAccountID holds the value of the "salesforce_account_id" field. |
salesforceOpportunityId | string | no | SalesforceOpportunityID holds the value of the "salesforce_opportunity_id" field. |
salesforceReferralId | string | no | SalesforceReferralID holds the value of the "salesforce_referral_id" field. |
sourceLeadId | string | no | SourceLeadID holds the value of the "source_lead_id" field. |
stage | string | no | Stage holds the value of the "stage" field. |
status | string | no | Status holds the value of the "status" field. |
ApprovalInfo fields:
| Field | Type | Required | Description |
|---|---|---|---|
approvalStatus | ApprovalStatus | no | |
decisionDate | string | no | DecisionDate is when the final approval/decline happened (nil when pending) Latest DecisionDate |
message | string | no | Message is the reason or explanation provided when the approval status is set to Declined or Action Required. It always stores the latest message for the current status transition. Historical messages are stored in notification events. |
requestDate | string | no | Latest RequestDate |
ReferralInfo fields:
| Field | Type | Required | Description |
|---|---|---|---|
aceEngagementInvitation | EngagementInvitation | no | |
aceOpportunity | AceOpportunity | no | |
aceOpportunityV2 | AceOpportunityV2 | no | |
aceOutboundEngagementInvitations | array<EngagementInvitation> | no | AceOutboundEngagementInvitations stores all outbound engagement invitations sent to partners. |
createMicrosoftReferralRequest | CreateReferralRequest | no | |
gcpOpportunity | GCPOpportunity | no | |
gcpOpportunityV2 | Opportunity | no | |
microsoftReferralSet | MicrosoftReferralSet | no | |
sugerOpportunity | SugerOpportunity | no |
ReferralMetaInfo fields:
| Field | Type | Required | Description |
|---|---|---|---|
archivedAt | string | no | ArchivedAt is the time when the referral was deleted. It is set to indicate that the referral has been archived; otherwise, the referral is considered active. |
autoAcceptedAt | string | no | AutoAcceptedAt is when Fours' AWS/Azure auto-accept sent the accept for this inbound referral: ACE took the accept and it was saved (AWS; AWS completes it asynchronously), or the outbound sync carrying it to Microsoft started (Azure). It records that the accept was sent, not that the partner has confirmed it. Written only by the auto-accept path, never from a request body; the first accept wins and nothing clears it on purpose. Nil means the referral was not auto-accepted — with one known gap: other metaInfo writers save the whole struct they read, so one that read the row just before this was written and saves just after drops it. |
autoConnectedManagedAccount | boolean | no | AutoConnectedManagedAccount is true when Fours' Auto Share auto-picked the Microsoft Managed Account for this referral's customer (vs CRM-mapped or user-selected). Azure-only. Set at submission time and never cleared. |
awsInvitePartnerRequests | array<SendEngagementInvitationRequest> | no | AwsInvitePartnerRequests stores the list of partners to invite when creating this referral. Each entry is passed to SendEngagementInvitation after engagement creation completes. This field is never cleared — it serves as a permanent record of invitation intent and allows retry via the standalone SendEngagementInvitation endpoint. Max 9 partners per opportunity (AWS API limit). |
azureDealRegIsEligible | boolean | no | AzureDealRegIsEligible indicates whether the referral is eligible for Azure deal registration. This is pre-computed by a daily cron workflow and cached here. |
createdByEmail | string | no | The email address of the user who created the referral. This field is immutable after creation. Especially useful for referrals created from Salesforce/HubSpot integrations where the creator may not have a Fours account yet. |
createdBySource | CreatedBySource | no | |
creationFailureMessage | string | no | |
creationStatus | string | no | |
crmOpportunityId | string | no | |
crmPartner | string | no | |
hubspotDealId | string | no | |
isTesting | boolean | no | IsTesting is a flag to indicate if the referral is for testing purpose. E.g., customer doing a POC without a real ACE connection. |
lastSyncMessage | string | no | |
lastSyncStatus | string | no | |
lastSyncTime | string | no | |
partnerOps | CosellAgentReferralState | no | |
preCheckCrossCloudConflict | PreCheckCrossCloudConflictInfo | no | |
predictedQualityScore | PredictedQualityScoreSnapshot | no | |
salesforceReferralId | string | no | |
syncDisabled | boolean | no | |
updateFailureMessage | string | no | |
updateStatus | string | no |
EngagementInvitation fields:
| Field | Type | Required | Description |
|---|---|---|---|
Arn | string | no | |
Catalog | string | no | |
EngagementDescription | string | no | |
EngagementId | string | no | |
EngagementTitle | string | no | |
ExistingMembers | array<EngagementMember> | no | |
ExpirationDate | string | no | |
Id | string | no | |
InvitationDate | string | no | |
InvitationMessage | string | no | |
Payload | EngagementInvitationPayload | no | |
PayloadType | string | no | |
Receiver | Receiver | no | |
RejectionReason | string | no | |
SenderAwsAccountId | string | no | |
SenderCompanyName | string | no | |
Status | string | no |
AceOpportunity fields:
| Field | Type | Required | Description |
|---|---|---|---|
IsOppFromMarketingActivity | string | no | Note that the JSON field's first letter must be uppercase. |
aWSAccountOwnerEmail | string | no | |
aWSAccountOwnerName | string | no | |
aWSCloseDate | string | no | |
aWSClosedLostReason | string | no | |
aWSISVSuccessManagerEmail | string | no | |
aWSISVSuccessManagerName | string | no | |
aWSPartnerSuccessManagerEmail | string | no | |
aWSPartnerSuccessManagerName | string | no | |
aWSSalesRepEmail | string | no | |
aWSSalesRepName | string | no | |
aWSStage | string | no | |
acceptBy | string | no | |
additionalComments | string | no | |
apnCrmLeadUniqueIdentifier | string | no | |
apnCrmUniqueIdentifier | string | no | |
apnReviewerComments | string | no | |
awsAccountId | string | no | |
awsProducts | array<string> | no | |
awsSFCampaignName | string | no | |
backwardsCompatibilityChanges | string | no | |
campaignName | string | no | |
city | string | no | |
closedLostReason | string | no | |
competitiveTracking | string | no | |
competitiveTrackingOther | string | no | |
contractEndDate | string | no | |
contractStartDate | string | no | |
cosellConvertReason | string | no | |
country | string | no | |
createdBy | string | no | |
createdDate | string | no | |
customerCompanyName | string | no | |
customerDuns | string | no | |
customerEmail | string | no | |
customerFirstName | string | no | |
customerLastName | string | no | |
customerPhone | string | no | |
customerSoftwareValue | number | no | |
customerSoftwareValueCurrency | string | no | |
customerTitle | string | no | |
customerWebsite | string | no | |
deliveryModel | string | no | |
doesOppBelongToNatSec | string | no | |
engagementInvitationArn | string | no | For Partner Central API inbound opportunity |
engagementScore | string | no | |
expectedMonthlyAwsRevenue | integer | no | |
industry | string | no | |
industryOther | string | no | |
isMarketingDevelopmentFunded | string | no | |
lastModifiedBy | string | no | |
lastModifiedDate | string | no | |
marketingActivityChannel | string | no | |
marketingActivityUsecase | string | no | |
nextStep | string | no | |
nextStepHistory | string | no | |
offers | array<string> | no | |
opportunityOwnerEmail | string | no | |
opportunityOwnerName | string | no | |
opportunityOwnership | string | no | |
opportunityType | string | no | |
otherSolutionOffered | string | no | |
parentOppId | string | no | When Opportunity Type is set to "Flat Renewal". Mandatory when partner needs to send updates to existing opportunities. |
partnerAcceptanceDate | string | no | |
partnerAcceptanceStatus | string | no | |
partnerCrmUniqueIdentifier | string | no | |
partnerDeveloperManager | string | no | |
partnerDeveloperManagerEmail | string | no | |
partnerPrimaryNeedFromAws | string | no | |
partnerProjectTitle | string | no | |
postalCode | string | no | |
primaryContactEmail | string | no | |
primaryContactFirstName | string | no | |
primaryContactLastName | string | no | |
primaryContactPhone | string | no | |
primaryContactTitle | string | no | |
procurementType | string | no | |
projectDescription | string | no | |
recommendedNextBestActions | string | no | |
rejectionReason | string | no | |
salesActivities | string | no | |
solutionOffered | array<string> | no | |
stage | string | no | |
state | string | no | |
status | string | no | |
streetAddress | string | no | |
sugerRequestId | string | no | Fours-internal field to store the request id. |
targetCloseDate | string | no | |
useCase | string | no | |
wWPSPDM | string | no | |
wWPSPDMEmail | string | no |
AceOpportunityV2 fields:
| Field | Type | Required | Description |
|---|---|---|---|
AWSLifeCycle | LifeCycle | no | |
AWSOpportunityTeam | array<AceContact> | no | AWSOpportunityTeam details the AWS opportunity team, including members involved. This information helps partners know who from AWS is engaged and what their role is. |
Arn | string | no | Arn, The Amazon Resource Name (ARN) that uniquely identifies the opportunity. Type: String Pattern: ^arn:.*$ |
Catalog | string | no | Specifies the catalog associated with the request. This field takes a string value from a predefined list: AWS or Sandbox. The catalog determines which environment the opportunity is created in. Use AWS to create opportunities in the AWS catalog, and Sandbox to test in a secure and isolated environment. Type: String Pattern: ^[a-zA-Z]+$ Required: Yes |
CosellMotion | string | no | CosellMotion classifies how AWS is engaging with this opportunity. Operational classification produced by AWS's routing model — not an analytical insight. Populated asynchronously after submission; empty string until classified. Values are extensible — new motions may be added without notice. Type: String Known Values: AWS Field-engaged | Agent-engaged | Partner-led |
CreatedDate | string | no | DateTime when the Opportunity was last created. |
Customer | Customer | no | |
Id | string | no | ID Read-only, system generated Opportunity unique identifier. Type: String Pattern: ^O[0-9]{1,19}$ |
Insights | Insights | no | |
InvolvementType | string | no | InvolvementType specifies the type of involvement AWS has in the opportunity, such as direct cosell or advisory support. This field helps partners understand the role AWS plays in advancing the opportunity. Type: String Valid Values: For Visibility Only | Co-Sell |
InvolvementTypeChangeReason | string | no | InvolvementTypeChangeReason provides a reason for any changes in the involvement type of AWS in the opportunity. This field is used to track why the level of AWS engagement has changed from For Visibility Only to Co-sell offering transparency into the partnership dynamics. Type: String Valid Values: Expansion Opportunity | Change in Deal Information | Customer Requested | Technical Complexity | Risk Mitigation |
LastModifiedDate | string | no | DateTime when the opportunity was last modified. |
LifeCycle | LifeCycle | no | |
Marketing | Marketing | no | |
NationalSecurity | string | no | Indicates whether the Opportunity pertains to a national security project. This field must be set to true only when the customer's industry is Government. Additional privacy and security measures apply during the review and management process for opportunities marked as NationalSecurity. Type: String Valid Values: Yes | No Required: No |
OpportunityTeam | array<AceContact> | no | Represents the internal team handling the opportunity. Specify the members involved in collaborating on this opportunity within the partner's organization. Type: Array of Contact objects Array Members: Minimum number of 0 items. Maximum number of 1 item. Required: No |
OpportunityType | string | no | Specifies the opportunity type as a renewal, new, or expansion. Opportunity types: New opportunity: Represents a new business opportunity with a potential customer that's not previously engaged with your solutions or services. Renewal opportunity: Represents an opportunity to renew an existing contract or subscription with a current customer, ensuring continuity of service. Expansion opportunity: Represents an opportunity to expand the scope of an existing contract or subscription, either by adding new services or increasing the volume of existing services for a current customer. Type: String Valid Values: Net New Business | Flat Renewal | Expansion Required: No |
Origin | string | no | Specifies the origin of the opportunity, indicating if it was sourced from AWS or the partner. For all opportunities created with Catalog: AWS, this field must only be Partner Referral. However, when using Catalog: Sandbox, you can set this field to AWS Referral to simulate AWS referral creation. This allows AWS-originated flows testing in the sandbox catalog. Type: String Valid Values: AWS Referral | Partner Referral Required: No |
PartnerOpportunityIdentifier | string | no | Specifies the opportunity's unique identifier in the partner's CRM system. This value is essential to track and reconcile because it's included in the outbound payload sent back to the partner. This field allows partners to link an opportunity to their CRM, to ensure seamless integration and accurate synchronization between the Partner Central API and the partner's internal systems. Type: String Length Constraints: Minimum length of 0. Maximum length of 64. Required: No |
PrimaryNeedsFromAws | array<string> | no | Identifies the type of support the partner needs from AWS. Valid values: Co-Sell - Architectural Validation: Confirmation from AWS that the partner's proposed solution architecture is aligned with AWS best practices and poses minimal architectural risks. Co-Sell - Business Presentation: Request AWS seller's participation in a joint customer presentation. Co-Sell - Competitive Information: Access to AWS competitive resources and support for the partner's proposed solution. Co-Sell - Pricing Assistance: Connect with an AWS seller for support situations where a partner may be receiving an upfront discount on a service (for example: EDP deals). Co-Sell - Technical Consultation: Connect with an AWS Solutions Architect to address the partner's questions about the proposed solution. Co-Sell - Total Cost of Ownership Evaluation: Assistance with quoting different cost savings of proposed solutions on AWS versus on-premises or a traditional hosting environment. Co-Sell - Deal Support: Request AWS seller's support to progress the opportunity (for example: joint customer call, strategic positioning). Co-Sell - Support for Public Tender / RFx: Opportunity related to the public sector where the partner needs AWS RFx support. Do Not Need Support from AWS Sales Rep: Indicates that a partner doesn't need support from an AWS sales representative, and the partner solely manages the opportunity. It's possible to request co-selling support on these opportunities at any stage during their lifecycle. Also known as, for-visibility-only (FVO) opportunity. Type: Array of strings Valid 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 Required: No |
Project | Project | no | |
RelatedEntityIdentifiers | RelatedEntityIdentifiers | no | |
SoftwareRevenue | SoftwareRevenue | no | |
Visibility | string | no | Visibility defines the visibility level for the AWS Opportunity. Use Full visibility for most cases, while Limited visibility is reserved for special programs or sensitive opportunities. Type: String Valid Values: Full | Limited |
CreateReferralRequest fields:
| Field | Type | Required | Description |
|---|---|---|---|
attributes | object | no | |
callToAction | string | no | |
campaignId | string | no | |
consent | MicrosoftPartnerReferralConsent | no | |
contract | MicrosoftPartnerReferralContract | no | |
customerProfile | MicrosoftPartnerReferralProfile | no | |
dealType | DealType | no | |
details | MicrosoftPartnerReferralDetail | no | |
engagementId | string | no | |
expirationDateTime | string | no | |
externalReferenceId | string | no | |
invitations | array<InvitationToPartner> | no | Additional properties from Fours, used to generate connected referrals Details and Team are mandatory for non-msft invitations |
inviteContext | MicrosoftPartnerReferralInviteContext | no | |
mpnId | string | no | |
name | string | no | |
organizationId | string | no | |
organizationName | string | no | |
qualification | MicrosoftPartnerReferralQualification | no | |
status | MicrosoftPartnerReferralStatus | no | |
statusReason | string | no | |
substatus | MicrosoftPartnerReferralSubStatus | no | |
target | array<MicrosoftPartnerReferralTarget> | no | |
team | array<MicrosoftPartnerReferralPerson> | no | |
type | MicrosoftPartnerReferralType | no |
GCPOpportunity fields:
| Field | Type | Required | Description |
|---|---|---|---|
approvedDate | string | no | |
authority | string | no | |
budget | string | no | |
campaignCode | string | no | |
closeDate | string | no | |
closeDatePushCount | integer | no | |
confidential | boolean | no | |
contractExpiryDate | string | no | |
contractLengthMonths | integer | no | |
contractVehicle | string | no | |
customerAddressAdministrativeArea | string | no | |
customerAddressLanguageCode | string | no | |
customerAddressLines | array<string> | no | |
customerAddressLocality | string | no | |
customerAddressOrganization | string | no | |
customerAddressPostalCode | string | no | |
customerAddressRecipients | array<string> | no | |
customerAddressRegionCode | string | no | |
customerAddressRevision | integer | no | |
customerAddressSortingCode | string | no | |
customerAddressSublocality | string | no | |
customerContactEmail | string | no | |
customerContactFamilyName | string | no | |
customerContactGivenName | string | no | |
customerContactPhone | object | no | |
customerContactRequested | boolean | no | |
customerContacts | array<object> | no | |
customerDisplayName | string | no | |
customerDomain | string | no | |
customerEmployeeCount | integer | no | |
customerIndustry | string | no | |
customerOrganizationName | string | no | |
customerRegion | string | no | |
dealNumber | string | no | |
dealSize | object | no | |
decisionPhase | string | no | |
deliveryModel | string | no | |
distributor | string | no | |
estimatedCloseDate | string | no | |
extensionsCount | integer | no | |
gcpCreatedDate | string | no | |
gcpCreatorEmail | string | no | |
gcpName | string | no | |
gcpOwner | string | no | |
gcpOwnerEmail | string | no | |
gcpProjectNumbers | array<string> | no | |
gcpSource | string | no | |
gcpStage | string | no | |
gcpState | string | no | |
gcpStateDescription | string | no | |
gcpUpdatedDate | string | no | |
gcpWatermark | number | no | |
id | string | no | |
incentiveEligibility | boolean | no | |
incentiveType | string | no | |
indirectPartnerEntity | string | no | |
isvSolutionConnectDeal | boolean | no | |
legalLanguageAccepted | boolean | no | |
lostMainReason | string | no | |
lostReason | string | no | |
lostRejectedReasonDetails | string | no | |
msspDeal | boolean | no | |
need | string | no | |
operationType | string | no | |
opportunityAmount | object | no | |
opportunityDescription | string | no | |
opportunityDisplayName | string | no | |
opportunityLines | array<object> | no | |
opportunityTeamMembers | array<object> | no | |
opportunityType | string | no | |
partnerEntity | string | no | |
partnerReadyToClose | string | no | |
prmSiteDetails | string | no | |
productCategory | array<string> | no | |
productFamily | array<string> | no | |
publicSector | boolean | no | |
rebateExpirationDate | string | no | |
rebateExtensions | array<object> | no | |
subbillingAccountId | string | no | |
submittedDate | string | no | |
supportLevel | string | no | |
timeline | string | no | |
winLossAdditionalContext | string | no | |
winLossProducts | array<string> | no | |
winMainReason | string | no | |
wonReason | string | no |
Opportunity fields:
| Field | Type | Required | Description |
|---|---|---|---|
createTime | string | no | Output only. CreateTime is the time when the Opportunity was created. |
creationDate | GcpCosellDate | no | |
creatorEmail | string | no | Output only. CreatorEmail is the email of the user who created the Opportunity. |
customerContacts | array<CustomerContact> | no | List of Customer contacts for the Opportunity, present after approval. Present only after the Opportunity is approved. Unset otherwise. Cannot be edited. Output only. |
customerDisplayName | string | no | Output only. CustomerDisplayName is the display name of the customer associated with the Opportunity. |
customerInfo | CustomerInfo | no | |
isvSolutionConnectInfo | IsvSolutionConnectInfo | no | |
name | string | no | Name is the identifier for the Opportunity in the format: opportunities/{opportunity_id}. |
opportunityInfo | GcpOpportunityInfo | no | |
opportunityLines | array<OpportunityLine> | no | Information about the products added to the Opportunity Present only after the Opportunity is approved. Unset otherwise. Cannot be edited. Output only. |
opportunityTeamMembers | array<OpportunityTeamMember> | no | Information on the Partner users with access to the Opportunity Present only after the Opportunity is approved. Unset otherwise. Cannot be edited. Output only. |
opportunityType | string | no | Optional. Indicates if the opportunity is a Regular/Independent Software Vendor/2-tier deal. If not specified, it will be treated as a Regular. Can't be edited after the Opportunity is Accepted. |
owner | string | no | Output only. Owner is the name of the Google FSR (Field Sales Representative) who owns the Opportunity. |
ownerEmail | string | no | Output only. OwnerEmail is the email of the Google FSR who owns the Opportunity. |
partnerInfo | PartnerInfo | no | |
qualificationInfo | QualificationInfo | no | |
rebateExtensions | array<RebateExtension> | no | Information about rebate extensions requested on the Opportunity. Present only after the Opportunity is approved. Unset otherwise. Cannot be edited. Output only. |
salesCycle | SalesCycle | no | |
source | string | no | Output only. Source indicates if the Opportunity was created by Google or a Partner. |
stage | GCPOppoStage | no | |
state | GCPOppoState | no | |
stateDescription | string | no | Output only. StateDescription contains the reason if the Opportunity was not accepted. |
updateTime | string | no | Output only. CreateTime is the time when the Opportunity was updated. |
winLossInfo | WinLossInfo | no |
MicrosoftReferralSet fields:
| Field | Type | Required | Description |
|---|---|---|---|
connected | array<MicrosoftPartnerReferral> | no | |
self | MicrosoftPartnerReferral | no |
SugerOpportunity fields:
| Field | Type | Required | Description |
|---|---|---|---|
acceptedDateTime | string | no | AcceptedDateTime is when the partner accepted. |
attributionRole | SugerAttributionRole | no | |
closedLostReason | string | no | ClosedLostReason is set when the ISV closes the deal as lost. |
collaborationContext | SugerCollaborationContext | no | |
commissionLifecycle | CommissionLifecycle | no | |
commissionPreview | SugerCommissionPreview | no | |
commissionsDisabled | boolean | no | Multi-partner attribution: the create API is single-partner (top-level partnerId + attributionRole + revenueShareTerms describe THE partner); additional partners join an existing engagement through the InviteCosellPartners endpoint (SugerCoSellPartnerInput body), each getting its own reseller copy. The per-engagement partner summary for the list table is response-level (ListCosellReferralsResponse.EngagementPartners, keyed by referral id) — never a field on this persisted struct. CommissionsDisabled snapshots, at create time, that the PRM Cosell Commissions feature was NOT in play for this deal — stamped true only when either party lacked the feature (the bilateral both-on check failed). Mirrored identically to both copies and immutable after create, so a later org-config flip never rewrites an in-flight deal. The zero value (false) is the safe default: legacy rows and any un-stamped row read as commissions active. Read via CommissionsActive; never the raw negative. When true, the commission surface (revenue-share terms, preview, lifecycle) is absent for the deal on both sides (PRM_COSELL_COMMISSIONS). |
conversations | array<SugerCosellConversation> | no | Conversations is the in-platform conversation thread surfaced on the co-sell detail page's Activity tab ( Component 5). Each entry is one message from a participant. Email replies are NOT stored here — those are queried separately via the auditing / notification-event APIs. This array is for in-platform conversation only. READ-ONLY on the write path: clients receive this on GET responses but MUST NOT modify it via PATCH. Direct changes via this field are rejected by the validator (CONVERSATION_DIRECT_EDIT). To add a message, send `newConversations` instead — the server stamps actor identity and appends. SHARED CROSS-COPY: like CommissionLifecycle, both copies of the engagement carry the same Conversations. The engagement-sync workflow propagates additions to the counterpart row so seller and partner always see the same thread. |
createdDateTime | string | no | CreatedDateTime is when this referral was created. |
customerInfo | SugerCustomerInfo | no | |
dealDetails | SugerDealDetails | no | |
dealRegistrationDraft | SugerDealRegistrationDraft | no | |
dealRole | SugerDealRole | no | |
declineReason | string | no | DeclineReason is set when the partner declines. |
direction | string | no | Direction is "Outbound" (ISV) or "Inbound" (partner). |
engagementId | string | no | EngagementID is a shared UUID linking the ISV's and partner's referral rows. |
expirationDateTime | string | no | ExpirationDateTime is when the co-sell expires if not accepted. |
externalReferenceId | string | no | ExternalReferenceID is the CRM opportunity ID or any external reference ID. |
matchedBuyerId | string | no | MatchedBuyerID is the identity.buyer record auto-matched to this co-sell's end customer by domain (CustomerInfo.Website → buyer info.companyInfo.emailDomain), set on the ISV's (outbound) copy. Drives the §3 CPPO↔co-sell linking and the "End Customer ✓ Matched" surface. Empty when no unambiguous buyer matched ( §2). |
newConversations | array<SugerCosellConversation> | no | NewConversations is the REQUEST-ONLY append channel for the in- platform conversation thread. Clients submit one or more new messages here on PATCH; the server stamps ID / actor identity / timestamp / source server-side, validates Body is non-empty, appends to Conversations, and clears NewConversations before persisting (the persisted shape never carries this field at the parent level). |
nextSteps | string | no | NextSteps is a per-party, free-form field describing the immediate next actions for this co-sell. Either party can edit their own copy; never synced across copies. |
onBehalfRegistration | SugerOnBehalfRegistration | no | |
partnerActionGrants | object | no | PartnerActionGrants records the one-click credentials issued to partners who DO have a console login — accept, close won, close lost, approve commission change. Same credential type and the same storage contract as the map above: hashes only, cleared on use, so what remains is an audit record rather than anything that can act. The shape is the whole difference between the two, and it is the semantic difference: a token is ONE credential per action, a grant is one per RECIPIENT per action, because the email that carries a grant is addressed to one person. Sharing a credential across a deal team would record every click under whoever the first address happened to be. A second field rather than a wider first one: widening would turn a JSON object into an array on every on-behalf row already in the database. Unlike PartnerActionTokens these authorize action on THIS row, and they do not stand alone: consuming one resolves IssuedToEmail to a Fours user and requires that user to hold an editing role in this row's organization. The credential says which action, on which row, offered to whom; the membership check says whether that person may perform it. Server-owned: create drops it from the request body and the update merge never copies it from a patch, so a client value can never be persisted — a stale echo from the console is simply ignored. |
partnerActionTokens | object | no | PartnerActionTokens records the one-click partner actions BEYOND registration — confirming Close Won and confirming payment receipt. It holds only the SHA-256 HASH of each credential, never the credential itself: the opaque token exists solely in the email sent to the partner, and is verified by hashing what the partner presents and comparing. The hash is cleared on use, so the entry that remains is an audit record (who it was issued to, when it expired, when it was consumed) rather than anything that can act. Reading this field grants no ability to perform the action. This is also why the public API schema description must not call these "credentials" — see SugerPartnerActionToken. Present only on on-behalf co-sells: an ordinary partner has a console login and gets a deep link instead, so no unauthenticated mutation credential is ever minted for them. A map rather than more fields on SugerOnBehalfConfirmation because that struct holds exactly ONE TokenHash, which cannot represent three actions outstanding at once. Keying by action is also what makes the credential action-scoped: a Close Won link cannot confirm a payment, because the dispatcher only applies the action whose hash matched. Server-owned, like OnBehalfRegistration — see rejectOnBehalfRegistrationEdit. |
partnerIds | array<string> | no | PartnerIds lists the Partnership ids, in this copy's own organization, of every counterparty partner in the engagement. On a seller's copy that is one id per participating partner, including partners invited after the co-sell was created; on a partner's copy it is the single partnership with the seller. Server-owned: values supplied by a client are ignored. |
partnerTeam | array<SugerTeamMember> | no | PartnerTeam is the people at the partner the co-sell was shared to, the partner champion first (as on SugerCoSellPartnerInput). Stored only on the partner's own copy, where it is also seated as Team. Server-owned after create: an update cannot change it. Empty on co-sells shared before the choice existed. |
publicRegistration | SugerPublicRegistration | no | |
recipientMode | SugerPartnerRecipientMode | no | |
revenueShareTerms | SugerRevenueShareTerms | no | |
showDealValue | boolean | no | ShowDealValue controls whether THIS copy's owner sees the full deal value. Per-partner and Seller-set (create/invite ShowDealValueToPartner, or the Seller's accept-time choice on reseller-initiated deals), it lives on each reseller (partner) copy like AttributionRole — a sharing control, NOT a commission term, so it exists independently of RevenueShareTerms and survives commissions-disabled deals. Never engagement-synced; server-set only (the generic referral PATCH ignores it). Pointer so nil ("not set" — default visible) is distinct from an explicit false ("hidden"); nil-or-true means visible. The read-path redaction (RedactHiddenDealValue / RedactHiddenDealValueForReferrals) clears the numeric deal-value fields on a Referrer copy when this is false. |
stage | string | no | Stage is the deal lifecycle stage. The vocabulary is SugerCosellStage — Title Case with spaces ("Pending", "Active", "In Discovery", "Proposal Sent", "Negotiating", "On Hold", "Won", "Lost"), NOT lowercase snake_case. Bulk imports can write anything, so readers must treat an unrecognised value as unknown rather than assume the enum. |
status | string | no | Status is the per-copy sharing state. The vocabulary is SugerReferralStatus — UPPER_CASE ("DRAFT", "PENDING_ACCEPTANCE", "ACTIVE", "REJECTED", "CLOSED_WON",...), NOT lowercase. Readers should compare against the typed constants. |
team | array<SugerTeamMember> | no | Team is this copy's own org team members. Each copy holds only its own members; a party sees counterpart teams via the engagement view (EngagementPartner.Team). |
type | string | no | Type is the opportunity type: "New Business", "Renewal", "Expansion", "Add On". |
updatedDateTime | string | no | UpdatedDateTime is when this referral was last updated. |
400 — Bad request error
Content-Type: application/json · Schema: ErrorResponse
ErrorResponse fields:
| Field | Type | Required | Description |
|---|---|---|---|
code | ErrorCode | no | |
info | object | no | |
message | string | no |
404 — Not found
Content-Type: application/json · Schema: ErrorResponse
ErrorResponse fields:
| Field | Type | Required | Description |
|---|---|---|---|
code | ErrorCode | no | |
info | object | no | |
message | string | no |
500 — Internal server error
Content-Type: application/json · Schema: ErrorResponse
ErrorResponse fields:
| Field | Type | Required | Description |
|---|---|---|---|
code | ErrorCode | no | |
info | object | no | |
message | string | no |
Example
The request bodies are this operation's documented examples; the
response and error bodies are generated from its schema. Substitute your
own ids, and set SUGER_TOKEN to a bearer token from the
OAuth client-credentials exchange.
Request
Adds what the ISV supplies before confirming: the opportunity type, deal role, delivery model and collaboration context, plus the customer's country and target close date the draft was missing. `customerInfo` and `dealDetails` replace the stored objects whole, so send every field you want to keep. Read the draft with GetDealRegistrationDraft first; its `missingFields` lists what is still needed.
curl -X PATCH 'https://api.suger.cloud/org/{orgId}/cosell/dealRegistrationDraft/{draftId}' \
-H "Authorization: Bearer $SUGER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"type": "New Business",
"dealRole": "Seller",
"customerInfo": {
"companyName": "Contoso Freight",
"website": "contosofreight.example",
"industry": "Logistics",
"country": "US"
},
"dealDetails": {
"name": "Contoso Freight — Northwind Partners",
"dealValueAmount": 120000,
"dealValueCurrency": "USD",
"targetCloseDate": "2027-06-30T00:00:00Z",
"customerBusinessProblem": "Dispatch runs on spreadsheets per depot, so they can't see cross-depot capacity and miss about 8% of same-day loads.",
"deliveryModel": [
"Cloud Marketplace"
]
},
"collaborationContext": {
"partnerNeeds": [
"Active Co-Selling"
]
}
}' Response — 200
{
"approvalInfo": {
"approvalStatus": "Submitted",
"decisionDate": "2026-01-31T12:00:00Z",
"message": "string",
"requestDate": "2026-01-31T12:00:00Z"
},
"contactIDs": [
"01H0000000000000000000"
],
"creationRetryCount": 1,
"creationTime": "2026-01-31T12:00:00Z",
"direction": "INBOUND",
"dynamics365OpportunityId": "01H0000000000000000000",
"errorMessages": [
"string"
],
"externalCreationTime": "2026-01-31T12:00:00Z",
"externalId": "01H0000000000000000000",
"externalLastUpdateTime": "2026-01-31T12:00:00Z",
"hubspotDealId": "01H0000000000000000000",
"id": "01H0000000000000000000"
} Error — 400
{
"code": "InternalServerError",
"message": "string"
} View as Markdown · API reference overview
Spotted something wrong or out of date on this page? Tell us and we'll correct it.