Concepts
Data model
SIVO's main entities and how they relate. For your technical team needing to understand how to model the integration.
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.
| Field | Type | Meaning |
|---|---|---|
id | UUID | Internal unique identifier |
slug | string | URL-friendly (e.g. acme-corp) |
name | string | Display name in UI |
sip_domain | string | SIP domain (acme.sip.sivocenter.com) |
plan | enum | starter / pro / enterprise |
region | enum | eu / us / custom |
created_at | timestamp | Signup date |
User
Every person with SIVO access. Acts as both agent (handles calls) and panel user.
| Field | Type | Meaning |
|---|---|---|
id | UUID | Unique identifier |
tenant_id | UUID | Tenant they belong to |
email | string | Login + communications |
full_name | string | Full name |
extension | string | SIP extension (3-5 digits) |
role | enum | agent / supervisor / admin / viewer |
status | enum | available / on_call / paused / acw / logged_out |
language | enum | es / en / de / fr / it / pt |
mfa_enabled | bool | Whether MFA is enabled |
Queue
ACD queue. Distributes calls among agents per a strategy.
| Field | Meaning |
|---|---|
id, name, tenant_id | Identification |
strategy | ring-all / longest-idle / round-robin / top-down / fewest-calls / random |
max_wait_time | Seconds before timeout |
wrap_up_time | Automatic ACW after hangup |
moh_url | Hold music |
announce_position | Whether 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:
| Field | Meaning |
|---|---|
queue_id, user_id | Identification |
tier | Priority (1 = primary, 2 = backup) |
level | Sub-priority within tier |
DID
Direct Inward Dial — an inbound number.
| Field | Meaning |
|---|---|
id, tenant_id | Identification |
number | E.164 (+34911234567) |
trunk_id | Trunk via which calls come in |
ivr_flow_id | IVR that runs |
schedule_id | Assigned schedule (optional) |
out_of_hours_ivr_flow_id | Out-of-hours IVR |
outbound_caller_id | Whether allowed as outbound caller ID |
IVR Flow
A call flow. Multiple versions per flow.
| Field | Meaning |
|---|---|
id, name, tenant_id | Identification |
description | Human description |
And per version (ivr_flow_versions):
| Field | Meaning |
|---|---|
flow_id, version | Identification |
is_active | Only one active version per flow |
nodes | JSON with nodes (start, menu, queue, etc.) |
created_at, created_by | Audit |
SIP Trunk
Connection with your phone carrier.
| Field | Meaning |
|---|---|
id, name, tenant_id | Identification |
provider | zadarma / twilio / bandwidth / custom |
host | Registrar SIP host |
username, password_encrypted | Credentials (password AES-256-GCM encrypted) |
allowed_cidrs | Array of allowed IPs/CIDRs |
state | REGED / TRYING / FAIL / NOREG |
failover_trunk_id | Failover trunk (optional) |
Schedule
Business hours and holidays.
| Field | Meaning |
|---|---|
id, name, tenant_id | Identification |
timezone | IANA (Europe/Madrid) |
hours | JSON per day with open/close |
holidays | Array of YYYY-MM-DD dates |
exceptions | One-off exceptions |
Call (CDR)
A call. The highest-volume entity.
| Field | Meaning |
|---|---|
id | UUID |
tenant_id | Tenant |
direction | inbound / outbound / internal |
caller_id_number, caller_id_name | Origin |
destination | Destination |
did_id | DID it came through (if inbound) |
agent_id | Agent who answered (nullable) |
queue_id | Queue it went through (nullable) |
ivr_flow_id | IVR that ran (nullable) |
status | answered / no_answer / busy / failed / abandoned |
started_at, answered_at, ended_at | Timestamps |
duration_sec, billsec | Total and talk time |
hangup_cause | NORMAL_CLEARING, CALL_REJECTED, etc. |
recording_id | If recorded |
transcript_id | If transcribed |
mos_score | Audio quality (1-5) |
salesforce_voicecall_id | If pushed to SF |
Recording
| Field | Meaning |
|---|---|
id, call_id, tenant_id | Identification |
storage_url | Pre-signed URL |
format | wav / mp3 / ogg |
duration_sec, size_bytes | Size |
expires_at | When it’s deleted (policy-sealed) |
provider | sivo_managed / s3 / gcs / azure / minio |
Transcript
| Field | Meaning |
|---|---|
id, call_id, tenant_id | Identification |
provider | deepgram / elevenlabs / whisper |
language | ISO 639-1 (es, en) |
segments | JSON with turns: [{speaker, start, end, text}, ...] |
expires_at | Sealed at creation |
Audit Log
Immutable.
| Field | Meaning |
|---|---|
id, timestamp | Identification |
tenant_id, actor_user_id | Actor |
actor_ip, actor_ua | Origin |
action | create / update / delete / access / login |
resource_type, resource_id | Affected object |
diff | JSONB with before/after |
cross_tenant | If superadmin action |
Identities — external IDs
For integrations, SIVO uses these stable IDs you can save in your systems:
| System | ID to save |
|---|---|
| Salesforce VoiceCall | vendor_call_key (UUID generated by SIVO) |
| Your webhooks | event_id (UUID per event) |
| Your CRM | SIVO’s call_id |
| Your ticketing system | call_id or transcript_id |
All are UUIDs, stable, never reused.
IVR session variables
Variables available in any flow node:
| Variable | Value |
|---|---|
caller_id_number | Origin E.164 |
caller_id_name | Name if carrier sends it |
did | DID it came through |
now | Current UTC timestamp |
language | Expected language |
attempt | N-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
- 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.
- Subscribe to specific webhooks (
call.ended,transcript.completed) instead of polling the API. - Capture IVR variables you need for your BI. Better capture extra than have to reconstruct.
- Document your mapping: which IVR variable maps to which CRM field. Useful as your team grows.
- Annual data-model audit: SIVO adds new fields with each release. Review changelog to leverage them.