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

# CRM Data Sync

> Enable your users to push customer data, leads, and company information directly to their CRM of choice - without building separate integrations for each platform.

## Overview

Many platforms collect valuable customer information - contact details, company data, deal information, and interaction history. Your users need this data in their CRM systems, but manually copying information between platforms is tedious and error-prone.

**The Traditional Problem:**

* Users must manually export data from your platform
* Copy and paste into their CRM (HubSpot, Salesforce, Copper, etc.)
* Risk of data entry errors and outdated information
* No real-time sync between systems

**The Alloy Automation Solution:**

With Alloy Automation, you can add a "Send to CRM" button to your platform that:

* Lets users choose their preferred CRM
* Handles authentication automatically
* Maps your data fields to their CRM's format
* Pushes data with one click
* Works with dozens of CRM platforms

## Components of CRM Data Sync

* **Connectors** - Pre-built integrations for CRM platforms (HubSpot, Salesforce, Copper, Zoho, Pipedrive, and more)
* **Credentials** - Secure authentication that Alloy manages - OAuth flows, API keys, tokens - handled automatically
* **Actions** - Operations available for each CRM (createContact, createDeal, createCompany, updateContact, etc.)
* **Field Mapping** - Translation layer between your universal data model and each CRM's specific field names and requirements

## How CRM Data Sync Works

1. **User clicks "Send to CRM"** in your application
2. **First time only**: User selects their CRM and authenticates (OAuth handled by Alloy)
3. **Your app discovers** available actions and fields for their chosen CRM
4. **Map your data** to their CRM's field format
5. **Show preview** of what will be created (optional but recommended)
6. **Execute action** to push data to their CRM
7. **Confirm success** and store the CRM record ID for future updates

This pattern works for contacts, deals, companies, or any CRM entity. You can trigger syncs manually (button click), automatically (on record creation), in bulk (historical import), or bidirectionally (pull data from CRM back into your platform).

## Building Your First Integration

Select the appropriate drop-down below based on which Alloy Automation product you'll be building with.

<Accordion title="Embedded iPaaS (Coming Soon)" />

