SIVO
Data model

Concepts

Data model

SIVO's main entities and how they relate. For your technical team needing to understand how to model the integration.

Updated:
conceptsdata-modelentities

This page describes SIVO’s main entities and their relationships. Useful for your IT team, solution architects and integrators needing to know how to model the integration with their systems.

Overview

┌─────────────────────────────────────────────────────────────────┐
│                          Tenant                                  │
│  ┌───────┐  ┌────────┐  ┌──────┐  ┌──────┐  ┌──────────────┐   │
│  │ Users │  │ Queues │  │ DIDs │  │ IVRs │  │ SIP Trunks    │   │
│  └───┬───┘  └────┬───┘  └───┬──┘  └───┬──┘  └──────┬───────┘   │
│      │           │          │         │             │           │
│      └───────────┴──────────┴─────────┴─────────────┘           │
│                            │                                    │
│                       ┌────▼─────┐                              │
│                       │  Calls   │  (CDR + recordings +         │
│                       │          │   transcripts + events)      │
│                       └──────────┘                              │
└─────────────────────────────────────────────────────────────────┘

Everything hangs from the Tenant — the main isolation container. One tenant’s data is not visible from another (see Multi-tenant).

Main entities

Tenant

The tenant is the customer. Each SIVO org has one or more tenants.

FieldTypeMeaning
idUUIDInternal unique identifier
slugstringURL-friendly (e.g. acme-corp)
namestringDisplay name in UI
sip_domainstringSIP domain (acme.sip.sivocenter.com)
planenumstarter / pro / enterprise
regionenumeu / us / custom
created_attimestampSignup date

User

Every person with SIVO access. Acts as both agent (handles calls) and panel user.

FieldTypeMeaning
idUUIDUnique identifier
tenant_idUUIDTenant they belong to
emailstringLogin + communications
full_namestringFull name
extensionstringSIP extension (3-5 digits)
roleenumagent / supervisor / admin / viewer
statusenumavailable / on_call / paused / acw / logged_out
languageenumes / en / de / fr / it / pt
mfa_enabledboolWhether MFA is enabled

Queue

ACD queue. Distributes calls among agents per a strategy.

FieldMeaning
id, name, tenant_idIdentification
strategyring-all / longest-idle / round-robin / top-down / fewest-calls / random
max_wait_timeSeconds before timeout
wrap_up_timeAutomatic ACW after hangup
moh_urlHold music
announce_positionWhether to tell caller “you’re number N in queue”
service_level_target% goal answered in under N seconds

Relationship with users: many-to-many via queue_members:

FieldMeaning
queue_id, user_idIdentification
tierPriority (1 = primary, 2 = backup)
levelSub-priority within tier

DID

Direct Inward Dial — an inbound number.

FieldMeaning
id, tenant_idIdentification
numberE.164 (+34911234567)
trunk_idTrunk via which calls come in
ivr_flow_idIVR that runs
schedule_idAssigned schedule (optional)
out_of_hours_ivr_flow_idOut-of-hours IVR
outbound_caller_idWhether allowed as outbound caller ID

IVR Flow

A call flow. Multiple versions per flow.

FieldMeaning
id, name, tenant_idIdentification
descriptionHuman description

And per version (ivr_flow_versions):

FieldMeaning
flow_id, versionIdentification
is_activeOnly one active version per flow
nodesJSON with nodes (start, menu, queue, etc.)
created_at, created_byAudit

SIP Trunk

Connection with your phone carrier.

FieldMeaning
id, name, tenant_idIdentification
providerzadarma / twilio / bandwidth / custom
hostRegistrar SIP host
username, password_encryptedCredentials (password AES-256-GCM encrypted)
allowed_cidrsArray of allowed IPs/CIDRs
stateREGED / TRYING / FAIL / NOREG
failover_trunk_idFailover trunk (optional)

Schedule

Business hours and holidays.

FieldMeaning
id, name, tenant_idIdentification
timezoneIANA (Europe/Madrid)
hoursJSON per day with open/close
holidaysArray of YYYY-MM-DD dates
exceptionsOne-off exceptions

Call (CDR)

A call. The highest-volume entity.

