Skip to main content
Version: next

Installation & pairing

From zero to a verified connection in five commands. You will not push any data here — that happens in the first full sync.

Requirements

  • PHP 8.2+ (Laravel 13 requires PHP 8.3+)
  • Laravel 10, 11, 12 or 13
  • An APP_KEY set (Laravel uses it to encrypt the stored shared secret)

1. Require the package

Terminal
composer require monoverse/voicebot-laravel-sync

Laravel package auto-discovery registers the service provider — there is no manual providers entry to add.

2. Publish the config

Terminal
php artisan vendor:publish --tag="voicebot-config"

This writes config/voicebot.php, where you enable entity kinds and map your models. Leave it for now; Mapping covers it in full.

3. Run migrations

Terminal
php artisan migrate

The package registers its migrations, so a plain php artisan migrate creates three tables — no migration-publish step is required:

TablePurpose
voicebot_connectionsPaired tenant id + encrypted shared secret + ingest URL
voicebot_sync_statePer-entity-kind watermark + last full-snapshot timestamp
voicebot_dead_letterDelta ops that failed to push, with a bounded attempt counter
Customising the schema

You only need to publish the migrations if you want to edit them. To do that:

Terminal
php artisan vendor:publish --tag="voicebot-migrations"

Otherwise skip it — the registered migrations run from the package directly.

4. Get a pair code

In your VoiceBot cabinet, generate a one-time pair code. It looks like VB-XXXX-XXXX.

5. Pair

Pass the code straight to the command:

Terminal
php artisan voicebot:pair VB-XXXX-XXXX

The handshake mints your tenant id and a shared secret, stores them encrypted, and prints the tenant id and ingest URL:

voicebot:pair output
Paired with VoiceBot.
Tenant: 3f9c…-…-…
Ingest: https://api.monoverse.tech

Next: `php artisan voicebot:doctor` then `php artisan voicebot:sync --full`.
The shared secret is never printed

voicebot:pair stores the secret encrypted (via Laravel Crypt, keyed by APP_KEY) and never prints or logs it. There is no command that reveals it. If you lose access, re-pair.

Already paired?

voicebot:pair refuses to overwrite an existing connection. To switch tenants, run voicebot:unpair first, then pair again.

6. Verify

Terminal
php artisan voicebot:doctor
Run doctor after every mapping change

voicebot:doctor is the fastest way to catch a broken map before it reaches the backend — it samples a real row per kind and checks the required payload keys without pushing anything.

Doctor is a read-only pre-flight. It checks pairing, backend reachability, and — per enabled kind — a resolvable model, a non-empty map, and that a sampled mapped row carries the backend-required payload fields. It emits one sample record per kind and pushes nothing.

voicebot:doctor output
VoiceBot sync doctor
----------------------------------------
PASS pairing paired (tenant 3f9c…)
PASS backend reachable (provider_status=connected)
PASS entity:product 1240 rows, sample maps cleanly
{"kind":"product","external_id":"laravel:product:42","payload":{"name":"…","price_amount":19999,…}}
PASS entity:category 58 rows, sample maps cleanly

PASS — configuration looks healthy.

Fix every FAIL before syncing. WARN (for example "resolves but has 0 rows") is non-fatal but worth a look — a zero-row kind would make a full snapshot refuse to push. Doctor details are in Operations.

Configuration env vars

All knobs are env-overridable; the defaults live in config/voicebot.php. The ones you are most likely to set:

EnvDefaultPurpose
VOICEBOT_BASE_URLhttps://api.monoverse.techIngest base URL (must be https://)
VOICEBOT_PAIR_CODENon-interactive pairing (CI)
VOICEBOT_SITE_URLAPP_URLSent as X-VoiceBot-Site-Url on every request
VOICEBOT_SYNC_CHUNK_SIZE200Rows pulled per DB chunk while streaming
VOICEBOT_SYNC_QUEUEdefaultQueue connection used by voicebot:sync --queue
VOICEBOT_DEAD_LETTER_MAX_ATTEMPTS5Re-fail count before a dead-letter row is flagged exhausted
VOICEBOT_CURRENCYUAHConvenience default for example maps
https only

The ingest base URL must be https://. Plaintext http:// is rejected (an HMAC over http would leak the signature to a network attacker). localhost / 127.0.0.1 / ::1 are allowed for local development.

Next

  • Map your models — the config-driven Eloquent map and the custom-source escape hatch.
  • Schedule syncs — deltas every few minutes, a nightly full.