Skip to main content

Unattended PCI capture in the IVR builder

The DTMF Input node in the IVR builder has a PCI capture mode built for pay-by-phone menus with no agent on the call: an after-hours self-service balance line, a callback-led payment flow, an agent-free billing IVR. When capture mode is on, the caller types their card on the keypad, recording pauses for that window, and the raw digits never reach logs, transcripts, or your flow context — only the digit count and a per-call fingerprint are kept. If a live agent is on the call instead, use the agent-assisted flow covered in Secure payment capture on the live softphone — this page covers the unattended path only.

1. When unattended capture is the right tool

Choose the IVR path when the entire payment happens inside the menu and no person participates:
  • After-hours self-service. A caller reaches your number outside business hours, hears “press 1 to pay your balance,” and types the card while recording pauses. No agent is staffed, so no agent can be descoped — the menu itself must be the trust boundary.
  • Callback-led pay. Your system calls the customer back at a confirmed time and walks straight into a capture node.
  • Agent-free billing IVRs. Recurring invoice or top-up lines where the caller self-enters a card or PIN every time.
Choose the agent-assisted softphone flow when a human is mid-conversation with the caller and needs to take payment there and then — the same masked-DTMF semantics apply, but the agent controls the session from the live softphone.

2. Configure it from the IVR builder

In the dashboard, go to Voice → IVR Builder and open your flow (or start a new one — see Design IVR flows on the visual builder).
  1. Drag a DTMF Input node onto the canvas and click it to open the config panel.
  2. Set the collection shape for a card field: Max Digits (up to 20 for a full card number), Timeout, and Finish on Key (# is the usual terminator). For a full capture, use one DTMF Input node per field — card number, expiry, CVV.
  3. Toggle PCI capture mode (secure entry) on.
  4. Optionally set Tokenizer URL to your payment service provider’s (PSP) tokenization endpoint — for example https://payments.example.com/tokenize. The digits are exchanged once against this URL; its opaque reply token is the only value a downstream node can read, via the {{pci_token}} template placeholder. Leave the URL empty to pause recording and mask the digits without tokenizing.
Behind the capture there is nothing extra to wire: the runtime emits a recording pause before the gather and a resume on the continuation automatically.

3. Publish preflight

The builder’s preflight validation (the Validate button, which also runs on publish) rejects a malformed tokenizer URL, so a bad literal never ships to the live snapshot. An unparseable URL fails validation with an issue shaped like:
Fix the URL until Validate returns clean, then Publish and attach the flow to a number. An empty tokenizer URL is valid — capture still pauses recording; only the token exchange is skipped.

4. Runtime semantics — what the platform actually does

Once a published flow reaches a PCI capture node on a live call:
  1. Recording pauses. When the route records the call, recording is paused immediately before the digits are collected and resumed on the continuation — including error paths, so a call is never left with recording silently paused. If the number’s route never started recording, the pause/resume pair is skipped.
  2. The digits are masked end to end. The platform stores only the digit count and a salted, per-call fingerprint. The raw entry never lands in logs, in the call’s flow context, or in transcripts, and downstream {{dtmf_input}} placeholders are explicitly cleared so they can never resolve to the captured digits.
  3. Optional token exchange, on your edge. When the node carries a tokenizer URL, the digits are POSTed once to that URL — your PSP’s PCI-scoped tokenization endpoint — before they are dropped. The URL passes an SSRF guard (internal addresses are refused), the request has a 5-second budget, and the response must be JSON with a top-level string token field. The token is stored as {{pci_token}} for downstream nodes (HTTP Request, Send Message, webhooks).
  4. Failure fails closed. An SSRF block, timeout, non-2xx reply, or a response with no token ends the capture with a polite hangup — the digits stay dropped, recording resumes, and nothing half-captured is stored.

5. Bind the capture to a commerce charge

The capture on the call produces a masked, verified summary. Bind it to a priced charge from your backend with POST /api/v1/commerce/secure-payment/charge. The capture proof is derived server-side from the call’s stored session — the fields you send are consistency hints, and any hint that disagrees with the stored masked summary fails closed. Only a completed capture can bind.
The equivalent with the Node SDK — the endpoint is reachable through the client’s generic request method against the resource you prefer:
card_last4 must be exactly four digits — send a full card number anywhere in this flow and the request is rejected at validation. Your PSP settles the opaque token out of band; subscribe to commerce.secure_payment.charge_bound to notify your order system when a charge binds. See Webhook events.

6. Tenant-owned security posture

Masked-DTMF capture is a scope-reduction control you opt into per node — it defaults off. The platform handles only masked digits: the raw card number never persists anywhere on Orbit, and the token exchange runs against an endpoint you operate. That shape keeps Orbit outside your cardholder data environment; it does not by itself make any party PCI DSS compliant.
  • The PCI scope of the full flow is owned by you: your tokenizer endpoint, your PSP, and your qualified security assessor determine where your boundary lands.
  • Keep capture nodes collecting card data only — routing menus, account lookups, and confirmations stay on ordinary DTMF Input nodes.
  • Confirm your tenant’s recording-consent and PCI scope obligations with your assessor, and document the control in your own policy. See PCI DSS posture.

7. Limits

  • A full card number is never accepted on any platform endpoint — a PAN sent as the card_last4 hint is rejected at validation. The platform stores digit count plus a salted fingerprint, nothing more.
  • There is no SIP-trunk or AI-agent pass-through for captured digits: collection runs on the platform’s own voice path, and the only value that travels downstream is the tokenizer’s opaque reply token.
  • Tokenizer requests are bounded (5 seconds, response size capped) and fail closed — a slow tokenizing endpoint ends the call rather than holding the caller indefinitely.

8. Troubleshooting

  • Publish is blocked with “PCI capture: tokenizer URL is not a valid URL.” The tokenizer URL does not parse as a URL with a host. Fix it in the node’s config panel and re-validate; an empty field is allowed.
  • Callers hear “we were unable to process your input” and the call hangs up. The tokenizer exchange failed closed: the URL is unreachable, timed out past 5 seconds, answered non-2xx, returned a body without a top-level string token, or the SSRF guard refused it (internal address). Check your tokenizer endpoint’s reachability and response shape.
  • The digits arrive but nothing is tokenized. The tokenizer URL is empty — capture still masked and paused recording, but no exchange ran. Set the URL if downstream nodes need {{pci_token}}.
  • Capture behaves oddly on a non-bridged leg. PCI capture is an in-call flow step: it runs on the answered leg the flow controls. A leg that is mid-transfer or pure SIP-trunk transit without the flow’s control does not present a gather point — route through a DTMF Input node on the answered call. For the related agent-assisted codes, see Troubleshooting: secure-payment capture failures.

See also