> ## Documentation Index
> Fetch the complete documentation index at: https://docs.introw.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Nudge partners at scale via the API

> Post comments on partners, deals, tasks, submissions, and payouts from your own systems or an agent to nudge partners on the channels they already use.

> The reason partners go quiet is rarely that nobody knew. The signal is usually sitting in a query somewhere: this deal has not moved in three weeks, this certification lapsed, this order form was never signed. What is missing is a way to turn that signal into a nudge that reaches the partner without somebody writing the message.

The [Create a comment](/general/collaboration-overview) endpoint is that path. One call posts a comment on a partner, a deal, a task, a submission, or a payout, and the partner is notified through whichever channel they already use, email, Slack, or Microsoft Teams. Ten thousand partners is ten thousand calls, not ten thousand emails.

## What you'll achieve

Any system, script, or agent in your stack able to follow up with partners on the record itself, attributed to a real person on your team, notifying the partner where they already work, and with the reply landing back in the same thread.

## Before you start

<Steps>
  <Step title="Create a key with collaborate:write">
    Create an API key with the **Collaboration - Write** permission. See [Create and manage API keys](./create-and-manage-api-keys).
  </Step>

  <Step title="Decide who the comment is from">
    Comments are posted as a real person, not as "the system". Pick the team member the follow-up should appear to come from, usually the partner manager, and have their email ready.
  </Step>

  <Step title="Check your notification setup">
    A non-internal comment notifies the partner through the channels you have configured. Confirm those are the channels you want before you send at volume, see [Control who gets notified](/features/engagement/notifications/guides/control-who-gets-notified).
  </Step>
</Steps>

## Watch it

<Tabs>
  <Tab title="Video">
    <video controls playsInline preload="none" poster="https://assets.introw.io/docs/features/developer/api/guides/nudge-partners-at-scale-via-the-api/steps/01.png?v=1787341296" className="w-full rounded-xl" src="https://assets.introw.io/docs/features/developer/api/guides/nudge-partners-at-scale-via-the-api/video.webm?v=1787341296#t=2.5" />
  </Tab>

  <Tab title="Click through">
    <iframe className="w-full rounded-xl" style={{ width: "100%", aspectRatio: "16 / 11", border: 0, backgroundColor: "#FAFAFA" }} src="https://assets.introw.io/docs/features/developer/api/guides/nudge-partners-at-scale-via-the-api/walkthrough.html?v=1787341296" />
  </Tab>
</Tabs>

## Steps

### Post your first comment

