Secure payment capture on the live softphone
An agent mid-conversation often needs to take payment: a deposit, an invoice balance, a booking. Reciting a card number over the line puts the agent in scope for PCI DSS, and letting the card number land in a call recording puts you out of compliance. Orbit’s secure payment capture removes both problems: the caller types the card number on their keypad, the agent never hears the digits, and recording pauses for the capture window. This page covers the agent-assisted flow on the live softphone. For unattended capture inside a self-service IVR menu (after-hours pay lines, agent-free billing), see IVR unattended PCI capture.How it works
- The agent clicks Secure payment on the live softphone (or your integration calls the start endpoint below).
- Orbit pauses recording for that window and masks the caller’s keypad tones. The agent cannot hear the digits and the digits never appear in the stored media or the live transcript.
- The caller enters each field (card number, expiry, CVV) by keypad. Your payment service provider (PSP) tokenizes the card off the voice path.
- Once the PSP confirms tokenization, the session completes and recording resumes. If the caller bails or the agent backs out, the agent cancels the session instead. Either way, Orbit stores only a masked summary: the card’s last four digits and brand.
Five-minute secure-payment flow
Here is one scripted end-to-end scenario — the sequence your agent and PSP follow every time a caller pays over the phone:-
Agent starts capture. The caller confirms the amount and the agent
clicks Secure payment on the live softphone. A dialog opens with the
default field selection (card number, expiry, CVV; postal code is
optionally selectable). The agent clicks Start capture. Orbit pauses
the SIPREC recording for this call and flips the
dtmf_maskedflag so the media bridge suppresses keypad tones from the agent’s audio. - Caller enters card digits. The agent instructs the caller to type each field — card number, expiry, CVV — on their phone keypad. The agent hears nothing; the digits never appear in the live transcript or the recording.
- PSP tokenizes. Your PSP reads the DTMF digits from the voice path and tokenizes the card. It returns a token reference (or a masked summary) to your listener.
- Agent completes capture. The agent pastes the last four digits and brand into the dialog and clicks Confirm. Orbit resumes recording, unmasks DTMF, and stores only the masked summary on the call record. Your PSP listener posts the token reference into your order system.
- Agent continues the call. Recording is back on, the caller’s keypad tones are audible again, and the agent resumes the conversation.
Dashboard walkthrough
Where the control lives
On a live call, the Secure payment button appears in the persistent floating softphone widget — the agent’s actual in-call toolbar — not buried in a call-detail page the agent visits only after the call ends. The button is visible whenever the softphone state is “on a call”; it derives the active session from the same 10-second poll that powers the call detail page.- Dialog path:
SecurePaymentDialog(apps/web/src/components/dialogs/secure-payment-dialog.tsx) - Softphone integration:
FloatingSoftphone(apps/web/src/components/softphone/floating-softphone.tsx), rendered whensoftphone.state === "on_call"and anactiveCallIdexists.
- Secure payment summary panel (
SecurePaymentSummaryPanel) — the immutable capture timeline for every session on the call, newest first. Shows the masked card summary (·· 4242 — visa), captured field badges, status (captured / cancelled), and start-to-end timestamp. - Secure payment history (
SecurePaymentHistory) — the full post-call read-only audit record, with a per-session row of the same masked summary, status chip, and timeline.
Who can start, complete, and cancel
There are no client-side role or permission gates on the secure payment control. Any agent who can join a call can start, complete, or cancel a capture session. Enforcement is server-side: the API rejects the request with a403 INSUFFICIENT_PERMISSIONS DevotelError if the authenticated
principal does not hold the required scope. The dialog surfaces that
rejection as a toast.
What the agent sees during a capture
While a session iscapturing:
- The softphone’s Secure payment button and the dialog switch to the live-capture view (Complete / Cancel footer) instead of the start form.
- The live transcript and agent-assist panels on the call detail page
pause content delivery for the capture window. They use the
server-authoritative
started_attimestamp (not the client’s “when I noticed” moment) as the PCI descope cutoff — any transcript content stamped at or after that instant is dropped, not merely hidden, so it never reappears when the capture ends. - The call recording timeline marks the paused segment so an auditor can see exactly which portion of the media was suppressed during the capture window.
Limits and behaviour
Every limit below is read from the current implementation — not invented.Capture-window duration
There is no server-enforced timeout on the capture window. A session stayscapturing until the agent explicitly completes or cancels it. If your PSP
needs an upper bound, set one in your integration layer — the agent clicks
Cancel if the caller takes too long or the PSP never responds.
Per-call concurrency
One capturing session per call at a time. Start rejects with409 SECURE_PAYMENT_ALREADY_ACTIVE if another session is still capturing.
Complete or cancel the active session before starting another.
Sequential sessions
Multiple sessions can run back-to-back on the same call. There is no per-call session cap. A caller who makes a mistake, or a call that needs to capture card details for two separate transactions, can go through start–complete, then start–complete again.Agent disconnect
The session is metadata on the call record — it does not depend on the agent’s WebSocket or the softphone session. If the agent disconnects and reconnects, the capturing session is still active. If the caller hangs up mid-capture, the session stayscapturing on the call record; recording
does not auto-resume because the call itself terminated. An operator can
review orphan sessions on the call detail page.
Field validation
fieldsacceptspan,expiry,cvv, andpostal_code. Unknown values are ignored.card_last4on complete must be exactly four digits (/^\d{4}$/) — the full PAN is rejected with422 SECURE_PAYMENT_INVALID_MASK.card_brandandpsp_token_refare free-form optional strings.
Recording resume
Recording resumes automatically when a session completes or cancels, with one gate: if the tenant’s recording settings require a consent receipt on resume, pass aconsent_receipt_id in the complete or cancel request.
Without it, the resume is rejected and the session stays capturing — the
agent can retry with the receipt. Recording does not resume if another
session is still capturing on the same call.
Audit and webhook failure modes
Webhook events
Orbit emits three webhook events — one per state transition:
Events are dispatched to the tenant event stream and to every registered
webhook endpoint. Delivery is best-effort and non-blocking — a webhook
delivery failure never blocks the session state transition. If your PSP
listener never receives an event because the webhook queue backed up, the
session still moved to
captured or cancelled on the call record.
What a PSP listener should do on each event
-
call.secure_payment.started— your PSP has a capture window. Start listening for DTMF digits on the bridged voice path. No card data has arrived yet; this is the “arm your tokenizer” signal. -
call.secure_payment.completed— the agent confirmed the capture. The event carriescard_last4andcard_brand. Your listener can post the masked summary into your order system now, or reconcile thepsp_token_refagainst the token the PSP returned. Do not re-tokenize at this point — the card was already tokenized during the capture window. -
call.secure_payment.cancelled— the capture was aborted (caller bailed, PSP unreachable, agent cancelled). If your PSP had already tokenized the card, discard or void the token. The call recording resumed and no card summary was stored.
Orphan sessions — what happens when things go wrong
Audit trail on the call record
Every session — whethercaptured or cancelled — is appended to
call_logs.metadata.secure_payment_sessions[]. The array persists for the
life of the call record and is read by the dashboard’s summary panel and
history view. An operator reconciling an orphan session can inspect:
session_idandstatus— whether it landed in a terminal statestarted_atandstarted_by— who initiated it and whencompleted_at/cancelled_at— when it ended, if it endedfields— which fields were selectedcard_last4,card_brand,psp_token_ref— masked summary (captured only)
PCI posture checklist for your team
The platform handles the technical descoping — recording pause, DTMF masking, and the PAN-storage boundary. The rest is your responsibility. Work through this checklist before you put an agent on a live payment call:- Remove manual recording pause from your agent workflow. A capture that relies on the agent manually pausing recording leaves the agent able to hear card digits. Orbit’s secure payment control pauses recording automatically — use it as the sole pause mechanism during card capture.
-
Wire a recording-consent receipt into your complete and cancel
calls. If your tenant recording settings require a consent receipt
on resume, pass
consent_receipt_idon every complete and cancel request. Without it, the recording-resume gate rejects the finalize step and the session stays open. - Get your PSP and QSA to sign off on your tokenization path. Masked-DTMF capture follows the same widely accepted descoping pattern used by PCI Pal and Sycurio, but your specific PSP integration, your network path, and your tokenization pipeline are your scope to confirm. Orbit is the conduit — your QSA owns the assessment.
-
Subscribe your PSP listener to all three webhook events. Arm your
tokenizer on
started, route the masked summary into your order system oncompleted, and void any partial token oncancelled. -
Never send a full card number to the complete endpoint. The
/^\d{4}$/gate exists to keep the PAN out of call metadata — but the gate only works if your integration extracts exactly the last four digits before calling complete. - Review your call recording retention and access controls. The paused segments during capture windows are marked on the call recording timeline, so an auditor can verify the capture window is absent from the stored media. Confirm your retention policy and access roles align with what your QSA expects.
Start a capture session
fields accepts any of pan, expiry, cvv, postal_code, and
defaults to ["pan", "expiry", "cvv"] when omitted. The response
returns a session_id; hold on to it for complete or cancel.
A session starts only on a live, bridged call leg. Calls routed purely
through the SIP trunk or an AI-agent pipeline without a bridged leg
return 422 SECURE_PAYMENT_UNSUPPORTED. If a capture is already in
progress on the call, start returns 409 SECURE_PAYMENT_ALREADY_ACTIVE
— complete or cancel the active session first.
Complete the session
After the PSP tokenizes the card, confirm the capture. Orbit resumes recording, unmasks the keypad, and stores the masked summary.card_last4 must be exactly four digits. card_brand and an opaque
psp_token_ref string from your PSP are optional; both are stored so
your reconciliation job can pull them together later. Never send the
full card number — the request is rejected with
422 SECURE_PAYMENT_INVALID_MASK.
Cancel the session
Caller changes their mind, or the PSP is unreachable — cancel instead. Recording resumes and no card summary is stored.409 SECURE_PAYMENT_NOT_ACTIVE. An unknown session_id returns
404 SECURE_PAYMENT_SESSION_NOT_FOUND.
From the dashboard, the agent triggers all three steps from the
Secure payment control on the live softphone, and a past call’s
detail page shows the masked summary and the capture timeline for each
session.
Webhooks
Subscribe tocall.secure_payment.started,
call.secure_payment.completed, and call.secure_payment.cancelled
to drive your PSP tokenization flow. The completed event carries the
card_last4 and card_brand, so a listener can post the masked
summary straight into your order system. See
Webhook Events.
Compliance notes
- Recording resumes automatically on complete or cancel. If your tenant requires a recording-consent receipt on resume, pass the receipt id in the request — Orbit returns a validation error rather than resume without consent. See Recording library.
- Manual pause is not enough: a capture that still uses manual recording pause leaves the agent able to hear the card digits.
- PCI scope: masked-DTMF capture follows the same widely accepted descoping pattern used by PCI Pal and Sycurio. Confirm your PCI scope with your PSP and qualified security assessor.
Cross-references
- Recording library — start, pause, and resume recording and how paused segments appear on the call record
- IVR unattended PCI capture — the self-service menu counterpart when no agent is on the call
- Voice quickstart — place your first live call
- Webhook events — subscribe to
call.secure_payment.* - Troubleshooting: secure-payment capture failures —
triage the five
SECURE_PAYMENT_*codes when a start, complete, or cancel rejects - Consent management — recording-consent receipts and manual pause