🚀Quick Start From Template
Scaffold a new vCon adapter from the official template repo and get a first vCon delivered.
The vcon-adapter-template repo is a GitHub template repository. This page takes you from a source platform that produces conversations to a running adapter delivering vCons over a signed webhook or straight to a conserver. The rules your code must follow are on the Spec Compliance Checklist, and the template's tests enforce them.
Prerequisites
Python 3.12+
uv(recommended) orpipghCLI, or the GitHub web UI for step 1A source platform that exposes conversation data: webhook events, a pollable API, files on disk, or an S3 bucket
Step 1. Create your repo
Pick three names that refer to the same adapter:
Adapter name
kebab-case
foo
Python package
snake_case
foo_adapter
Source platform
human-readable
Foo
gh repo create vcon-dev/vcon-foo-adapter \
--template vcon-dev/vcon-adapter-template \
--public \
--clone
cd vcon-foo-adapterStep 2. Replace the placeholders
In README.md, delete the "What this is" section that explains the template. Keep USAGE.md until you have read it: it holds the lawful basis setup and the finalize_vcon() and json_body() notes.
Step 3. Install and run the tests
The whole test suite should pass before you change anything. A failure at this point means placeholder residue or a Python version mismatch.
Step 4. Wire the source listener
Open src/<your_package>/cli.py and find # TODO: wire your source-platform listener. Pick the shape that fits your source (webhook receiver, polling job, file watcher, batch CLI); the Development Guide has a skeleton for each.
The per-event work looks like this:
external_media_url() computes content_hash with sha512_b64url(). Replace datetime.now() with the time your source says the basis was established when it tells you. If LAWFUL_BASIS is unset, add_lawful_basis() logs one warning and adds nothing; it never invents a basis. See the Extensions Cookbook for what the attachment looks like.
deliver() calls finalize_vcon() for you. If you serialize a vCon anywhere else, such as straight to local storage, call finalize_vcon(v.vcon_dict) first.
Step 5. Configure
Copy config.example.yaml to config.yaml. The file substitutes ${ENV_VAR} at startup, so secrets stay out of it.
<PACKAGE>_API_KEY
Credentials for your source platform
VCON_WEBHOOK_URL
Where to POST vCons (delivery.mode: webhook)
VCON_WEBHOOK_HMAC_SECRET
Shared secret for body signing (delivery.mode: webhook)
CONSERVER_URL
Base URL of a vcon-server (delivery.mode: conserver)
CONSERVER_API_TOKEN
Sent as x-conserver-api-token (delivery.mode: conserver)
LAWFUL_BASIS
One of consent, contract, legal_obligation, vital_interests, public_task, legitimate_interests. Unset means no attachment
LAWFUL_BASIS_PURPOSE
Comma-separated purposes, default recording
LAWFUL_BASIS_JURISDICTION
Optional, for example US-MA
LAWFUL_BASIS_EXPIRATION
Optional ISO 8601 timestamp
LAWFUL_BASIS_PROOF_MECHANISM
Optional, for example external_system
LAWFUL_BASIS_PROOF_DESCRIPTION
Optional free text for the proof
Set delivery.mode to webhook (the default) or conserver. Conserver mode POSTs to {CONSERVER_URL}/vcon with the token header and an ingress_lists query parameter per configured list. Both modes share the retry and dead-letter code (Operational Patterns). Each LAWFUL_BASIS* variable overrides the matching vcon.lawful_basis YAML field.
Step 6. Run it
Step 7. Verify a real vCon
Trigger or simulate an event and check:
The log shows
delivered url=... uuid=...vcons_delivered_totalincrementsA webhook receiver sees
Idempotency-Key: <uuid>andX-Hub-Signature-256: sha256=...; a conserver sees thex-conserver-api-tokenheaderWith the receiver down, vCons land in
dlq/after retries run outThe delivered vCon has a
purpose: "lawful_basis"attachment, or you saw the one-time warning that says why not
Step 8. Publish
Push the repo with git push -u origin main. The template ships one workflow, test.yml (lint, type check, tests on Python 3.12 and 3.13). It has no PyPI publish step, so adding one is up to you.
What to read next
Last updated
Was this helpful?