# Propose an AWS referral update for a person to approve

`PUT https://api.suger.cloud/org/{orgId}/cosell/referral/{referralId}/agentProposal`

Stage a proposed change to an AWS co-sell referral, or record an outcome that needs a person, without changing the referral. The proposal is stored on the referral's metaInfo.partnerOps and shown to the seller on the referral page, where a person approves or rejects it. Use this in Review mode, or when an AWS rep is working the deal: send statusCode UPDATE_PROPOSED with the changed ACE opportunity fields in changes, shaped like the info.aceOpportunityV2 part of a merge=true UpdateCosellReferral body. When a fact needed for the change is missing, send NEEDS_NEXT_STEP, NEEDS_CONTACT, NEEDS_ADDRESS or NEEDS_OTHER with a reason and no changes; DUPLICATE_FOUND, BLOCKED_SENSITIVE and BLOCKED_PAYLOAD record those outcomes the same way. A new proposal replaces one already waiting.

A proposed change must meet the rules an AI agent update meets: the referral is ACTIVE, IN_REVIEW, ACTION_REQUIRED or UPDATE_FAILED and stays open, no field that has a value is blanked, and the new text carries no other cloud's name, email address, phone number, pricing or discount term. A refused proposal returns 400 and stores nothing.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgId` | path | string | yes | Organization ID |
| `referralId` | path | string | yes | Referral ID |

## Request Body

Required.

Content-Type: `application/json` · Schema: `ProposeCosellReferralUpdateRequest`

**`ProposeCosellReferralUpdateRequest`** fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `changes` | object | no | Changes are the ACE opportunity fields to change (merge=true shape, under info.aceOpportunityV2). Required for UPDATE_PROPOSED, not allowed otherwise. |
| `predictedScore` | integer | no | PredictedScore is the predicted AWS quality score after the change, when checked. |
| `reason` | string | no | Reason is the specifics, shown next to the outcome. Required unless StatusCode is UPDATE_PROPOSED. |
| `skillId` | string | yes | SkillID is the skill that made the proposal. |
| `sources` | array<string> | no | Sources name where each fact came from. |
| `statusCode` | CosellAgentStatusCode | yes |  |

## Responses

### 200 — The referral's agent state after the proposal

Content-Type: `application/json` · Schema: `CosellAgentReferralState`

**`CosellAgentReferralState`** fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `approvedAt` | string | no |  |
| `approvedBy` | string | no | ApprovedBy and ApprovedAt record the person who approved the latest proposal. |
| `awsScoreBefore` | integer | no | AwsScoreBefore is AWS's quality score just before the agent's latest update, and AwsScoreBeforeAt when it was read, so the improvement can be shown. |
| `awsScoreBeforeAt` | string | no |  |
| `lastRejection` | CosellAgentRejection | no |  |
| `proposal` | CosellAgentProposal | no |  |
| `reason` | string | no | Reason is the specifics behind StatusCode, e.g. "No dated next step in any source". |
| `skillId` | string | no | SkillID is the skill that produced the latest outcome. |
| `statusCode` | CosellAgentStatusCode | no |  |
| `updatedAt` | string | no | UpdatedAt is when this state last changed. |

**`CosellAgentRejection`** fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `at` | string | yes |  |
| `by` | string | no |  |
| `reason` | string | no |  |

**`CosellAgentProposal`** fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `changes` | object | yes | Changes are the ACE opportunity fields to change, shaped like the info.aceOpportunityV2 part of a merge=true update body. |
| `predictedScore` | integer | no | PredictedScore is the predicted AWS quality score after the change, when checked. |
| `proposedAt` | string | yes |  |
| `sources` | array<string> | no | Sources name where each fact came from (e.g. "Gong call on Sep 19"). |

### 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 — Referral 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

_Generated from this operation's schema. Values are placeholders — substitute your own ids, and set `SUGER_TOKEN` to a bearer token from the [OAuth client-credentials exchange](https://doc.fours.com/settings/oauth-app/)._

### Request

```bash
curl -X PUT 'https://api.suger.cloud/org/{orgId}/cosell/referral/{referralId}/agentProposal' \
  -H "Authorization: Bearer $SUGER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
  "skillId": "01H0000000000000000000",
  "statusCode": "UPDATE_PROPOSED"
}'
```

### Response — 200

```json
{
  "approvedAt": "2026-01-31T12:00:00Z",
  "approvedBy": "string",
  "awsScoreBefore": 1,
  "awsScoreBeforeAt": "2026-01-31T12:00:00Z",
  "lastRejection": {
    "at": "2026-01-31T12:00:00Z",
    "by": "string",
    "reason": "string"
  },
  "proposal": {
    "changes": {},
    "proposedAt": "2026-01-31T12:00:00Z",
    "predictedScore": 1,
    "sources": [
      "string"
    ]
  },
  "reason": "string",
  "skillId": "01H0000000000000000000",
  "statusCode": "UPDATE_PROPOSED",
  "updatedAt": "2026-01-31T12:00:00Z"
}
```

### Error — 400

```json
{
  "code": "InternalServerError",
  "message": "string"
}
```

---

API reference: https://doc.fours.com/api/