FieldMeaning
idUUID
tenant_idTenant
directioninbound / outbound / internal
caller_id_number, caller_id_nameOrigin
destinationDestination
did_idDID it came through (if inbound)
agent_idAgent who answered (nullable)
queue_idQueue it went through (nullable)
ivr_flow_idIVR that ran (nullable)
statusanswered / no_answer / busy / failed / abandoned
started_at, answered_at, ended_atTimestamps
duration_sec, billsecTotal and talk time
hangup_causeNORMAL_CLEARING, CALL_REJECTED, etc.
recording_idIf recorded
transcript_idIf transcribed
mos_scoreAudio quality (1-5)
salesforce_voicecall_idIf pushed to SF

Recording

FieldMeaning
id, call_id, tenant_idIdentification
storage_urlPre-signed URL
formatwav / mp3 / ogg
duration_sec, size_bytesSize
expires_atWhen it’s deleted (policy-sealed)
providersivo_managed / s3 / gcs / azure / minio

Transcript

FieldMeaning
id, call_id, tenant_idIdentification
providerdeepgram / elevenlabs / whisper
languageISO 639-1 (es, en)
segmentsJSON with turns: [{speaker, start, end, text}, ...]
expires_atSealed at creation

Audit Log

Immutable.

FieldMeaning
id, timestampIdentification
tenant_id, actor_user_idActor
actor_ip, actor_uaOrigin
actioncreate / update / delete / access / login
resource_type, resource_idAffected object
diffJSONB with before/after
cross_tenantIf superadmin action

Identities — external IDs

For integrations, SIVO uses these stable IDs you can save in your systems:

SystemID to save
Salesforce VoiceCallvendor_call_key (UUID generated by SIVO)
Your webhooksevent_id (UUID per event)
Your CRMSIVO’s call_id
Your ticketing systemcall_id or transcript_id

All are UUIDs, stable, never reused.

IVR session variables

Variables available in any flow node:

VariableValue
caller_id_numberOrigin E.164
caller_id_nameName if carrier sends it
didDID it came through
nowCurrent UTC timestamp
languageExpected language
attemptN-th attempt if retry

Plus the custom ones you define in input, webhook, function, ai_agent nodes.

Cross-relationships

A call with everything linked

Call
 ├── tenant_id        → Tenant
 ├── did_id           → DID            → IVR Flow → Versions → Nodes
 ├── agent_id         → User           → Queue Members → Queues
 ├── queue_id         → Queue
 ├── recording_id     → Recording      → expires per Recording Policy
 ├── transcript_id    → Transcript     → expires per Transcription Policy
 ├── salesforce_voicecall_id → SF VoiceCall + Conversation + ConversationEntries
 └── associated audit_logs entries

Emitted events

Every relevant change emits an event consumable via webhook:

call.created  call.answered  call.transferred  call.ended  call.recorded
queue.entered  queue.abandoned
agent.status_changed  agent.paused
ivr.completed  ai_agent.completed
transcript.segment  transcript.completed
salesforce.voicecall_pushed

Full schema at Webhooks.

What SIVO does NOT store

To avoid confusion:

  • Contacts / Leads / Cases: live in your CRM (Salesforce, HubSpot, your own). SIVO only links via caller_id_number.
  • Opportunities / invoices: same. SIVO is a contact center, not a CRM.
  • Sensitive caller data (ID number, IBAN, etc.): if your IVR captures them, it passes them to your system via webhook. SIVO doesn’t store them except in transcripts (with configurable retention).

REST API

Each entity has its CRUD in the API:

GET    /api/{resource}
POST   /api/{resource}
GET    /api/{resource}/{id}
PUT    /api/{resource}/{id}
DELETE /api/{resource}/{id}

Documented at /api with complete OpenAPI.

Best practices

  1. Use SIVO’s UUID as source-of-truth to identify calls in your CRM. Don’t use phone number — a caller may dial from several.
  2. Subscribe to specific webhooks (call.ended, transcript.completed) instead of polling the API.
  3. Capture IVR variables you need for your BI. Better capture extra than have to reconstruct.
  4. Document your mapping: which IVR variable maps to which CRM field. Useful as your team grows.
  5. Annual data-model audit: SIVO adds new fields with each release. Review changelog to leverage them.