Set CRM lead sync rules

Set which Vini conversations are written to the dealer's CRM for this rooftop.

PUThttps://api.spyne.ai/leads/dealer/v1/crm-config/leads-sync
AuthBearer token (console user) with MODIFY_CRM_CONFIG_ALL (EDIT) permissionRate limitNot documentedProcessingOne database write; the updated settings are returned.

This updates the rooftop's CRM lead sync gate: whether it is enforced, and which call types, outcomes and interest levels cause a conversation to sync to the CRM. Each list you send replaces the stored list. Appointment and Callback outcomes always sync and cannot be changed. Without agent, the settings are written for both the inbound and the outbound agent. The record is created if it does not exist.

Before you call it

  • You need the bearer token of a signed-in console user with the MODIFY_CRM_CONFIG_ALL (EDIT) permission on the dealer group and rooftop.
  • Save the rooftop's CRM first with Save an integration and entity: "CRM". This endpoint does not check that.
  • Send at least enforced or one list. An empty update returns 400.
  • One database write; the updated settings are returned. Rate limit: not documented.

Request body

Requiredalways sendOptionalcan be left out
ParameterTypeRequiredDescription
Header———
AuthorizationstringRequiredBearer YOUR_TOKEN
Body———
enterprise_idstringRequired<enterpriseId> of the dealer group. Snake case.
team_idstringRequired<teamId> of the rooftop. Snake case.
agentstringOptionalinbound or outbound. Leave it out to apply to both. The UI leaves it out.
enforcedbooleanOptionalWhether the gate holds conversations. The UI always sends true.
selectedCallTypesstring[]OptionalCall types that sync. Any non-empty string is accepted except no_signal. Known sales values: sales_shopping, sales_routing, service_routing, finance_routing, parts_routing, human_request, operational, other. Unknown values are accepted with a warning.
selectedOutcomesstring[]OptionalOutcomes that sync, as Title Case labels. Allowed: Appointment, Transfer, Callback, Query Resolved, Qualified Lead, None.
selectedInterestsstring[]OptionalInterest levels that sync. Allowed: not_interested, soft_considering, interested, strong_buying, no_vehicle_discussed.
Request checklist
  1. Authenticate: set Authorization: Bearer YOUR_TOKEN.
  2. Identify the rooftop: send enterprise_id and team_id in snake case.
  3. Outcomes: send them as the Title Case labels above.
  4. Leave out locked outcomes: do not send lockedOutcomes.

Sample request

curl -X PUT "https://api.spyne.ai/leads/dealer/v1/crm-config/leads-sync" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enterprise_id": "<enterpriseId>",
    "team_id": "<teamId>",
    "enforced": true,
    "selectedCallTypes": ["sales_shopping", "human_request"],
    "selectedOutcomes": ["Appointment", "Callback", "Transfer"],
    "selectedInterests": ["interested", "strong_buying"]
  }'
import requests

res = requests.put(
    "https://api.spyne.ai/leads/dealer/v1/crm-config/leads-sync",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={
        "enterprise_id": "<enterpriseId>",
        "team_id": "<teamId>",
        "enforced": True,
        "selectedCallTypes": ["sales_shopping"],
        "selectedOutcomes": ["Appointment", "Callback"],
        "selectedInterests": [],
    },
)
print(res.json())
const res = await fetch(
  "https://api.spyne.ai/leads/dealer/v1/crm-config/leads-sync",
  {
    method: "PUT",
    headers: {
      Authorization: "Bearer YOUR_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      enterprise_id: "<enterpriseId>",
      team_id: "<teamId>",
      enforced: true,
      selectedCallTypes: ["sales_shopping"],
      selectedOutcomes: ["Appointment", "Callback"],
      selectedInterests: ["interested"],
    }),
  }
);
const body = await res.json();

Sample response

{
  "message": "CRM leads sync configuration updated successfully",
  "crmLeadsSync": {
    "enforced": true,
    "selectedCallTypes": ["sales_shopping", "human_request"],
    "selectedOutcomes": ["Appointment", "Callback", "Transfer"],
    "selectedInterests": ["interested", "strong_buying"],
    "lockedOutcomes": ["Appointment", "Callback"]
  },
  "changes": {
    "selectedOutcomes": { "from": ["Appointment", "Callback"], "to": ["Appointment", "Callback", "Transfer"] }
  }
}
{
  "message": "CRM leads sync configuration updated successfully",
  "crmLeadsSync": { "enforced": true, "selectedCallTypes": ["sales_shoping"] },
  "changes": {},
  "warnings": [
    "selectedCallTypes: \"sales_shoping\" is not a known sales call type. Accepted (service call types are configured per agent and cannot be validated here), but if this is a typo it will never match and those conversations will be held."
  ]
}
{
  "message": "Invalid CRM leads sync configuration",
  "errors": ["selectedOutcomes contains unsupported outcome: \"Booked\". Supported: Appointment, Transfer, Callback, Query Resolved, Qualified Lead, None"],
  "error": true
}
{ "message": "Invalid Token", "error": true, "code": "ERROR_AUTH_401", "details": "<details>", "data": null }
{ "message": "You don't have permission to update the CRM leads sync configuration", "error": true }
{ "message": "Error updating CRM leads sync configuration", "error": "<error message>" }

Response parameters

ParameterTypeDescription
messagestringResult message.
crmLeadsSyncobject or nullThe stored settings after the update (for the inbound agent when agent is left out).
crmLeadsSync.enforcedbooleanWhether the gate holds conversations.
crmLeadsSync.selectedCallTypes, selectedOutcomes, selectedInterestsstring[]Stored selections.
crmLeadsSync.lockedOutcomesstring[]Outcomes that always sync.
changesobjectfrom and to for each field that changed.
warningsstring[]Present only when unknown call types were accepted.

Errors

StatusCodeWhen it happens
400Invalid CRM leads sync configurationA value is not allowed, a list is not an array, enforced is not boolean, lockedOutcomes was sent, or the database rejected the value.
400Nothing to update: provide 'enforced' and/or a selection listNo enforced and no list in the body.
401Token errorMissing or rejected token.
403PermissionThe user lacks MODIFY_CRM_CONFIG_ALL (EDIT) on the dealer group and rooftop.
408TimeoutUser management could not be reached.
500Error updating CRM leads sync configurationUnexpected error.

A typo in a call type is accepted with 200 and a warning. Those conversations will not match.

What happens next

When this call and the CRM save both succeed, the UI calls Mark a checklist task done in the Checklist section with taskName: "CRM Integration". If this call fails after the CRM save succeeded, the CRM link is already saved and the task is not marked done. Retrying the full save is safe.


Did this page help you?