Skip to main content

Export conversations as signed IETF vCon containers

The IETF vCon working group is standardising a container for conversation data: parties, dialog, attachments, analysis, and a signature, all in one JSON document. Orbit adopts that container as its canonical conversation export envelope. One API call turns any conversation in your workspace into a standards-conformant file you can hand to another AI system, a carrier, or a compliance archive — and the recipient can verify it was never altered. Use the vCon export when a plain CSV or JSON dump is not enough:
  • Hand a support thread to an external AI system that reads vCon directly, with the message order and party roles intact.
  • Deliver a thread to a compliance archive as a tamper-evident artifact, not a spreadsheet anyone can edit.
  • Prove to the recipient that the export came from your workspace — with your masking preferences already applied.
The Conversation archive guide covers the CSV/JSON bulk export for filtered result sets. The vCon export is the per-conversation, signed counterpart; request it over the API.

Why a signed container

A CSV row can be edited after the fact and no one can tell. A vCon is signed at export time, and the signature binds the exact bytes of the parties, dialog, attachments, and analysis sections. If a recipient changes so much as one character, the signature no longer verifies. The container also mints a fresh, tamper-evident uuid per export, so the artifact is addressable without exposing the internal conversation id.

Export a conversation

Call GET /conversations/:id/vcon with an API key that has conversation read access (conversations:read — the same scope the inbox and archive use):
The response is a JSON document with an exported_at date stamp and the signed container under vcon. Every export is recorded in your audit log, and the Content-Disposition header names the download conversation-<id>-<date>.vcon.json.
A 404 means no conversation with that id exists in your workspace. The export is read-only — it issues no outbound traffic of any kind.

Container anatomy

Verifying the signature

Orbit signs with a symmetric HMAC-SHA256 scheme labelled Orbit-HS256, using the same platform signing secret that protects your share links and CSAT tokens. This is an honest choice, not a shortcut: the platform’s keyring holds an HMAC secret rather than an Ed25519 keypair, so a symmetric scheme is what the signature genuinely is. The consequence to plan around: verification requires the shared secret, so the verifier is a party you have shared that secret with — it is not public-key verification anyone can run. The signed surface covers the payload_b64 string itself, so stripping the signature from the file yields an invalid artifact rather than an “unsigned but valid” one. Verification also requires the signed payload’s uuid to match the container’s top-level uuid, which defeats a substitution attack that swaps in another validly-exported payload. To verify by recompute:
Recompute the HMAC over payload_b64, compare it with signature, and then confirm the decoded payload’s uuid matches the container’s top-level uuid. Reject anything that fails either check. The same symmetric verification is available inside the platform for re-import; it never throws, so a tampered artifact simply returns false.

PII masking before signing

If you have turned on transcript PII redaction in your workspace privacy settings (pii_redaction_in_transcripts), the export applies the standard PII scan to every dialog body and to the party phone/email addresses before the signature is computed. The exported artifact never carries cleartext values you opted out of storing in transcripts. Two consequences worth understanding:
  • The signature binds the masked bytes, so a masked export verifies against what a recipient actually sees. There is no “cleartext version” of a masked export — masking is not a view.
  • The flag fail-opens: if the setting cannot be read (for example a transient cache failure), the export proceeds unmasked, matching the default-off posture of the setting. If your archive requires masked exports, enable the setting before you export.

Import and handoff

A vCon is a complete handoff artifact: parties identify whose thread it is, dialog preserves the message order sender-by-sender, attachments carry the operational context (channel, status, tags), and the signature lets the recipient confirm none of it drifted in transit. Typical flows:
  • Compliance archive — export on a schedule or per request, push the file into your archive, and let the archive recompute the HMAC against the secret you provisioned there. A file whose signature fails is quarantined, not ingested.
  • External AI system — hand the container to a vCon-aware system for case migration or second-opinion analysis. Party roles and the oldest-first dialog survive the move; the per-turn meta gives the receiving system channel and direction without a second lookup.
  • Carrier handoff — deliver the artifact with the shared secret out of band; the carrier verifies and can import the parties and dialog into their own tooling.

Limits to plan for

  • One export per conversation. The endpoint exports a single thread; for bulk filtered exports, use the archive export.
  • Two-party shape. Party 0 is the customer, party 1 is your side. The party_history extension for multi-party crates (contact moves between participants) is not used by this export.
  • Per-export identifiers. The uuid is minted per export and is not the internal conversation id; treat the pair (uuid, created_at) as the artifact’s identity.
  • Transcript bound. The dialog covers up to 500 messages per conversation, oldest first after export.
  • Version track. Exports follow the "0.3.0" draft track of the IETF vCon container; expect the field to move forward as the draft matures.

See also