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

# Triggering from Salesforce

> Create a custom button inside the native Salesforce app in order to trigger the tool directly from within the CRM.

This integration enables your sales reps to autonomously launch Cargo actions directly associated to a contact or account without leaving the CRM. Perfect for on-demand company research, contact enrichment, and lead scoring.

***

## Prerequisites

What you'll need to make this possible:

| Requirement                 | Description                                                                                                                         |
| :-------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- |
| **Salesforce admin access** | Required to create flows, named credentials, and custom buttons—and to create the SFDC connector in Cargo (if not already the case) |
| **Cargo workspace**         | With write access and a Tool already configured                                                                                     |
| **API access**              | Your Cargo API token and tool endpoint URL                                                                                          |

***

## Step 1 - Define and deploy a Tool in Cargo

Define the tool in code — an input schema that matches the fields Salesforce will send, a workflow that researches the account and writes back via the Salesforce connector, then deploy it:

```ts tools/account-research.ts theme={null}
import { defineTool, defineWorkflow } from "@cargo-ai/cdk";
import { z } from "zod";

const research = defineWorkflow(
  "account-research",
  {
    input: z.object({ accountId: z.string(), domain: z.string(), ownerId: z.string() }),
    output: z.object({ message: z.string() }),
  },
  ({ input, ai, integrations }) => {
    const brief = ai(`Research the company at ${input.domain} for account ${input.accountId}.`);
    integrations.salesforce.updateRecords({
      objectType: "Account",
      matchingValue: input.accountId,
      matchingPropertyName: "Id",
      mappings: [{ propertyName: "Research__c", value: brief }],
    });
    return { message: brief };
  },
);

export const accountResearch = defineTool("account-research", { workflow: research });
```

```bash theme={null}
cargo-ai cdk deploy
cargo-ai orchestration tool list        # → the tool's UUID for the URL below
```

<Accordion title="Prefer the UI?">
  Build the same tool in the visual editor — an AI prompt for research, a
  Salesforce **Update** action, and input parameters for the fields Salesforce
  sends.

  <div style={{position: "relative", paddingBottom: "calc(62.5% + 41px)", height: 0, width: "100%"}}>
    <iframe src="https://demo.arcade.software/DyYrU1nsWb9SQ9w0PEBz?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Integrate Account Research Workflows with API Access" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
  </div>
</Accordion>

Either way, the tool is reachable at its execute endpoint — this is the URL Salesforce will call:

```bash theme={null}
https://api.getcargo.io/v1/tools/<TOOL_UUID>/execute?token=<API_TOKEN>
```

| Placeholder   | Description          |
| :------------ | :------------------- |
| `<TOOL_UUID>` | Your unique tool ID  |
| `<API_TOKEN>` | Your Cargo API token |

***

## Step 2 - Create a named credential

Named credentials store the Cargo API endpoint securely within Salesforce.

<div style={{position: "relative", paddingBottom: "calc(62.5% + 41px)", height: 0, width: "100%"}}>
  <iframe src="https://demo.arcade.software/vQRYqt1RJcP8I2doPDQa?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Step 2 - Create a Named Credential in Salesforce" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
</div>

1. Go to **Setup → Named Credentials**
2. Click **New** and select **Legacy Named Credential**
3. Enter the label and URL for your Cargo endpoint
4. Save the credential

***

## Step 3 - Register an external service

External services allow Salesforce to communicate with the Cargo API. In **Setup → External Services**, register a new service.

<div style={{position: "relative", paddingBottom: "calc(62.5% + 41px)", height: 0, width: "100%"}}>
  <iframe src="https://demo.arcade.software/IpsfnyJoEXUbDZvTIhOz?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Step 3 - Register an External Service in Salesforce" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
</div>

Select the named credential you just created and register the service with the following OpenAPI schema:

```json theme={null}
{
  "openapi": "3.0.1",
  "info": {
    "title": "Cargo",
    "description": ""
  },
  "paths": {
    "CARGOPATH": {
      "post": {
        "description": "",
        "operationId": "Query Cargo",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "description": "",
            "required": false,
            "allowEmptyValue": false,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "description": "",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "accountId": { "type": "string" },
                  "linkedinUrl": { "type": "string" },
                  "domain": { "type": "string" },
                  "name": { "type": "string" },
                  "linkedinId": { "type": "string" },
                  "ownerId": { "type": "string" }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": { "type": "string" }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
```

<Warning>
  **Replace `CARGOPATH`** with your actual Tool URL from Cargo. Use only the path portion starting with `/v1` and ending with `execute`:

  ```
  /v1/tools/e276dc32-aca1-4136-bbe7-dce879346c58/execute
  ```
</Warning>