<Accordion title="Connectivity API">
  ### Prerequisites

  Before you begin, ensure you have:

  * **Alloy API Key** - Generate in Alloy Dashboard → Settings → API Keys
  * **Base URL** - `https://production.runalloy.com`
  * **Required headers for all API calls**:

  ```
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: USER_ID
  ```

  <Warning>
    Store your API key securely (environment variables, secrets manager). Never expose it in client-side code.
  </Warning>

  ### Step 1: Create a User (One-Time Setup)

  Before managing credentials or executing actions, create a user record in Alloy for each of your end-users. This enables multi-tenancy and isolates each user's credentials and data.

  **API Call:**

  ```bash theme={null}
  POST https://production.runalloy.com/users
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  Content-Type: application/json

  {
    "fullName": "Dexter Morgan",
    "username": "user_bhb"
  }
  ```

  **Response:**

  ```json theme={null}
  {
    "userId": "675987329f2bda83f0dff233"
  }
  ```

  Store this `userId` in your database associated with the user's account. You'll pass it in the `x-alloy-userid` header for all subsequent API calls associated with this user.

  ### Step 2: Discover Available CRM Connectors

  List all available connectors and filter for CRM platforms. This lets you show users which CRMs they can connect to.

  **API Call:**

  ```bash theme={null}
  GET https://production.runalloy.com/connectors
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  ```

  **Response:**

  ```json theme={null}
  {
    "connectors": [
      {
        "id": "hubspot",
        "name": "Hubspot",
        "icon": "https://cdn.runalloy.com/icons/hubspot.png",
        "group": ["input"],
        "category": ["crm"]
      },
      {
        "id": "salesforceCRM",
        "name": "Salesforce CRM",
        "icon": "https://cdn.runalloy.com/icons/salesforceCRM.png",
        "group": ["output"],
        "category": ["sales-crm"]
      }
    ]
  }
  ```

  **Filter for CRM Connectors:**

  ```javascript theme={null}
  const response = await fetch('https://production.runalloy.com/connectors', {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'x-api-version': '2025-09'
    }
  });

  const { connectors } = await response.json();

  // Filter for CRM category
  const crmConnectors = connectors.filter(connector => 
    connector.category && 
    connector.category.some(cat => cat.toLowerCase().includes('crm'))
  );

  // Display these to your user as options
  console.log(`Available CRMs: ${crmConnectors.map(c => c.name).join(', ')}`);
  ```

  ### Step 3: Let User Select CRM and Authenticate

  When a user selects their CRM, check if they already have credentials. If not, initiate the authentication flow.

  **Check for Existing Credentials:**

  ```bash theme={null}
  GET https://production.runalloy.com/connectors/hubspot/credentials
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: 675987329f2bda83f0dff233
  ```

  **Response (No Credentials):**

  ```json theme={null}
  {
    "credentials": []
  }
  ```

  **Create Credential (OAuth Flow):**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/hubspot/credentials
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: 675987329f2bda83f0dff233
  Content-Type: application/json

  {
    "authenticationType": "oauth2",
    "redirectUri": "https://yourplatform.com/crm/callback"
  }
  ```

  **Response:**

  ```json theme={null}
  {
    "oauthUrl": "https://app.hubspot.com/oauth/authorize?client_id=..."
  }
  ```

  Redirect your user to the `oauthUrl`. After they authorize, Alloy redirects them back to your `redirectUri` with a success parameter. The credential is now stored securely and you can use the `credentialId` for all future API calls.

  **Response (Existing Credentials):**

  ```json theme={null}
  {
    "credentials": [
      {
        "credentialId": "cred_xyz789abc",
        "name": "Dexter Morgan's Hubspot",
        "type": "hubspot-oauth2",
        "createdAt": "2025-02-05T15:09:29.551Z",
        "updatedAt": "2025-05-16T10:32:58.003Z"
      }
    ]
  }
  ```

  Store the `credentialId` in your database associated with the user and their selected CRM.

  ### Step 4: Discover Available Actions and Fields

  Before pushing data, inspect what actions are available and what fields they require. This allows you to dynamically build your field mapping.

  **List Available Resources and Actions:**

  ```bash theme={null}
  GET https://production.runalloy.com/connectors/hubspot/resources
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  ```

  **Response:**

  ```json theme={null}
  {
    "resources": [
      {
        "name": "companies",
        "description": "Manage companies.",
        "actions": [
          {
            "id": "createCompany",
            "name": "Create a company",
            "description": "Create a single company."
          },
          {
            "id": "updateCompany",
            "name": "Update a company",
            "description": "Update a company."
          }
        ]
      },
      {
        "name": "contacts",
        "description": "Manage contacts.",
        "actions": [
          {
            "id": "createContact",
            "name": "Create a contact",
            "description": "Create a new contact record."
          },
          {
            "id": "updateContact",
            "name": "Update a contact",
            "description": "Update an existing contact record by its ID."
          }
        ]
      }
    ]
  }
  ```

  **Get Detailed Action Schema:**

  ```bash theme={null}
  GET https://production.runalloy.com/connectors/hubspot/actions/createContact
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  ```

  **Response:**

  ```json theme={null}
  {
    "action": {
      "id": "createContact",
      "displayName": "Create a contact",
      "description": "Create a new contact record.",
      "httpMethod": "post",
      "path": "/crm/v3/objects/contacts",
      "parameters": [],
      "requestBody": {
        "type": "object",
        "required": ["properties"],
        "properties": {
          "properties": {
            "type": "object",
            "required": ["firstname", "lastname", "email"],
            "properties": {
              "firstname": { "type": "string" },
              "lastname": { "type": "string" },
              "email": { "type": "string" },
              "company": { "type": "string" },
              "website": { "type": "string" },
              "phone": { "type": "string" }
            }
          }
        }
      }
    }
  }
  ```

  This tells you exactly what fields the CRM expects, allowing you to map your data correctly.

  ### Step 5: Map Your Data to CRM Fields

  Create a mapping between your platform's field names and each CRM's requirements. Different CRMs use different field names for the same data.

  **Your Universal Data Model:**

  ```json theme={null}
  {
    "contact_email": "john.doe@acme.com",
    "contact_first_name": "John",
    "contact_last_name": "Doe",
    "contact_phone": "+1 (555) 123-4567",
    "contact_company": "Acme Corp",
    "contact_title": "Sales Manager"
  }
  ```

  **Field Mapping Configuration:**

  ```javascript theme={null}
  const fieldMappings = {
    hubspot: {
      contact_email: 'email',
      contact_first_name: 'firstname',
      contact_last_name: 'lastname',
      contact_phone: 'phone',
      contact_company: 'company',
      contact_title: 'jobtitle'
    },
    salesforceCRM: {
      contact_email: 'Email',
      contact_first_name: 'FirstName',
      contact_last_name: 'LastName',
      contact_phone: 'Phone',
      contact_company: 'Company',
      contact_title: 'Title'
    },
    copper: {
      contact_email: 'emails',
      contact_first_name: 'name',
      contact_last_name: 'name',
      contact_phone: 'phone_numbers',
      contact_company: 'company_name'
    }
  };

  function mapFieldsForCRM(universalData, crmName) {
    const mapping = fieldMappings[crmName] || {};
    const mappedData = {};
    
    Object.entries(universalData).forEach(([key, value]) => {
      if (value) {
        const mappedKey = mapping[key] || key;
        mappedData[mappedKey] = value;
      }
    });
    
    return mappedData;
  }
  ```

  **Example Usage:**

  ```javascript theme={null}
  const userData = {
    contact_email: "john.doe@acme.com",
    contact_first_name: "John",
    contact_last_name: "Doe",
    contact_phone: "+1 (555) 123-4567"
  };

  const hubspotData = mapFieldsForCRM(userData, 'hubspot');
  // Result: { email: "john.doe@acme.com", firstname: "John", lastname: "Doe", phone: "+1 (555) 123-4567" }

  const salesforceData = mapFieldsForCRM(userData, 'salesforceCRM');
  // Result: { Email: "john.doe@acme.com", FirstName: "John", LastName: "Doe", Phone: "+1 (555) 123-4567" }
  ```

  ### Step 6: Execute Action to Push Data

  Now you're ready to execute the action and push data to the user's CRM.

  **API Call:**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/hubspot/actions/createContact/execute
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: 675987329f2bda83f0dff233
  Content-Type: application/json

  {
    "credentialId": "cred_xyz789abc",
    "requestBody": {
      "properties": {
        "email": "john.doe@acme.com",
        "firstname": "John",
        "lastname": "Doe",
        "phone": "+1 (555) 123-4567",
        "company": "Acme Corp",
        "jobtitle": "Sales Manager"
      }
    }
  }
  ```

  **Success Response:**

  ```json theme={null}
  {
    "responseData": {
      "id": "166643419989",
      "properties": {
        "createdate": "2025-10-23T18:52:29.567Z",
        "email": "john.doe@acme.com",
        "firstname": "John",
        "lastname": "Doe",
        "phone": "+1 (555) 123-4567",
        "company": "Acme Corp",
        "jobtitle": "Sales Manager"
      },
      "createdAt": "2025-10-23T18:52:29.567Z",
      "updatedAt": "2025-10-23T18:52:29.567Z",
      "url": "https://app.hubspot.com/contacts/166643419989"
    },
    "statusCode": 200
  }
  ```

  Store the returned `id` in your database if you need to update this contact later.

  **Error Response:**

  ```json theme={null}
  {
    "error": {
      "code": "INVALID_CREDENTIAL",
      "message": "The credential has expired or been revoked",
      "details": "User needs to re-authenticate"
    }
  }
  ```

  ### Error Handling

  All Connectivity API endpoints return structured error responses. Handle common scenarios gracefully:

  **Credential Expired or Revoked:**

  ```json theme={null}
  {
    "error": {
      "code": "INVALID_CREDENTIAL",
      "message": "The credential has expired or been revoked"
    }
  }
  ```

  **Solution:** Prompt user to re-authenticate with their CRM.

  **Rate Limit Exceeded:**

  ```json theme={null}
  {
    "error": {
      "code": "RATE_LIMIT_EXCEEDED",
      "message": "Too many requests"
    }
  }
  ```

  **Solution:** Implement exponential backoff and retry logic. Wait before retrying the request.

  **Invalid Field Value:**

  ```json theme={null}
  {
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Invalid field value",
      "details": {
        "field": "email",
        "reason": "Email format is invalid"
      }
    }
  }
  ```

  **Solution:** Validate data before sending to CRM. Show user-friendly error messages.

  **Best Practices:**

  * Log execution IDs for debugging
  * Show human-friendly messages to users
  * Implement retry logic for transient failures (429, 5xx errors)
  * Store credential status in your database to avoid repeated auth failures
