> ## Documentation Index
> Fetch the complete documentation index at: https://docs.natural.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> When building application code, use `@naturalpay/sdk` for TypeScript or `naturalpay` for Python.
> When operating Natural directly for a user, use the payments MCP at `https://mcp.natural.com`.
> When searching Natural documentation, use the docs MCP at `https://docs.natural.com/mcp`.
> Use the Natural CLI for terminal and CI automation.
> Use REST only for unsupported languages or when the user explicitly requests raw HTTP.
> Start integration development and testing in the sandbox. Do not use production unless the user explicitly requests it.
> For sandbox requests that require `customerPartyId`, list customers first. Reuse only the intended fixture; otherwise create a customer.
> REST and SDK amounts use integer minor units. Payments MCP amounts use decimal strings with a required currency code.

# Take a payment over voice

> Collect a card payment during a phone call

Voice allows you to take card payments in a PCI compliant manner. Voice agents typically run cloud hosted LLMs, telephony, STT/TTS, and logging, making cardholder data infamously hard to capture due to PCI-DSS standards. Voice runs a locally hosted PCI-compliant voice agent that allows inbound SIP transfers to make voice payments on. It can be configured to transfer back to the original call or ended upon completion, with redacted transcripts available and realtime webhooks.

Transfer the caller to Natural's agent. It takes the card and processes the payment while your systems stay out of PCI scope.

<Snippet file="shared/prerequisites.mdx" />

Complete [Accept onboarding](/guides/flows/accept-payments), then contact [hi@natural.com](mailto:hi@natural.com) to connect your voice platform.

<Note>
  Collecting for a customer? Pass their party ID as `customerPartyId` when creating the payment
  intent and voice session.
</Note>

## Create the voice session

[Create a payment intent](/guides/accept/pay-by-link#create-the-intent), then [create a voice session](/api-reference/voice/create-voice-session) for it.

<Snippet file="shared/instance-id-note.mdx" />

<CodeGroup>
  ```python Python theme={null}
  import uuid
  from naturalpay import Natural

  # Set NATURAL_API_KEY to your agent's API key.
  client = Natural(instance_id=str(uuid.uuid4()))

  session = client.voice_sessions.create(
      kind="payment",
      payment_intent_id="pmi_019d0a1b2c3d4e5f60718293a4b5c6d7",
      caller_phone="+14155550123",
      return_target="sip:agent-9920@sip.partner.example.com",
      idempotency_key=str(uuid.uuid4()),
  )
  ```

  ```typescript TypeScript theme={null}
  import Natural from "@naturalpay/sdk";

  // Set NATURAL_API_KEY to your agent's API key.
  const client = new Natural();
  const session = await client.voiceSessions.create(
    {
      kind: "payment",
      paymentIntentId: "pmi_019d0a1b2c3d4e5f60718293a4b5c6d7",
      callerPhone: "+14155550123",
      returnTarget: "sip:agent-9920@sip.partner.example.com",
      idempotencyKey: crypto.randomUUID(),
    },
    { instanceId: crypto.randomUUID() },
  );
  ```

  ```bash CLI theme={null}
  natural voice-sessions create \
    --kind payment \
    --payment-intent-id pmi_019d0a1b2c3d4e5f60718293a4b5c6d7 \
    --caller-phone +14155550123 \
    --return-target sip:agent-9920@sip.partner.example.com \
    --x-instance-id "$(uuidgen)" \
    --idempotency-key "$(uuidgen)"
  ```

  ```text MCP theme={null}
  Create a voice session for payment intent pmi_019d0a1b2c3d4e5f60718293a4b5c6d7.
  The caller is +14155550123. Return the call to sip:agent-9920@sip.partner.example.com.
  ```

  ```bash cURL theme={null}
  # NATURAL_API_KEY=ak_ntl_prod_... (the agent's key)
  curl -X POST https://api.natural.com/voice/sessions \
    -H "Authorization: Bearer $NATURAL_API_KEY" \
    -H "X-Instance-ID: $(uuidgen)" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{
      "data": {
        "attributes": {
          "kind": "payment",
          "paymentIntentId": "pmi_019d0a1b2c3d4e5f60718293a4b5c6d7",
          "callerPhone": "+14155550123",
          "returnTarget": "sip:agent-9920@sip.partner.example.com"
        }
      }
    }'
  ```
</CodeGroup>

`callerPhone` is required. Natural texts that number a checkout link if the card keeps failing. Set `returnTarget` to the SIP address that receives the call afterward. Omit it to end the call instead.

<Snippet file="api-examples/voice.create.response.mdx" />

## Transfer the caller

Transfer the call over SIP to the returned `dialUri` before `dialExpiresAt`, which is 15 minutes after creation or sooner if the intent expires first. Natural's agent confirms the amount, takes the card by speech or keypad, and processes the payment.

Each session accepts one call. Create a new session if the transfer fails or the session expires.

## Read the result

[Get the payment intent](/api-reference/payment-intents/get-payment-intent) to check its status, or subscribe to `paymentIntent.completed`, `cardPayment.succeeded`, and `cardPayment.failed` [webhooks](/api-reference/event-catalog).

Subscribe to `voiceSession.completed` to learn how each call finished. It fires once per session, after the call has ended and the result is known, and carries the call details. It does not mean paid. Read `payment.outcome`:

* `paid`: the card was charged on the call.
* `linkSent`: voice payment did not succeed, so Natural texted the caller the checkout link. The payment intent stays open. `payment.failure` holds the last decline, if any.
* `unpaid`: the call ended without a payment or a link.

A later link payment arrives as `paymentIntent.completed`. The voice session's outcome stays `linkSent`.

The outcome is on the voice session as soon as it is known, before the call ends. [Get the voice session](/api-reference/voice/get-voice-session) if you need it before the event.

<CodeGroup>
  ```python Python theme={null}
  payment = client.payment_intents.get(
      "pmi_019d0a1b2c3d4e5f60718293a4b5c6d7",
  )
  ```

  ```typescript TypeScript theme={null}
  const payment = await client.paymentIntents.get({
    paymentIntentId: "pmi_019d0a1b2c3d4e5f60718293a4b5c6d7",
  });
  ```

  ```bash CLI theme={null}
  natural payment-intents get --payment-intent-id pmi_019d0a1b2c3d4e5f60718293a4b5c6d7
  ```

  ```text MCP theme={null}
  Has that voice payment completed?
  ```

  ```bash cURL theme={null}
  curl https://api.natural.com/payment-intents/pmi_019d0a1b2c3d4e5f60718293a4b5c6d7 \
    -H "Authorization: Bearer $NATURAL_API_KEY"
  ```
</CodeGroup>

A paid intent has status `completed`. Its `cardPayment` relationship identifies the successful payment.

<Snippet file="api-examples/paymentIntents.get.response.paidByVoice.mdx" />

View call logs and transcripts in the dashboard or through the API, with card details redacted. See [Call log and transcripts](/guides/voice/call-log).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.