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_KEYset (Laravel uses it to encrypt the stored shared secret)
1. Require the package
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
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
php artisan migrate
The package registers its migrations, so a plain php artisan migrate creates three tables — no
migration-publish step is required:
| Table | Purpose |
|---|---|
voicebot_connections | Paired tenant id + encrypted shared secret + ingest URL |
voicebot_sync_state | Per-entity-kind watermark + last full-snapshot timestamp |
voicebot_dead_letter | Delta ops that failed to push, with a bounded attempt counter |
You only need to publish the migrations if you want to edit them. To do that:
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
- Interactive
- Non-interactive (CI)
Pass the code straight to the command:
php artisan voicebot:pair VB-XXXX-XXXX
Set VOICEBOT_PAIR_CODE in the environment and run voicebot:pair with no argument — handy in a
deploy pipeline where you can't type the code:
VOICEBOT_PAIR_CODE=VB-XXXX-XXXX php artisan voicebot:pair
The handshake mints your tenant id and a shared secret, stores them encrypted, and prints the tenant id and ingest URL:
Paired with VoiceBot.
Tenant: 3f9c…-…-…
Ingest: https://api.monoverse.tech
Next: `php artisan voicebot:doctor` then `php artisan voicebot:sync --full`.
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
php artisan voicebot:doctor
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 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:
| Env | Default | Purpose |
|---|---|---|
VOICEBOT_BASE_URL | https://api.monoverse.tech | Ingest base URL (must be https://) |
VOICEBOT_PAIR_CODE | — | Non-interactive pairing (CI) |
VOICEBOT_SITE_URL | APP_URL | Sent as X-VoiceBot-Site-Url on every request |
VOICEBOT_SYNC_CHUNK_SIZE | 200 | Rows pulled per DB chunk while streaming |
VOICEBOT_SYNC_QUEUE | default | Queue connection used by voicebot:sync --queue |
VOICEBOT_DEAD_LETTER_MAX_ATTEMPTS | 5 | Re-fail count before a dead-letter row is flagged exhausted |
VOICEBOT_CURRENCY | UAH | Convenience default for example maps |
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.