</Accordion>

<Accordion title="MCP Gateway (Coming Soon)" />

***

## Connector-Specific Walkthroughs

<Accordion title="HubSpot">
  HubSpot is one of the most popular CRM platforms, offering marketing, sales, and service tools.

  **Available Actions:**

  * `createContact` - Create a new contact
  * `updateContact` - Update existing contact
  * `createDeal` - Create a sales opportunity
  * `createCompany` - Create a company record

  **Authentication:**

  * Type: OAuth 2.0

  **Field Mapping for Contacts:**

  ```javascript theme={null}
  {
    contact_email: 'email',           // Required
    contact_first_name: 'firstname',
    contact_last_name: 'lastname',
    contact_phone: 'phone',
    contact_company: 'company',
    contact_title: 'jobtitle',
    contact_website: 'website',
    contact_address_city: 'city',
    contact_address_state: 'state',
    contact_address_postal: 'zip',
    contact_address_street: 'address',
    contact_address_country: 'country'
  }
  ```

  **Field Mapping for Deals:**

  ```javascript theme={null}
  {
    deal_name: 'dealname',           // Required
    deal_amount: 'amount',
    deal_stage: 'dealstage',
    deal_close_date: 'closedate',
    deal_probability: 'deal_probability'
  }
  ```

  **Example: Create Contact**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/hubspot/actions/createContact/execute
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: user_abc123xyz
  Content-Type: application/json

  {
    "credentialId": "cred_xyz789abc",
    "requestBody": {
      "properties": {
        "email": "sarah.jones@techcorp.com",
        "firstname": "Sarah",
        "lastname": "Jones",
        "phone": "+1 (555) 987-6543",
        "company": "TechCorp",
        "jobtitle": "VP of Sales",
        "city": "San Francisco",
        "state": "CA"
      }
    }
  }
  ```

  **Example: Create Deal**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/hubspot/actions/createDeal/execute
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: user_abc123xyz
  Content-Type: application/json

  {
    "credentialId": "cred_xyz789abc",
    "requestBody": {
      "properties": {
        "dealname": "Q4 Enterprise Contract",
        "amount": "75000",
        "dealstage": "negotiation",
        "closedate": "2025-12-31"
      }
    }
  }
  ```
