vicigeeksimple guides
Browse
All guides

Automate tasks · Schema decision framework

VICIdial custom fields: dynamic tables, APIs and migration safety

Treat list-specific custom fields as runtime schema, then test imports, API writes, backups and list moves without guessing at a table definition.

Reader setup

Before you evaluate

Use this to set expectations, limits and implementation boundaries before changing anything.

  1. A running VICIdial install holding an approved inactive synthetic list
  2. Read-only database access — see vicidial-read-only-database-account if you do not have one yet
  3. The target VICIdial revision, which the Admin screen prints as its VERSION and BUILD line
What you will prove
A documented custom-field test plan and verified schema boundary.
Safety boundary
This article never authorizes production schema or lead changes.

Reader path

How to use this article

  • Use it when: You are designing a change and want reliable limits before implementation.
  • Expected result: Separate what is known, unknown, and unsafe before you execute.
  • Start here: Use it as an evidence review before changing architecture, security, or reporting behavior.

Start with the list, not a guessed column

Fast answer: each VICIdial list (a named lead collection) can have one custom-field set, with definitions in vicidial_lists_fields and values in a dynamically created custom_<list_id> table. An API is an application programming interface: inspect both tables on the target before reading, importing, or changing data.

This is a schema decision deep dive, not an exact Admin UI how-to. Names, types, options and defaults are generated at runtime, and the demonstrated system has source support but its custom-fields feature flag is disabled. Source presence is evidence of implementation, not proof that a target has enabled or configured it.

Terms are defined in vicidial-terminology-for-complete-beginners.

  • Prerequisite: use an authorized read-only database account and an inactive synthetic test list.
  • Non-goal: do not alter production definitions, values, imports or schema from this article.
  • Record revision, database engine/version, timezone and authorized test-list ID.
  • Capture sanitized SHOW CREATE TABLE and SHOW INDEX output.
Trace path · read left to right
01List definition02custom_<list_id>03verified lead workflow

Visual walkthrough

Follow three real demo screens

Captured on an isolated VICIdial demo: Administration screens on September 24, 2026, and the idle Agent screen on August 11, 2026. Each caption states its own capture time, and every sanitized image helps you recognize a related screen; none proves that this article's call, command, or result occurred.
Step 1 · Confirm campaign context

Identify the owning campaign

Sanitized VICIdial Campaign Listings page showing only the fixture campaign row
Captured September 24, 2026 at 21:39:47 UTC on the authorized isolated demo. Only the fixture campaign row is shown; other campaigns are removed. Its columns do not prove dialing activity, performance, or a completed call.
Step 2 · Open Lists

Find the Lists workspace

Sanitized VICIdial List Listings page showing only the fixture list row
Captured September 24, 2026 at 21:53:00 UTC on the authorized isolated demo. Only the fixture list row is shown; other lists are removed. This page locates list administration and does not display a lead, caller, or campaign result.
Step 3 · Read list settings

Inspect one list without opening a lead

Sanitized VICIdial list detail page showing list state, reset, time, script, and URL override settings
Captured August 11, 2026 at 16:21:03 UTC on the authorized isolated demo. This is list configuration rather than a lead record; it contains no customer row and does not prove a dialing or import result.

Design fields as an interface contract

Choose stable field names, bounded values and explicit required/default behavior before an import template or downstream integration exists. A label is for people; a field name becomes a dependency for loaders, forms, exports and any approved API client.

Use the card below in a change ticket before creating a test field. FIELD_NAME is a stable machine-readable name, TYPE is the approved input type, and SENSITIVE is a data-classification decision. Success is a complete, owner-approved card; a blank owner, retention rule or allowed value means stop before configuration.

Avoid placing secrets, payment data, health data or free-form sensitive notes into call URLs or casually exported custom fields. Document ownership, retention and masking before a field becomes operationally relied upon.

  • Validate label, field name, type, options, length and default in a test list.
  • Test agent display and approved webform/script consumers.
  • Have the privacy owner approve any sensitive-data purpose.
Worked field-design card
FIELD_NAME: preferred_contact_windowTYPE: SELECTALLOWED_VALUES: morning | afternoonSENSITIVE: noOWNER: operationsRETENTION: approved policy reference
Not executed · worksheet or reference text

This sample is a template or reading aid, not a terminal command. There is no output to show.

Before you run it
Copy into the test-list change ticket; replace each all-caps label with an approved non-sensitive value.
Success looks like
Every field has a type, owner and retention decision.
Stop if
Stop and escalate when any value, owner or retention rule is unknown.

Prove the write path with synthetic data

Use the documented Non-Agent API function and target revision rather than constructing parameter names from a database column. API behavior, permissions and output modes vary by function; a successful HTTP response is not enough evidence of the intended custom-field write.