<Note>
  The `properties` in the schema must match the fields you'll configure in **Step 4.2**. For example:

  ```json theme={null}
  {
    "ownerId": { "type": "string" },
    "accountId": { "type": "string" },
    "domain": { "type": "string" }
  }
  ```
</Note>

***

## Step 4 - Create a flow

Flows orchestrate the entire integration—retrieving data from Salesforce, sending it to Cargo, and handling the response.

### 4.1 - Retrieve account records

Create a **flow** that pulls account records from Salesforce.

<div style={{position: "relative", paddingBottom: "calc(62.5% + 41px)", height: 0, width: "100%"}}>
  <iframe src="https://demo.arcade.software/988fE6fMLjlHfXnGcdkF?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Step 3 - Create a Flow to Retrieve Account Records in Salesforce" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
</div>

### 4.2 - Map fields in an assignment step

Map the Salesforce fields to the inputs required by your Cargo HTTP call.

<div style={{position: "relative", paddingBottom: "calc(62.5% + 41px)", height: 0, width: "100%"}}>
  <iframe src="https://demo.arcade.software/Za7j5UmPAgopbrrTLFoL?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Step 4 - Map Fields in a Salesforce Flow Assignment Step" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
</div>

Specify the JSON schema for the HTTP callout—this must align with the schema from **Step 3**. Use placeholder values to configure the action:

```json theme={null}
{
  "accountId": "0018b00002ABCDeAA1",
  "domain": "example.com",
  "ownerId": "0058b00001XYZAbAA1"
}
```

### 4.3 - Add a screen step at the end of the flow

Add a **screen element** to display results or request user input before the flow completes.

<div style={{position: "relative", paddingBottom: "calc(57.12240515390121% + 41px)", height: 0, width: "100%"}}>
  <iframe src="https://demo.arcade.software/2iwQ5qUufacXyp23nDXB?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Step 5 - Add a Screen Step to Your Salesforce Flow" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
</div>

### 4.4 - Map HTTP callout variables to the assignment action

Connect the variables created during the HTTP callout configuration to your assignment action. This ensures data flows correctly through the flow.

<div style={{position: "relative", paddingBottom: "calc(62.5% + 41px)", height: 0, width: "100%"}}>
  <iframe src="https://demo.arcade.software/7bwz9KwQfUqKM90O9oxm?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Step 4.4 - Configure Variable Assignments for HTTP Callouts in Salesforce Flow" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
</div>

***

## Step 5 - Add a custom button to your Accounts interface

Finally, create the button that sales reps will use to trigger the flow. Go to **Setup → Object Manager → Account → Buttons, Links, and Actions**.

<div style={{position: "relative", paddingBottom: "calc(62.5% + 41px)", height: 0, width: "100%"}}>
  <iframe src="https://demo.arcade.software/ZhmmQaWb6J37VdfD4YXF?embed&embed_mobile=inline&embed_desktop=inline&show_copy_link=true" title="Step 6 - Add a Custom Flow Button to an Account in Salesforce" frameBorder="0" loading="lazy" webkitAllowFullScreen mozAllowFullScreen allowFullScreen allow="clipboard-write" style={{position: "absolute", top: 0, left: 0, width: "100%", height: "100%", colorScheme: "light"}} />
</div>

1. Create a new **Flow Button**
2. Link it to the flow you built in Step 4
3. Add the button to the Account page layout

***

## Testing your integration

### Verify the setup

1. **Test the button** — Click your custom button on an Account record
2. **Check the flow** — Ensure the flow runs without errors
3. **Monitor the Tool** — Verify the Cargo Tool executes and updates the Salesforce record
4. **Review results** — Confirm the Account record is updated with the research data

### Troubleshooting

<AccordionGroup>
  <Accordion title="Flow failed to start">
    * Check that the custom button is properly linked to the flow - Verify the
      flow is active and has the correct permissions
  </Accordion>

  <Accordion title="HTTP callout failed">
    * Verify the named credential is correctly configured - Check that the API
      token is valid and has proper permissions - Ensure the tool ID in the URL
      matches your Cargo tool
  </Accordion>

  <Accordion title="Tool not executing">
    * Confirm the tool is receiving data from Salesforce - Check that the Tool
      is active and properly configured - Verify the Salesforce update action has
      the correct field mappings
  </Accordion>
</AccordionGroup>

***

## Next steps

Once your integration is working:

| Action               | Description                                    |
| :------------------- | :--------------------------------------------- |
| **Train your team**  | Show reps how to use the new button            |
| **Monitor usage**    | Track which accounts are being researched      |
| **Optimize prompts** | Refine your Tool's AI prompts based on results |
| **Scale up**         | Add similar buttons for Contacts or Leads      |
