Skip to content
TriedDocs
Integrations

CRM sync

Push Tried contacts and a call note to HubSpot, Salesforce, Dynamics 365, GoHighLevel or Zoho after every analysed call, and run full sync jobs.

CRM sync keeps your CRM up to date with the people who call your agents. After each analysed phone call, Tried creates or updates the caller's contact in every connected CRM and attaches a note with the call summary. Sync jobs push all contacts at once.

Supported CRMs: HubSpot, Salesforce, Dynamics 365, GoHighLevel and Zoho CRM.

Sync is push only. Changes made in the CRM are not pulled back into Tried contacts.

How it works#

  1. A phone call ends and post-call analysis is stored.
  2. Contact field mappings write values from the call onto the Tried contact.
  3. Contact memory is updated.
  4. For every enabled CRM connection with Sync after calls on, Tried upserts the contact and logs a call note.

Steps 2 to 4 run after the call_analyzed trigger and do not wait for your webhook. They do not run for silent analysis backfills. A failure in one CRM does not stop the others.

What is sent#

The contact:

Tried contact field Sent as
first_name The CRM's first name field
last_name The CRM's last name field. When empty, the first name or the phone number is used for CRMs that require a last name
email The CRM's email field
phone_number The CRM's phone field, and the match key where the CRM supports one
Mapped fields Any CRM field in your field_mapping

The note:

Tried call call_3ffd3f3831b0d4e1a2c96f07

Mia Chen called to book a check-up and clean. The agent offered Tuesday 9am or Wednesday 2pm and booked Tuesday at 9am.
Duration: 94 s
Ended: user_hangup

The title is Tried call <call_id>. The body is the call summary, the duration in seconds and the disconnection reason, each on its own line when present.

Only calls with a contact are synced. Phone calls get a contact automatically from the caller's number. Web calls have no contact.

Connect a CRM#

The Integrations page; the CRM sync tab holds one card per CRM

On Settings, Integrations, CRM sync, each CRM has a card with a badge: Not connected, Mock or Connected.

  • Connect (or Reconnect) starts OAuth. Needs keys
  • Use API token (or Configure once connected) opens a dialog with the credential fields and Field mapping (JSON). Leave the credentials empty to keep mock mode.

Once connected, the card shows the last sync time and:

  • Run full sync: start a sync job for every contact.
  • Sync after calls: the switch for the after-call push (sync_calls).
  • Disconnect: delete the connection and its credentials.

The Sync jobs table below the cards lists recent jobs with Status, Contacts, Notes and Failed counts, refreshing every few seconds.

Field mapping#

field_mapping maps a CRM field name to a Tried contact field:

{
  "lifecyclestage": "stage",
  "hs_lead_status": "lead_status",
  "description": "memory"
}
  • Keys are CRM field API names (lifecyclestage, Description, telephone1).
  • Values are first_name, last_name, email, phone_number, memory (the contact's memory text) or any custom contact field.
  • Empty values are not sent.

GET /get-crm-schema/:provider lists the CRM's contact fields and your contact fields so you can build the mapping:

{
  "provider": "hubspot",
  "object": "contact",
  "mock": false,
  "fields": [
    { "name": "firstname", "label": "First name", "type": "string" },
    { "name": "lifecyclestage", "label": "Lifecycle stage", "type": "enumeration" }
  ],
  "contact_fields": ["first_name", "last_name", "email", "phone_number", "memory", "stage", "lead_status"]
}

In mock mode fields is a built-in default list for the CRM. With credentials it is read live from the CRM.

To fill custom contact fields from calls, set up contact field mappings first, then map those contact fields to CRM fields here.

Sync jobs#

A sync job pushes many contacts at once. Each contact is upserted, and when sync_calls is on, a note for that contact's latest ended call is logged too. Each run logs the note again, so running full sync repeatedly adds repeat notes in CRMs that do not de-duplicate them.

curl -X POST https://api.tried.com.au/run-crm-sync-job \
  -H "Authorization: Bearer $TRIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider": "hubspot", "kind": "full"}'
Field Type Required Description
provider string Yes hubspot, salesforce, dynamics365, gohighlevel or zoho
kind string No full (default): every contact, when sync_contacts is on. contact: only contact_ids
contact_ids string[] For contact Up to 1,000 contact ids
{
  "job_id": "crm_sync_4f8b2e6a0c3d7f1b5e9a2c84",
  "provider": "hubspot",
  "kind": "full",
  "status": "pending",
  "stats": { "contact_ids": null },
  "error": null,
  "mock": false,
  "created_timestamp": 1760691000000,
  "completed_timestamp": null
}

The job runs in the background, up to 10,000 contacts, oldest first. Poll GET /get-crm-sync-job/:id:

{
  "job_id": "crm_sync_4f8b2e6a0c3d7f1b5e9a2c84",
  "provider": "hubspot",
  "kind": "full",
  "status": "complete",
  "stats": { "contacts": 412, "notes": 388, "failed": 2, "errors": ["+61400000000: POST /crm/v3/objects/contacts returned 400: {...}"] },
  "error": null,
  "mock": false,
  "created_timestamp": 1760691000000,
  "completed_timestamp": 1760691094000
}
Field Description
status pending, running, complete or failed
stats.contacts Contacts pushed
stats.notes Call notes logged
stats.failed Contacts that failed
stats.errors Up to 50 messages, each starting with the phone number
error Set when the whole job failed

A disabled connection returns 400 when you start a job.

CRM sync API#

Method and path Purpose
GET /get-crm-config Every CRM with required_credentials and connected, plus your connections
PUT /update-crm-config/:provider Create or update a connection: credentials, enabled, config
DELETE /delete-crm-config/:provider Remove a connection. Returns 204
GET /get-crm-schema/:provider CRM fields and contact fields
POST /test-crm-auth/:provider Check the credentials
POST /run-crm-sync-job Start a sync job. Returns 202
GET /get-crm-sync-job/:id One job
GET /list-crm-sync-jobs The 50 newest jobs

update-crm-config and delete-crm-config need the admin or developer role.

curl -X PUT https://api.tried.com.au/update-crm-config/hubspot \
  -H "Authorization: Bearer $TRIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "credentials": { "access_token": "pat-ap1-..." },
    "enabled": true,
    "config": { "field_mapping": { "lifecyclestage": "stage" }, "sync_calls": true, "sync_contacts": true }
  }'
Field Type Description
credentials object or null The CRM's credential keys. All required keys must be present. null clears them (mock mode)
enabled boolean Disabled connections are skipped after calls and refuse sync jobs
config.field_mapping object CRM field to contact field
config.sync_calls boolean Push the contact and a call note after every analysed call. Default true
config.sync_contacts boolean Include all contacts in full sync jobs. Default true

config is merged with the stored config, so you can send one key.

{
  "provider": "hubspot",
  "enabled": true,
  "mock": false,
  "credentials": { "access_token": "******3c1e" },
  "required_credentials": ["access_token"],
  "config": { "field_mapping": { "lifecyclestage": "stage" }, "sync_calls": true, "sync_contacts": true },
  "last_sync_timestamp": null,
  "last_modification_timestamp": 1760690800000
}
{ "ok": true, "mock": false, "message": "Authenticated." }

In mock mode the test returns {"ok": true, "mock": true, "message": "Mock mode: no credentials are set, operations are recorded instead of sent."}.

CRM actions during calls#

CRM sync runs after the call. To create a contact while the caller is still on the line, give the agent a <crm>.create_contact integration app tool.