</Accordion>

<Accordion title="Salesforce CRM">
  Salesforce CRM is the leading enterprise CRM platform with extensive customization capabilities.

  **Available Actions:**

  * `createContact` - Create a new contact
  * `updateContact` - Update existing contact
  * `createOpportunity` - Create a sales opportunity (called "Deal" in other CRMs)
  * `createAccount` - Create an account record (called "Company" in other CRMs)

  **Authentication:**

  * Type: OAuth 2.0

  **Field Mapping for Contacts:**

  ```javascript theme={null}
  {
    contact_email: 'Email',           // Required
    contact_first_name: 'FirstName',
    contact_last_name: 'LastName',    // Required
    contact_phone: 'Phone',
    contact_company: 'Company',
    contact_title: 'Title',
    contact_address_street: 'MailingStreet',
    contact_address_city: 'MailingCity',
    contact_address_state: 'MailingState',
    contact_address_postal: 'MailingPostalCode',
    contact_address_country: 'MailingCountry'
  }
  ```

  **Field Mapping for Opportunities (Deals):**

  ```javascript theme={null}
  {
    deal_name: 'Name',               // Required
    deal_amount: 'Amount',
    deal_stage: 'StageName',         // Required
    deal_close_date: 'CloseDate',    // Required (format: YYYY-MM-DD)
    deal_probability: 'Probability'
  }
  ```

  **Example: Create Contact**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/salesforceCRM/actions/createContact/execute
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: user_abc123xyz
  Content-Type: application/json

  {
    "credentialId": "cred_abc456def",
    "requestBody": {
      "Email": "mike.chen@innovate.io",
      "FirstName": "Mike",
      "LastName": "Chen",
      "Phone": "+1 (555) 234-5678",
      "Title": "Director of Engineering",
      "MailingCity": "Seattle",
      "MailingState": "WA"
    }
  }
  ```

  **Example: Create Opportunity**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/salesforceCRM/actions/createOpportunity/execute
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: user_abc123xyz
  Content-Type: application/json

  {
    "credentialId": "cred_abc456def",
    "requestBody": {
      "Name": "Enterprise Platform Migration",
      "Amount": 125000,
      "StageName": "Proposal/Price Quote",
      "CloseDate": "2025-11-30",
      "Probability": 60
    }
  }
  ```

  <Note>
    The `StageName` values depend on your Salesforce org's configuration. Common values include: "Prospecting", "Qualification", "Proposal/Price Quote", "Negotiation/Review", "Closed Won", "Closed Lost".
  </Note>
