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.
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
User clicks “Send to CRM” in your application
First time only : User selects their CRM and authenticates (OAuth handled by Alloy)
Your app discovers available actions and fields for their chosen CRM
Map your data to their CRM’s field format
Show preview of what will be created (optional but recommended)
Execute action to push data to their CRM
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.
Embedded iPaaS (Coming Soon)
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
Store your API key securely (environment variables, secrets manager). Never expose it in client-side code.
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: 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: {
"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: GET https://production.runalloy.com/connectors
Authorization: Bearer YOUR_API_KEY
x-api-version: 2025-09
Response: {
"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: 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: 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): Create Credential (OAuth Flow): 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: {
"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): {
"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: GET https://production.runalloy.com/connectors/hubspot/resources
Authorization: Bearer YOUR_API_KEY
x-api-version: 2025-09
Response: {
"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: GET https://production.runalloy.com/connectors/hubspot/actions/createContact
Authorization: Bearer YOUR_API_KEY
x-api-version: 2025-09
Response: {
"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: {
"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: 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: 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: 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: {
"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: {
"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: {
"error" : {
"code" : "INVALID_CREDENTIAL" ,
"message" : "The credential has expired or been revoked"
}
}
Solution: Prompt user to re-authenticate with their CRM.Rate Limit Exceeded: {
"error" : {
"code" : "RATE_LIMIT_EXCEEDED" ,
"message" : "Too many requests"
}
}
Solution: Implement exponential backoff and retry logic. Wait before retrying the request.Invalid Field Value: {
"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
MCP Gateway (Coming Soon)
Connector-Specific Walkthroughs
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: Field Mapping for Contacts: {
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: {
deal_name : 'dealname' , // Required
deal_amount : 'amount' ,
deal_stage : 'dealstage' ,
deal_close_date : 'closedate' ,
deal_probability : 'deal_probability'
}
Example: Create Contact 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 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"
}
}
}
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: Field Mapping for Contacts: {
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): {
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 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 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
}
}
The StageName values depend on your Salesforce org’s configuration. Common values include: “Prospecting”, “Qualification”, “Proposal/Price Quote”, “Negotiation/Review”, “Closed Won”, “Closed Lost”.
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: Field Mapping for People (Contacts): {
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): {
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 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 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
}
}
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.
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
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.