Skip to main content

Sync Agents

Synchronizes the local agent_mappings table with the current state of agents in Ultravox. Imports new agents that do not have local mappings, updates existing mappings with the latest Ultravox configuration, and identifies orphaned mappings whose Ultravox agents no longer exist. Supports multiple sync modes and optional orphan cleanup.

Endpoint

PropertyValue
Function Nameagents-sync
HTTP MethodPOST
AuthenticationSupabase JWT (Bearer token)
Required Roleagency_owner or agency_admin

Request

Headers

Authorization: Bearer <supabase_jwt_token>
Content-Type: application/json

Body

The body is optional. If omitted or unparseable, defaults are used.

FieldTypeRequiredDescription
modestringNoSync mode. One of "full" (default), "import_only", or "update_only".
remove_orphansbooleanNoWhether to delete local mappings for agents that no longer exist in Ultravox. Defaults to false.

Sync Modes:

ModeImports New AgentsUpdates ExistingDetects Orphans
fullYesYesYes
import_onlyYesNo (marks as unchanged)Yes
update_onlyNo (marks as unchanged)YesYes

Response

Success (200)

{
"success": true,
"message": "Synced 5 agents from Ultravox",
"stats": {
"imported": 2,
"updated": 3,
"skipped": 10,
"errors": 0
}
}
FieldDescription
stats.importedNumber of new agents imported from Ultravox (new local mappings created).
stats.updatedNumber of existing mappings updated with changed Ultravox configuration.
stats.skippedNumber of agents that had no changes, or were skipped due to mode restrictions. Also includes orphaned agents in the count logic.
stats.errorsNumber of agents that failed to sync.

The message field summarizes the count of imported plus updated agents.

Error Responses

StatusCondition
400Ultravox API key is not configured for the agency
401Missing or invalid authorization header
403User is not associated with an agency
403User role is not agency_owner or agency_admin
405HTTP method is not POST
500Failed to retrieve API credentials
500Unexpected server error
502Ultravox API returned an error when fetching agents

Behavior

  • Authenticates the user via Supabase JWT and verifies they belong to an agency with the agency_owner or agency_admin role.
  • Parses the optional request body for mode and remove_orphans options.
  • Retrieves the agency's Ultravox API key by calling the get_agency_credentials RPC function.
  • Fetches all agents from Ultravox by paginating through the /api/agents endpoint (100 per page) until no next cursor remains.
  • Fetches all existing agent_mappings records for the agency.
  • Builds lookup structures: a Map of existing mappings keyed by ultravox_agent_id, and a Set of all Ultravox agent IDs.
  • For each Ultravox agent, fetches the full agent details via GET /api/agents/{agent_id} to obtain the complete callTemplate (since the list endpoint may not include it).
  • New agents (no existing mapping):
    • In update_only mode, skipped as unchanged.
    • Otherwise, inserts a new agent_mappings record with managed_by_virsyn set to false, the full call template configuration (system_prompt, voice, language_hint, temperature, first_speaker_text, recording_enabled, max_duration_seconds, tools), and last_synced_at timestamp.
  • Existing agents (mapping exists):
    • In import_only mode, skipped as unchanged.
    • Otherwise, compares key fields (name, system_prompt, voice, language_hint, temperature) to detect changes.
    • If changes are detected, updates the mapping record with the latest Ultravox configuration, sets last_synced_at, and clears sync_error.
    • If no changes are detected, only updates last_synced_at and clears sync_error.
  • Orphaned mappings (local mapping exists but Ultravox agent does not):
    • Always detected regardless of mode.
    • If remove_orphans is true: unassigns any phone numbers linked to the orphaned mapping (sets agent_mapping_id to null in agency_phone_numbers), then deletes the mapping.
    • Reported in results with action orphaned.
  • Returns a summary with counts of imported, updated, skipped, and errored agents.

Database Tables

TableOperationDescription
usersReadFetches user profile to determine agency_id and role
agent_mappingsReadFetches all existing mappings for the agency
agent_mappingsInsertCreates new mappings for imported agents
agent_mappingsUpdateUpdates existing mappings with latest Ultravox config, or updates last_synced_at for unchanged agents
agent_mappingsDeleteRemoves orphaned mappings (when remove_orphans is true)
agency_phone_numbersReadChecks for phone numbers assigned to orphaned mappings
agency_phone_numbersUpdateUnassigns phone numbers from orphaned mappings

External APIs

APIMethodEndpointDescription
UltravoxGET/api/agents?limit=100Fetches paginated list of all agents (iterates until all pages consumed)
UltravoxGET/api/agents/{agent_id}Fetches full details for each agent (to get complete callTemplate)
  • List Agents -- List agents with merged data (single-page fetch)
  • Create Agent -- Create a new agent (creates mapping with managed_by_virsyn=true)
  • Assign Agent -- Assign agents to clients/campaigns after syncing
  • Delete Agent -- Delete agents and their mappings