</Accordion>

<Accordion title="Copper">
  Copper (formerly ProsperWorks) is a CRM designed for Google Workspace users.

  **Available Actions:**

  * `createPerson` - Create a new person (called "Contact" in other CRMs)
  * `updatePerson` - Update existing person
  * `createOpportunity` - Create a sales opportunity
  * `createCompany` - Create a company record

  **Authentication:**

  * Type: OAuth 2.0

  **Field Mapping for People (Contacts):**

  ```javascript theme={null}
  {
    contact_email: 'emails',          // Array: [{ email: "...", category: "work" }]
    contact_first_name: 'name',       // Combined into single name field
    contact_last_name: 'name',        // Combined into single name field
    contact_phone: 'phone_numbers',   // Array: [{ number: "...", category: "work" }]
    contact_company: 'company_name',
    contact_title: 'title'
  }
  ```

  **Field Mapping for Opportunities (Deals):**

  ```javascript theme={null}
  {
    deal_name: 'name',                // Required
    deal_amount: 'monetary_value',    // Integer (cents)
    deal_stage: 'pipeline_stage_id', // Must be valid stage ID
    deal_close_date: 'close_date'     // Unix timestamp
  }
  ```

  **Example: Create Person**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/copper/actions/createPerson/execute
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: user_abc123xyz
  Content-Type: application/json

  {
    "credentialId": "cred_def789ghi",
    "requestBody": {
      "name": "Lisa Rodriguez",
      "emails": [
        {
          "email": "lisa.rodriguez@globalco.com",
          "category": "work"
        }
      ],
      "phone_numbers": [
        {
          "number": "+1 (555) 345-6789",
          "category": "work"
        }
      ],
      "title": "Product Manager",
      "company_name": "GlobalCo"
    }
  }
  ```

  **Example: Create Opportunity**

  ```bash theme={null}
  POST https://production.runalloy.com/connectors/copper/actions/createOpportunity/execute
  Authorization: Bearer YOUR_API_KEY
  x-api-version: 2025-09
  x-alloy-userid: user_abc123xyz
  Content-Type: application/json

  {
    "credentialId": "cred_def789ghi",
    "requestBody": {
      "name": "Annual Subscription Renewal",
      "monetary_value": 4500000,
      "pipeline_stage_id": 123456,
      "close_date": 1735689600
    }
  }
  ```

  <Note>
    The `monetary_value` is in cents (so 4500000 = \$45,000), and `pipeline_stage_id` must reference a valid pipeline stage in the user's Copper account. You may need to fetch available pipeline stages first.
  </Note>
</Accordion>

***

## Common Integration Patterns

While this blueprint focuses on the "Send to CRM" button use case, Alloy Automation is flexible enough to support many patterns:

**Manual Sync (Button Click)**\
User reviews data and clicks "Send to CRM" to push selected records. This gives users control over what gets synced and when.

**Automatic Background Sync**\
Trigger syncs automatically when records are created or updated in your platform. Users don't need to take any action - data flows seamlessly.

**Bulk Historical Import**\
When a user first connects their CRM, offer to sync all existing records from your platform. Process in batches to respect rate limits.

**Bidirectional Sync**\
Pull data from the CRM back into your platform. Keep both systems in sync automatically.

**Selective Sync with Filters**\
Let users choose which types of records or which customers to sync based on tags, status, or custom criteria.

***

## Additional Resources

* [Connectivity API Quick Start Guide](https://docs.runalloy.com/connectivity-api/quick-start) - Complete walkthrough of the Connectivity API flow
* [Connectivity API Reference](https://docs.runalloy.com/reference/connectivity-api/connectivity-api) - Full API endpoint documentation
* [Connector Library](https://docs.runalloy.com/connectors) - Browse all available CRM connectors

**Next Steps:**\
Now that you understand CRM data sync, explore our companion blueprints on **Business Loan Underwriting** for financial data extraction and **Journal Entries** for accounting reconciliation workflows.
