Build a durable local receipt before connecting a trigger
This lab starts with an actual local HTTP event and finishes with one durable SQLite receipt that remains one receipt after a receiver restart. The complete files include the receiver, sender, synthetic event and seven-case self-test. There is no hidden CRM operation.
The optional native Dispo URL uses the same field names and receiver path as the tested sender. Its VICIdial substitution and delivery must be checked separately on an approved lab; the local test does not establish that a dialer event fired.
You should seeThe target outcome is a stored receipt with a stable identity and explicit replay/conflict behavior.
Step 1 — Choose Dispo and define the bounded event
For this exercise choose Dispo Call URL on one synthetic campaign. The official reference describes it as a server-triggered request when an agent dispositions a call. Start Call URL excludes manual dial calls; choosing the wrong trigger can produce a silent test with no request.
The single-server fixture identifies an event by source TRAINING_A, call_id from the reviewed uniqueid substitution, and event=dispo. The payload also includes numeric lead_id and the disposition. A different topology or correction policy needs a reviewed identity model before deployment.
Sources for this section
- VICIdial Call URL featuresVICIdial · Checked November 6, 2026
Step 2 — Run the self-test and inspect its real result
Extract the complete ZIP into a private local directory, or save the four Python/JSON files there together. Python 3.8 or later with sqlite3 is sufficient; no package install or credentials for VICIdial are required. The test creates its own temporary private state and only contacts loopback.
The receiver validates the token and exact field set, rejects unexpanded variables, and commits the receipt before acknowledging it. The primary key survives a process restart. A changed payload under the same key returns a conflict rather than overwriting the earlier receipt.
- Before you use it
- Download receiver.py, selftest.py and the lab notes together. This command starts temporary loopback listeners, not a remote service.
python3 -B selftest.pyCaptured demo response · 2026-11-06T22:50:57.148463+00:00. Any filtering, hidden values or test-only data are identified in the capture label. Select Replay transcript to read the recorded output.
- Success looks like
- All seven case checks pass, followed by the summary line, including duplicate-after-restart with exactly one ledger row.
- Stop if
- A failed assertion means the relevant behavior is unverified. Inspect local Python/sqlite support and the exact failing case; do not bypass it.
You should seeThe stored, duplicate, forbidden, invalid and conflict results were observed through real local HTTP; they are not fabricated VICIdial responses.
Step 3 — Complete the persistent two-terminal exercise
Run init once, then keep serve running in terminal A. In terminal B run send-example.py twice and inspect the ledger. Stop and restart only this receiver, repeat the sender, and inspect again. Re-running init creates a different exercise and is not a persistence test.
The sender reads the private token file; it does not print the credential or pass it as a shell argument. The expected first response is 201 stored; the repeat and post-restart responses are 200 duplicate. The ledger contains exactly the one fictional event.
- Terminal A: python3 -B receiver.py init, then python3 -B receiver.py serve.
- Terminal B, same directory: run python3 -B send-example.py twice, then python3 -B receiver.py inspect.
- Stop the owned receiver with Ctrl+C. Restart serve without changing its state directory. Repeat send-example.py and inspect.
- Before you use it
- Complete the two-terminal exercise using the same call-url-state directory.
python3 -B receiver.py inspectCaptured demo response · 2026-11-06T22:50:57.465840+00:00. Any filtering, hidden values or test-only data are identified in the capture label. Select Replay transcript to read the recorded output.
- Success looks like
- One row has TRAINING_A / 1700000000.42 / dispo, lead 900001 and SALE. A duplicate request does not add a row.
- Stop if
- If the row is missing, inspect which state directory and receiver you used. A changed disposition for the same identity should conflict, not replace the receipt.
You should seeYou can stop the process and replay the same event without losing the receipt identity.
Step 4 — Review the native URL without confusing hosts or credentials
The included native-dispo-url.txt targets exactly /call-event and supplies every field this receiver requires. Replace its token privately only in an approved single-server lab. Because Dispo originates on the VICIdial webserver, 127.0.0.1 means that server, not the workstation where you ran the local exercise.
Before saving the test field, keep its prior value and verify the receiver runs on the intended same host. Confirm actual variable expansion with a synthetic call/disposition and compare the ledger with the independent call record. An unexpanded or empty identity must be rejected. Restore the prior field after this separate test.
The token is a replayable query credential and can appear in stored URLs or upstream logs. The teaching receiver suppresses its own access log, but that does not protect other logs. Do not put CRM credentials, notes, names or phone numbers into the URL. A public deployment requires a reviewed authenticated/TLS ingress; the loopback HTTP server is not that deployment.
- Before you use it
- Use only the reviewed lab host, install-specific variable reference and a private replacement token. Keep the existing campaign field for recovery.
VARhttp://127.0.0.1:8765/call-event?token=REPLACE_PRIVATELY_WITH_GENERATED_TOKEN&source=TRAINING_A&event=dispo&call_id=--A--uniqueid--B--&lead_id=--A--lead_id--B--&dispo=--A--dispo--B--This sample is a template or reading aid, not a terminal command. There is no output to show.
- Success looks like
- An approved real disposition produces the same field contract and an independently matched durable receipt. This native trigger result has not been captured for this article.
- Stop if
- Do not use the local workstation address as if it were the webserver, publish the query token, or accept literal --A-- markers.
Know exactly which boundary passed
The demonstrated output is one committed local receipt. It does not establish VICIdial retries, event ordering, exactly-once delivery, a CRM write or arbitrary hardware-failure recovery. The seven-case test specifically establishes the observed process-restart behavior.
If a later worker must update a CRM, use a durable outbox and reconcile ambiguous remote outcomes using a reviewed external identity. Receipt storage and the remote acknowledgement are different state transitions. An in-memory Set or an HTTP 200 alone cannot establish them.
Finish with a verified local result and a clean stop
No request in the local ledger: confirm the receiver terminal, loopback port and state directory. Local sender succeeds but native trigger does not: check installed trigger/mode, actual substitutions and the webserver’s route to the receiver. A successful local sender is not a reason to claim the native trigger works.
Stop only the receiver you started. If you separately configured a lab Dispo field, restore its captured prior value. Retain the private receipt ledger for review and retire the test credential before reuse. Do not delete live call records or change unrelated integration fields.
You should seeThe local exercise is complete when one stored row remains one row after identical replay and restart, with rejection/conflict cases passing. Native VICIdial delivery and downstream processing need their own observed checks.
Checks and sources
What was checked
- Seven real loopback HTTP checks passed, including replay after a receiver restart; the observed transcript is downloadable.
- The receiver has no CRM action. The native Dispo template is source-reviewed and matches the local field contract, but no native trigger execution is claimed.
- No native VICIdial Dispo request or completed CRM action was captured. The real demonstrated evidence is the local HTTP/SQLite exercise; a saved URL screenshot would not establish native trigger delivery.
Primary references
Sources
- VICIdial Call URL featuresVICIdial · accessed November 6, 2026
- Python HTTP server limitsPython · accessed November 6, 2026
- Python sqlite3 transaction interfacePython · accessed November 6, 2026