A Campaign organizes outbound telephone activity around a specific message, caller ID, Contact audience, human Agent, AI Agent, recording preference, concurrency level, retry policy, and launch schedule.
The standard Campaign process is:
AIUNIFY Call Center supports standard browser Campaign routes for creating, viewing, editing, launching, pausing, resuming, deleting, uploading Campaign Contacts, opening a manual Call Queue, and placing an On-Demand test Call.
Campaign routes are protected by the Basic KYC middleware.
When KYC is enabled, a Customer generally requires:
Administrators and Agents follow the KYC exceptions described in Chapter 2.
Campaign access can require:
A visible Campaign action does not guarantee that the backend will authorize it.
An Administrator can generally:
provided the corresponding permissions are assigned.
A Customer can generally manage Campaigns whose:
An Agent can view and execute only Campaigns whose:
The Campaign policy does not permit Agents to edit or delete Campaigns.
The Campaign cards determine which buttons to display primarily from Campaign Status.
They do not consistently hide Edit and Delete according to the signed-in user’s permission.
An Agent assigned to a Draft Campaign can therefore see an Edit or Delete control that the backend later rejects.
From the Sidebar:
The page address is:
The page contains:
The backend returns:
Although the controller paginates Campaigns, the current Campaign index does not render its pagination links.
When more than fifteen Campaigns exist, only the first page may be accessible through the normal Campaign interface.
The Campaign model supports:
A Draft Campaign is saved but has not entered normal automated processing.
A Draft can generally be:
A Scheduled Campaign has a future scheduled_at value and is intended to begin automatically.
Current scheduling defects are explained later in this chapter.
A Running Campaign is eligible for automated processing.
Campaign-processing jobs look for:
A Paused Campaign stops new Campaign-processing jobs from initiating additional Calls.
Already initiated provider Calls are not canceled merely because the Campaign Status changes to Paused.
A Completed Campaign has no remaining Pending or Queued Campaign Contacts and no active Campaign Call records.
A Campaign can complete even when some Contacts failed.
Failed indicates that the Campaign-processing job encountered a terminal job failure.
The model permits a Failed Campaign to transition back toward Draft, but the normal user interface does not provide a dedicated Restart or Reset-to-Draft control.
The Campaign list displays filters for:
The index does not include a Scheduled filter.
More importantly, its frontend Status configuration does not define scheduled.
Because the Campaign card directly reads the missing Scheduled configuration, the presence of a Scheduled Campaign can cause the Campaign list to render incorrectly or fail with a frontend error.
The Campaign Details page does recognize Scheduled Status, but the Campaign index currently does not.
Each Campaign card displays:
Progress is calculated as:
The platform increments total_called when a Call first reaches:
A Call attempt that ends as Busy, No Answer, Failed, or Canceled without first reaching In Progress may not increase Total Called.
A Campaign can therefore finish while its visible progress remains below 100%.
Answer Rate is calculated as:
Total Answered is incremented when:
A completed Call can fail to increase Total Answered when the provider does not supply a usable AnsweredBy value.
Select:
or open:
The page description is:
The current form contains:
The template selector contains:
Template categories can include:
Selecting a Template can prefill:
Although Template data can contain DTMF Actions, the current Create page does not copy those Actions when applying the Template.
It applies only the general DTMF enabled value.
Selecting another Template replaces portions of the current Campaign form.
Review the Campaign Name, message, voice, recording, and DTMF values after changing Templates.
Existing Contact Lists appear with:
One or more Lists can be selected.
The form adds the displayed Contact counts from each selected List.
This preview does not account for the same Phone Number appearing in more than one selected List.
The final Campaign import skips duplicate Phone Numbers within the Campaign.
When the Campaign is created, the system copies each selected master Contact into a Campaign Contact.
The copied information includes:
The current List attachment process does not copy:
This can limit personalization and compliance traceability.
A selected List should be reviewed before use to confirm that only contactable people are included.
The form normally shows only the current user’s Contact Lists.
The backend validates that submitted List IDs exist, but it does not consistently verify that every selected List belongs to the Campaign owner.
Users should never modify submitted List IDs manually.
A Customer can optionally select an active Agent belonging to that Customer.
An Administrator can select from active Agent-role users more broadly.
Leaving the Agent field blank creates an unassigned Campaign.
An unassigned Campaign can still run automatically.
The assignment controls:
It does not convert the automated Campaign into a human-only Campaign.
The form provides:
on Create and Edit when an Agent has been selected.
Campaign Name is required.
Maximum length:
Use a descriptive Name such as:
The two standard types are:
Text to Speech converts the saved Campaign message into provider-generated speech.
It supports:
Voice to Voice plays a previously uploaded Audio File.
Despite its name, the current standard implementation is prerecorded audio playback rather than a live human voice conversation.
When the selected Phone Number is attached to an active AI Agent, the Campaign automatically stores that AI Agent.
During automated Campaign processing, the AI Agent path takes priority over:
A Phone Number is required before normal Campaign launch.
Selecting:
forces a newly created Campaign to Draft, even when the user selected Immediate or Scheduled launch.
The Create page currently retrieves Phone Number records that:
SIP-only or BYOC-only numbers without a Twilio SID are not displayed in this selector.
The selector can display:
When an active AI Agent has the exact selected Phone Number, the Campaign stores that Agent’s ID.
The page displays:
When editing and selecting a number with an active AI Agent, the Campaign is assigned to that Agent.
When selecting a number without an AI Agent, the update process clears the Campaign’s AI Agent.
When the Phone Number is changed to None, the Campaign’s phone_number_id can be cleared.
However, the current update logic does not reliably clear the previous:
when the submitted Phone Number is null.
The Campaign can therefore retain an old caller ID or AI Agent internally after the visible Phone Number is removed.
The backend validates only that phone_number_id exists.
It does not explicitly confirm in the Campaign store/update validation that the Phone Number belongs to the Campaign owner.
Use only numbers displayed by the normal selector.
A Text-to-Speech Campaign must have a Message before it can be launched through the normal Launch action.
The backend limit is:
The Message editor displays a counter but does not prevent typing beyond 250 characters.
A message longer than 250 characters is rejected when the form is submitted.
The counter changes emphasis as the Message approaches its limit:
Built-in Contact variables include:
Campaign variables use one shared value across all Campaign Contacts.
Example:
Contact variables can have a different value for each Campaign Contact.
Example:
The values normally come from Campaign Contact custom variables imported from CSV.
Custom variable names must begin with:
and can contain:
Example:
Variables must use double braces:
The AI Agent greeting system uses a different single-brace syntax for its own First Message:
Do not mix the two formats.
The Campaign TTS handler replaces:
The editor warns when a variable is used but not defined.
The normal Launch action does not independently reject every undefined Contact variable.
A missing variable can remain in the Message sent to the TTS processor.
The Launch action checks Campaign variables used in the Message.
When a used Campaign variable has no value, launch is rejected with an error similar to:
The interface can define expected Contact variables, but normal Launch does not verify that every Campaign Contact contains every expected value.
Review CSV data before launch.
The Message editor offers:
The user describes the intended message, and the application requests a generated version.
The editor also offers:
The service is instructed to preserve variables and remain within the 250-character limit.
AI Message assistance requires the configured AI messaging service.
When the provider or API key is unavailable, the dialog displays the returned error and does not replace the current Message.
Before using an AI-generated Message, confirm:
After a Text-to-Speech Campaign is created, its Edit page can offer AI-generated Message Variants.
The Create page describes five possible tones:
When active Variants exist:
The system initially favors random distribution and later applies a limited performance weighting.
When no active Variant exists or Variant selection fails, the Campaign’s default Message is used.
Visible language choices include:
Visible voices include:
The interface does not automatically restrict each Voice to a matching Language.
Test the selected Voice and Language combination before production use.
Voice-to-Voice Campaigns require an uploaded Audio File.
The selector displays Audio Files owned by the signed-in user.
When none exist, the form directs the user to:
to upload one.
The normal Launch action rejects a Voice-to-Voice Campaign without an Audio File.
The provider must be able to reach the Audio File’s URL.
A file can appear in the selector yet fail during a Call when its public playback URL is inaccessible.
The user can enable Call Recording for Campaign Calls.
Recording is passed into Campaign Call creation and provider configuration.
Consent, disclosure, retention, and access rules remain the Customer’s responsibility.
The general Campaign Settings section contains an Enable DTMF checkbox.
A separate DTMF Settings Card also contains another Enable DTMF checkbox.
Both control the same form state.
The interface describes a range of:
The backend accepts only:
Values from 51 through 100 are displayed as permitted by the form but rejected by server validation.
The interface describes:
The backend accepts:
The visible field prevents ordinary users from entering the backend’s higher supported values.
The interface allows:
The backend accepts only:
A value above 60 is rejected at submission.
The Create page initially uses:
The backend model-level creation defaults differ slightly in some cases, but the form values are submitted for normal browser creation.
DTMF allows the recipient to press keypad digits in response to a Campaign message.
Visible configuration includes:
The interface offers:
The backend can store:
Campaign Details can display DTMF response Analytics when usable configuration and responses exist.
The Create and Edit actions currently save the general:
flag, but they do not persist the detailed DTMF configuration displayed by the form.
The current Campaign actions omit:
from the Campaign create and update operations.
Even the controller validation does not preserve the visible DTMF Action value field used for:
The DTMF interface therefore overstates what is currently saved.
Do not rely on custom DTMF Actions until the create and update actions are corrected and tested.
The Create page offers:
Draft is the safest option for a new Campaign.
It allows the user to:
The interface states that Calls will begin as soon as the Campaign is created.
The current implementation instead creates the Campaign directly with:
Immediate creation does not call the normal LaunchCampaignAction.
It therefore does not apply the normal launch checks for:
A Campaign can be created as Running without passing the same checks required by the normal Launch button.
Immediate creation does not directly dispatch the Campaign-processing job.
The application scheduler searches for Running Campaigns every minute and dispatches processing.
“Launch Immediately” can therefore wait until the next scheduler run.
When an Immediate Campaign has no Contacts, the processing job can find no work and mark the Campaign Completed.
The Campaign can therefore move:
without placing a Call.
Selecting Schedule for Later reveals:
The browser requires a value at least approximately five minutes in the future.
The backend requires:
during creation.
The interface says the Campaign starts in:
However, the browser submits a datetime-local value without a time-zone offset, and the current Laravel application Time Zone is UTC.
The server can interpret the entered clock time as UTC rather than the user’s local Time Zone.
A scheduled time entered as 9:00 AM Eastern can therefore be stored incorrectly.
The application scheduler checks for due Scheduled Campaigns:
A server cron process must run Laravel’s scheduler for this to occur.
The scheduler sends each due Scheduled Campaign into the normal Launch action.
That Launch action accepts only:
It rejects:
with:
Consequently, Scheduled Campaigns cannot currently auto-launch successfully through the reviewed scheduling path.
The Campaign Details page displays Edit for a Scheduled Campaign that has not started.
The update action permits updates only when Status is:
Saving changes to a Scheduled Campaign can therefore fail with:
The current Edit page does not display:
There is no normal working reschedule workflow in the current interface.
Until scheduling is corrected:
The Create button changes according to launch choice:
On success:
appears and the Campaign Details page opens.
When no Phone Number is selected, creation forces:
even when the visible choice was Immediate or Scheduled.
Select View on a Campaign card.
The page address is:
Depending on Status, assignment, and activity, the page can display:
While the Campaign Status is Running, the page reloads Campaign information approximately every:
A separate Refresh icon appears for Running Campaigns.
The Details page displays:
The page can show:
The backend loads only the latest:
for the Campaign Details tabs.
The totals can be larger than the visible records.
There is no pagination in these two Details tabs.
Campaign Contacts can be added through:
The application contains a Campaign Contact Manager component and backend routes for:
The current Campaign Details page does not mount that manager.
The visible normal workflow provides CSV upload and Contact Lists, but not a manual Add Contact form.
A Phone Number can appear only once within the same Campaign through the standard Add and CSV processes.
Duplicate checks are based on the formatted Phone Number.
Open Campaign Details and select the Contacts tab.
The Upload Contacts Card supports:
Use:
Although the first controller validation permits CSV or text MIME types, the import action requires the file extension to be .csv.
The exact required header is:
Header names are converted to lowercase and trimmed.
Supported standard fields include:
Although Website is accepted during validation, it is neither saved as a Campaign Contact field nor retained as a custom variable.
Website data from this Campaign upload is effectively discarded.
Additional CSV columns are stored in the Campaign Contact’s:
JSON field.
Example:
The custom values can be used as:
Each row can be skipped for reasons such as:
The Campaign CSV import:
Use complete E.164 numbers for international Contacts.
CSV-uploaded Campaign Contacts are not automatically linked to master Contacts through contact_id.
They remain Campaign-specific records.
This can limit:
The import runs inside one database transaction.
A fatal unexpected exception rolls back the import.
Individual invalid rows are skipped without rolling back valid rows.
The page displays:
The Upload Card links to:
The reviewed source contains the link, but the source bundle does not confirm the actual public sample file.
When the button returns Not Found, create a CSV using the required headers documented above.
The Details page displays Edit for:
The Campaign list displays Edit only for Draft.
The actual Update action accepts:
It rejects every other Status.
Paused Campaigns are technically accepted by the backend Update action.
The normal Campaign list and Details page do not display Edit for Paused Campaigns.
The current Edit form includes:
The Edit page does not expose:
When changing from Text to Speech to Voice to Voice, select a valid Audio File.
When changing back to Text to Speech, enter a valid Message.
The Update action itself does not perform the same content requirement checks as Launch; those are applied later when launching.
Draft Campaigns display:
Selecting it opens a confirmation:
The normal Launch action requires:
The Launch action does not directly confirm:
These issues can appear later during processing.
Launch updates:
It dispatches:
The production runtime uses:
Queued Campaign jobs therefore execute in the process that dispatches them rather than through independent background workers.
This reduces the practical value of separate Campaign and Campaign-Call queues and can make launch or scheduler execution take longer.
The Campaign processor:
It fetches up to:
Pending Contacts at a time.
Available slots are calculated as:
The system models concurrency through active Call counts.
Because the current queue driver is synchronous, it does not provide the same parallel background execution expected from dedicated queue workers.
The active processing system uses statuses including:
Other workflows also write values such as:
The Campaign Contact Status vocabulary is not fully consistent across components.
Before an automated Campaign Call, the job checks whether the Customer can afford:
This is a fixed preliminary threshold, not the final duration-based Call price.
When the Customer cannot afford 1.0 Credit:
The job sanitizes and validates each Campaign Contact Phone Number before calling.
An invalid number is marked Failed and no Credit is deducted for that invalid-number rejection.
Automated Campaign processing looks for the Campaign owner’s:
This is different from merely having a global Twilio configuration.
A Campaign can appear properly configured but fail because the owner has no expected credential record.
Errors containing concepts such as:
are treated as critical.
The Campaign is Paused.
A noncritical initiation failure marks the Campaign Contact and Call as Failed and continues processing other Contacts.
When ai_agent_id exists, the automated job uses the AI Agent Campaign endpoint.
Without an AI Agent, Text to Speech uses the Campaign TTS endpoint.
Without an AI Agent, Voice to Voice uses the Audio playback endpoint.
An assigned AI Agent must remain:
When the Agent is missing or inactive, the recipient receives a fallback error message and the Campaign Contact can be marked Failed.
The AI Agent’s First Message can personalize:
The static Campaign TTS Message uses double braces instead.
When Campaign Recording is enabled, the Call record stores that preference and the provider receives a recording instruction.
Recording availability still depends on provider callbacks.
When DTMF is enabled, the Campaign route provides a DTMF callback.
Because the detailed DTMF configuration is not currently saved by Create or Edit, the recipient may not receive the intended custom prompt or Action behavior.
After a Campaign Call is successfully initiated, the job deducts:
with a description such as:
When the provider later marks a Call Completed with positive Duration, the Call Status action calculates duration-based pricing and attempts another Credit deduction.
The reviewed source contains two independent Call debit paths:
The completion idempotency check looks for:
The initial fixed Campaign debit does not store that same metadata field.
This creates a likely double-debit path for successfully completed automated and On-Demand Campaign Calls.
Review Account Statements closely and correct the billing logic before large Campaign use.
Failed Calls can return their Campaign Contact to Pending while attempts remain.
The next attempt is scheduled after the configured Retry Delay.
With the current synchronous queue driver, delayed queue behavior should be tested rather than assumed to operate like a persistent worker queue.
The Campaign Call job increments call_attempts when a Call is successfully initiated.
The final Call-status handler can increment it again after Busy, No Answer, Failed, or Canceled.
One provider attempt can therefore increase the stored attempt count more than once.
Because of the multiple increment paths, the visible Retry Attempts value may not equal the exact number of telephone attempts made.
The processor checks Campaign Contacts stuck In Progress for more than approximately:
It reviews their latest Call and either:
depending on provider state and remaining attempts.
A Campaign is marked Completed when:
Failed Campaign Contacts are terminal for the completion check.
A Campaign can be Completed with:
The application dispatches a Campaign Completed event when normal processing finishes.
The normal browser interface provides no Resume or Relaunch action for Completed Campaigns.
Create a new Campaign for a selective retry audience.
Running Campaigns display:
The confirmation explains that the Campaign can be resumed later.
Pause changes:
Campaign-processing and Call jobs check that the Campaign remains Running.
A queued job encountering a Paused Campaign resets its Contact to Pending and does not initiate the Call.
Pause does not explicitly:
Automatic pauses caused by insufficient Credits or critical provider errors set:
The manual Pause action changes Status but does not set paused_at.
Paused Campaigns display:
Resume changes:
and dispatches Campaign processing again.
Confirm:
Resume does not clear:
It continues from the remaining processable Campaign Contacts.
Campaign Details contains:
The confirmation describes it as a way to immediately call the next Pending Contact without using the Campaign Queue.
The button appears for Campaigns that are not:
This includes:
An On-Demand Call can therefore occur before formal Campaign launch or while the Campaign is Paused.
On-Demand selects:
The user cannot choose a specific Contact through this button.
The route checks:
Before initiating, the Contact changes to:
and its attempts increase.
The created Call is stored as:
The On-Demand route chooses only:
It does not check ai_agent_id.
An On-Demand Call does not test the Campaign’s AI Agent conversation path.
After provider initiation succeeds, the route immediately deducts:
The completion-based pricing path can later attempt another debit, producing the same likely double-charge risk described earlier.
When initiation fails:
An unexpected exception resets the Campaign Contact to Pending.
Use On-Demand only for:
Do not use it as a replacement for selecting an arbitrary production Contact.
Campaign Details displays:
when:
This Queue is a guided human-Agent calling interface.
It does not represent the same automated job queue used by Running Campaigns.
The page displays:
Call Now requires:
The button loads the Campaign Contact into the global browser Softphone.
The backend loads at most:
into the manual Queue.
A Campaign with more than 200 Contacts has no visible pagination in this Queue.
The backend attempts to order statuses as:
Automated Campaign processing uses:
while the manual Queue expects:
The Queue’s Calling statistic can therefore show zero even when Contacts are Queued or In Progress.
Unrecognized statuses can also appear in an unexpected order.
Manual Queue progress is:
This differs from the Campaign card’s total_called progress.
Skip moves to the next visible Campaign Contact.
It does not update the Contact’s database Status to Skipped.
After a Post-Call Disposition is successfully saved, the Queue tries to move to the next Pending or Failed Contact.
Do not run both workflows on the same Campaign audience without a controlled operating plan.
Campaign Details provides this action for all Campaign Statuses.
The dialog contains:
Available categories include:
Saving as a Template saves Campaign configuration, not the Campaign Contact audience or Call History.
Delete appears for:
The Delete action permits the same three Statuses:
When deletion is attempted in another Status, the backend states:
Paused Campaigns are still not allowed to be deleted.
The Campaign must be Draft, Completed, or Failed.
Campaigns use soft deletion.
Normal deletion records a deleted timestamp and removes the Campaign from ordinary queries.
The Delete action comments that database cascades will handle Contacts and Calls.
A soft delete does not trigger normal database hard-delete cascades.
Campaign Contacts and Calls can remain stored and linked to the soft-deleted Campaign.
The model supports restoration in policy, but the normal Campaign interface does not display a Restore action.
Confirm:
Confirm:
Use:
Do not simultaneously use:
on the same Contact audience without coordination.
Review:
during the first several Calls.
Campaign Name is required and cannot exceed 255 characters.
The Message may exceed 250 characters.
The interface counter does not prevent excess typing.
The UI allows up to 100, but the backend limit is 50.
The UI allows up to 1,440 minutes, but the backend limit is 60.
No Phone Number was selected.
Creation forces Draft when phone_number_id is empty.
The selected Phone Number has an active AI Agent attached.
The system automatically assigns that Agent to the Campaign.
The same Phone Number appears in multiple Lists.
The Campaign skips duplicate Phone Numbers.
The Contact List attachment process does not copy Company into the Campaign Contact.
Upload Campaign Contacts through CSV with the required Company value or correct the List-copy logic.
Contact List attachment does not currently preserve contact_id.
The Campaign Contact may not be linked back to the master Contact.
Use the exact header:
Use a file ending in:
Maximum size is 5 MB.
The import intentionally stops after 10,000 parsed Contact rows.
The formatted Phone Number already exists in the Campaign.
The Campaign upload validates Website but discards it.
Confirm:
The current scheduler calls a Launch action that rejects Scheduled Status.
Launch the Campaign manually after reviewing its intended start time.
The Campaign index does not define the Scheduled Status configuration.
Open the Campaign Details URL directly or have the frontend configuration corrected.
The browser labels the entry as local time, but the server currently operates in UTC and receives no explicit offset.
The Edit page permits opening it, but the update action rejects Scheduled Status.
Normal Launch requires at least one Campaign Contact.
Enter and save a Campaign Message.
Select an existing Audio File for Voice-to-Voice.
Enter a value for every Campaign variable used in the Message.
Check:
It may have contained no Pending Contacts.
Likely causes include:
Pause stops new job processing.
Already initiated provider Calls can continue.
Review Campaign Contacts that returned to Pending through retries or stale-Call recovery.
The backend permits Paused updates, but the normal interface does not show Edit.
The On-Demand route calls only the first Pending Contact.
The Campaign owner lacks the credential record expected by the On-Demand service.
On-Demand currently tests TTS or Audio playback, not the Campaign AI Agent route.
Review the Account Statement for:
Report duplicate Campaign Call charges to the Administrator.
The Campaign must:
The browser Softphone is not Registered or another Call is active.
The Queue looks for calling, while automated processing commonly stores queued or in_progress.
The Queue loads only the first 200.
Use focused Campaigns or improve Queue pagination.
Skip only advances the browser’s current position.
It does not save skipped to the database.
Confirm:
Confirm:
Confirm:
Confirm:
Confirm:
Confirm:
Confirm:
Confirm:
Confirm:
Confirm:
The reviewed Campaign implementation currently includes these important limitations:
At the end of this chapter, the user should understand how to create and configure a Campaign, select Contact Lists, assign a human Agent, choose a Phone Number, and distinguish among:
The user should know how Campaign variables and Contact variables work, how static Campaign TTS replaces double-brace placeholders, and why AI Agent greetings use single-brace placeholders.
The user should understand the normal Campaign Statuses:
and recognize that Scheduled Campaigns are not currently dependable because the scheduler sends them into a Launch action that rejects Scheduled Status.
The user should understand how normal Launch validates Contacts, Messages, Audio Files, and Campaign-variable values, while Create & Launch bypasses those normal checks and relies on the scheduler to begin processing.
The user should understand how Campaign-processing jobs validate Credits and Phone Numbers, choose between AI Agent, TTS, and Audio routes, control active Call slots, apply retries, recover stale Contacts, and mark a Campaign Completed.
The user should know the difference between:
and should avoid using all three workflows simultaneously on the same audience.
The user should understand how to Pause and Resume a Campaign and know that Pause prevents new jobs from starting Calls but does not terminate Calls already initiated.
The user should recognize the likely Campaign billing defect in which one fixed Credit can be deducted at initiation and a second duration-based charge can be deducted after completion.
Most importantly, the user should follow this operating sequence: