Skip to main content

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

  1. The agent clicks Secure payment on the live softphone (or your integration calls the start endpoint below).
  2. 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.
  3. The caller enters each field (card number, expiry, CVV) by keypad. Your payment service provider (PSP) tokenizes the card off the voice path.
  4. 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.
The full card number never passes through Orbit. Send a full card number to the complete endpoint and the request is rejected.

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:
  1. 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_masked flag so the media bridge suppresses keypad tones from the agent’s audio.
  2. 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.
  3. 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.
  4. 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.
  5. Agent continues the call. Recording is back on, the caller’s keypad tones are audible again, and the agent resumes the conversation.
If the caller changes their mind at step 2 or the PSP is unreachable at step 3, the agent clicks Cancel instead. Recording resumes with no card data stored. The agent can start a new session on the same call afterward — there is no per-call session limit.

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 when softphone.state === "on_call" and an activeCallId exists.
On a past call’s detail page (Dashboard → Voice → Calls → click a call), the Secure payment dialog also renders so a post-call review can start a capture on a still-bridged call. The call detail page surfaces two additional panels:
  • 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 a 403 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 is capturing:
  • 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_at timestamp (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 stays capturing 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 with 409 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 stays capturing 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

  • fields accepts pan, expiry, cvv, and postal_code. Unknown values are ignored.
  • card_last4 on complete must be exactly four digits (/^\d{4}$/) — the full PAN is rejected with 422 SECURE_PAYMENT_INVALID_MASK.
  • card_brand and psp_token_ref are 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 a consent_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 carries card_last4 and card_brand. Your listener can post the masked summary into your order system now, or reconcile the psp_token_ref against 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 — whether captured 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_id and status — whether it landed in a terminal state
  • started_at and started_by — who initiated it and when
  • completed_at / cancelled_at — when it ended, if it ended
  • fields — which fields were selected
  • card_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:
  1. 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.
  2. 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_id on every complete and cancel request. Without it, the recording-resume gate rejects the finalize step and the session stays open.
  3. 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.
  4. Subscribe your PSP listener to all three webhook events. Arm your tokenizer on started, route the masked summary into your order system on completed, and void any partial token on cancelled.
  5. 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.
  6. 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.
Each item on this list is your team’s responsibility. Orbit provides the capture control and the recording-pause boundary; your PSP, your QSA, and your integration code own compliance.

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.
Completing or cancelling a session that is already finished returns 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 to call.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