Start on an inactive test list with a synthetic lead, then verify the standard lead record, the matching custom row and the agent-facing result. URL-encode values at the client boundary and treat plain-text ERROR responses as failures even when a requested format is JSON.

Read-only schema gate
SHOW CREATE TABLE vicidial_lists_fields;SHOW CREATE TABLE custom_<LIST_ID>;SHOW INDEX FROM custom_<LIST_ID>;
Evidence · ViciBox 12 demo capture · demo values substituted

Captured demo response · 2026-09-24 22:25 UTC. The displayed command is the command that ran; a safe subset label means it was filtered, redacted, or fixture-scoped. Replays only after you select Replay transcript.

Command output line: SHOW CREATE TABLE vicidial_lists_fields;
+-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| vicidial_lists_fields | CREATE TABLE `vicidial_lists_fields` (
`field_id` int(9) unsigned NOT NULL AUTO_INCREMENT,
`list_id` bigint(14) unsigned NOT NULL DEFAULT 0,
`field_label` varchar(50) DEFAULT NULL,
`field_name` varchar(5000) DEFAULT NULL,
`field_description` varchar(100) DEFAULT NULL,
`field_rank` smallint(5) DEFAULT NULL,
`field_help` varchar(1000) DEFAULT NULL,
`field_type` enum('TEXT','AREA','SELECT','MULTI','RADIO','CHECKBOX','DATE','TIME','DISPLAY','SCRIPT','HIDDEN','READONLY','HIDEBLOB','SWITCH','SOURCESELECT','BUTTON') DEFAULT 'TEXT',
`field_options` varchar(5000) DEFAULT NULL,
`field_size` smallint(5) DEFAULT NULL,
`field_max` smallint(5) DEFAULT NULL,
`field_default` varchar(255) DEFAULT NULL,
`field_cost` smallint(5) DEFAULT NULL,
`field_required` enum('Y','N','INBOUND_ONLY') DEFAULT 'N',
`name_position` enum('LEFT','TOP') DEFAULT 'LEFT',
`multi_position` enum('HORIZONTAL','VERTICAL') DEFAULT 'HORIZONTAL',
`field_order` smallint(5) DEFAULT 1,
`field_encrypt` enum('Y','N') DEFAULT 'N',
`field_show_hide` enum('DISABLED','X_OUT_ALL','LAST_1','LAST_2','LAST_3','LAST_4','FIRST_1_LAST_4') DEFAULT 'DISABLED',
`field_duplicate` enum('Y','N') DEFAULT 'N',
PRIMARY KEY (`field_id`),
UNIQUE KEY `listfield` (`list_id`,`field_label`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci |
Before you run it
Run through the read-only credential file (mysql --defaults-extra-file=/etc/vicidial-readonly.cnf -e "..."; see vicidial-read-only-database-account if you do not have one yet); replace <LIST_ID> with its approved numeric list ID.
Success looks like
The custom table definition and indexes match the approved test-field design.
Stop if
Stop if the table is absent, belongs to another list, or differs from the plan.

Make list copies and renumbers real migrations

Copying a list or changing its list ID changes the schema relationship as well as lead membership. Inventory definitions, values, import mappings, exports, callbacks, campaign eligibility and any external consumer before moving a production population.

Build a deterministic mapping from old list and field names to new list and field names. Rehearse the mapping on synthetic data, compare non-sensitive counts and field null rates, and stop if the target schema differs from the approved plan.

  • Freeze or isolate the test population during the rehearsal.
  • Validate an import, an API update and an agent edit after migration.
  • Keep the original list untouched until acceptance is complete.

Back up both halves and define the stop point

A lead-table backup without the dynamic table, definitions and mappings is incomplete. Take a restorable, access-controlled backup and verify restoration into an isolated environment before a broad alteration or migration.

Stop and roll back when schema comparison, expected counts, sample reads or agent rendering disagree. Independent verification means a reviewer who did not perform the change compares the approved mapping, backup evidence and sanitized before/after totals.

  • Include definitions, custom tables and relevant loader mappings in backup scope.
  • Record evidence state: source present, demo enabled/disabled, or independently tested.
  • Run equivalent tests on every production revision and list family before rollout.

Evidence ledger

Verification basis

  • In this lab, custom fields are list-scoped dynamic tables (vicidial_lists_fields plus custom_<list_id>); the feature was present but not enabled at the time of writing.
  • No production custom-field rows, credentials, backups or migration result counts were reviewed for this article.

Primary references

Sources

  1. VICIdial Custom FieldsVICIdial · accessed September 23, 2026
  2. VICIdial Non-Agent APIVICIdial · accessed September 23, 2026

Follow without guesswork

Get the next article

RSS is live now. Email delivery below is an explicit local preview and sends nothing.Open the RSS feed
Email preview only. The address stays in this browser and is never transmitted.