<Steps>
  <Step title="Choose what to comment on">
    Every comment lands on a partner's timeline. What you additionally target decides which record it hangs off: a deal or ticket (`crmObjectId` + `crmObjectType`), a task (`taskId`), a form submission (`formSubmissionId`), a commission payout (`commissionPayoutId`), or the partner alone (`partnerId`). Pass at least one.
  </Step>

  <Step title="Send the call">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST "https://api.introw.io/api/v1/comments" \
      -H "x-api-key: $INTROW_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "comment": "This deal has been in **Proposal** for 21 days. Can you confirm the next step before Friday?",
        "authorEmail": "alex@vendor.example",
        "crmObjectId": "9840193344",
        "crmObjectType": "DEAL"
      }'
    ```

    You never pass a room or a portal id. The collaboration space is resolved from the target for you.
  </Step>

  <Step title="Use your CRM's own object names">
    `crmObjectType` is case-insensitive and takes whatever your CRM calls the object, so a Salesforce query can forward `Opportunity`, `Account`, or `Case` straight through and a HubSpot one can send `Deal`, `Company`, or `Ticket`. Introw resolves them to the same records, which means no type mapping in your script. Only custom objects need their exact API name, such as `Partner_Program__c`, because there is no standard equivalent to translate to.
  </Step>

  <Step title="Write it like a person would">
    `comment` accepts Markdown, and the formatting carries onto the partner portal timeline: `**bold**`, `*italic*`, `[links](url)`, blank-line paragraphs, and `-` or `1.` lists. HTML fragments are accepted too, so content you already generate can be forwarded as-is. A short, specific ask outperforms a templated reminder, and Markdown is what lets you write one.
  </Step>

  <Step title="Keep the threadId">
    The response returns a `threadId`. Pass it back as `threadId` on your next call and the follow-up joins the same thread instead of starting a new one, so a chase sequence reads as one conversation rather than four disconnected pings.
  </Step>
</Steps>

### Attribute it to the right partner

<Steps>
  <Step title="Use the id you already store">
    `partnerId` accepts the Introw partner id **or** the partner's CRM external id, so you can drive the loop straight off your CRM export without a mapping table.
  </Step>

  <Step title="Let a linked deal resolve the partner">
    When you target a deal or ticket that is already attributed to a partner, you can omit `partnerId` entirely. If the object is not attributed, the call returns `422 CRM_OBJECT_NOT_LINKED`, so pass `partnerId` explicitly for those.
  </Step>
</Steps>

### Keep a comment to your own team

<Steps>
  <Step title="Set isInternal">
    Send `"isInternal": true` and the comment stays on the record for your team only: hidden from every partner-facing surface and silent on notifications. Use it when your systems should annotate a record without talking to the partner, for example writing a risk score or a churn signal onto the deal.

    <Note>
      Internal comments require `authorEmail` to be one of **your** team members. A partner portal member can never author one. A comment on a payout the partner cannot see yet is kept internal automatically, whatever you send, so figures never leak ahead of the release.
    </Note>
  </Step>
</Steps>

## Patterns worth copying

<AccordionGroup>
  <Accordion title="Stalled-deal sweep on your own rules" icon="clock">
    Query the deals that broke your own definition of stalled (stage age, missing next step, no activity), then post one comment per deal targeting `crmObjectId`. Because the nudge lands on the deal, the partner opens the deal to reply, not an inbox. When your rule is simply "days in stage", the no-code [Sleeping deal notification](/features/engagement/notifications/guides/nudge-stalled-deals) already does this without any code, so reach for the API when the rule is yours.
  </Accordion>

  <Accordion title="Let an agent do the chasing" icon="robot">
    An agent that reviews your pipeline can decide who needs a nudge and post the comment itself, as a named team member, with the reply visible to that human in the same thread. The judgment is automated; the accountability is not. Pair it with [Introw's MCP server](/features/developer/mcp) when you want the agent reading Introw as well as writing to it.
  </Accordion>

  <Accordion title="Acknowledge intake instantly" icon="paper-plane">
    Right after [submitting a form via the API](/features/forms/sharing-submitting/guides/submit-a-form-via-the-api), pass the returned submission id as `formSubmissionId` and comment with what happens next and by when. Partners stop asking whether the registration arrived, and the SLA is on the record.
  </Accordion>

  <Accordion title="Close the loop from finance and provisioning" icon="money-bill-transfer">
    Have your billing system comment on the payout when it is scheduled (`commissionPayoutId`), and your provisioning system comment on the deal when the account goes live. The partner hears it from the record they already track, instead of a status email from a system they have never heard of.
  </Accordion>

  <Accordion title="Onboarding and enablement follow-up" icon="graduation-cap">
    Target `taskId` to chase an overdue onboarding step, or `partnerId` to reach a partner whose certification is about to lapse. Same call, different target.
  </Accordion>
</AccordionGroup>

## Verify it worked

Open the partner in [Partners](https://app.introw.io/partners) and check their timeline: the comment is there, attributed to the person in `authorEmail`, with your Markdown rendered. On the partner side it appears on the record in their portal and arrives on their configured channel. A comment sent with `isInternal` shows on your timeline marked internal and nowhere partner-facing.

## Limits & gotchas

<Warning>
  This is a nudge API, not a logging API: every non-internal comment reaches a person, so treat volume as outbound volume. Comments cap at 20,000 characters and the endpoint takes no attachments. `authorEmail` must resolve to a team member or to a portal member of that same partner, otherwise the call returns `422 AUTHOR_NOT_FOUND`.
</Warning>

## Troubleshooting

* **`403 Forbidden`** - the key lacks `collaborate:write`.
* **`422 AUTHOR_NOT_FOUND`** - the email is not a team member, nor a portal member of the partner being commented on.
* **`422 INTERNAL_AUTHOR_FORBIDDEN`** - `isInternal` was set for a partner-side author.
* **`422 CRM_OBJECT_NOT_LINKED`** - the deal or ticket is not attributed to a partner. Send `partnerId` too.
* **`422 VALIDATION_ERROR`** - no target was sent, or `crmObjectId` came without `crmObjectType`.
* **The partner never heard about it** - check whether the comment came back with `isInternal: true`, and confirm their notification channel in [Channels](/features/engagement/channels).

## Related

<CardGroup cols={2}>
  <Card title="Comments & nudges API" icon="code" href="/general/collaboration-overview">
    The full request, response, target, and error reference.
  </Card>

  <Card title="Nudge stalled deals" icon="bell" href="/features/engagement/notifications/guides/nudge-stalled-deals">
    The no-code version, configured on a pipeline.
  </Card>

  <Card title="Collaborate on a shared deal" icon="handshake" href="/features/co-selling/shared-pipelines/guides/collaborate-on-a-shared-deal">
    The same thread, worked by hand in the app.
  </Card>

  <Card title="Submit a form via the API" icon="paper-plane" href="/features/forms/sharing-submitting/guides/submit-a-form-via-the-api">
    Create the submission you are commenting on.
  </Card>
</CardGroup>
