> For complete lifecycle-event payload schemas and examples, use the canonical overview: Session /api/sessions; Room lifecycle, members, and room playback /api/rooms; Session playback /api/playback; Recording /api/recording; DTMF /api/keypad-input; Messages /api/messages; WebSocket Session /api/web-socket. Use /api/event-delivery for transport behavior. Endpoint pages name relevant events, but these overviews are the canonical references.

# Collect CVV

POST https://api.telekesher.dev/v1/sessions/{uuid}/payment/cvv/collect
Content-Type: application/json

Start one isolated secure collection workflow for the Session. The Gateway never receives, stores, logs, or returns the collected card digits. Card collection accepts 12–19 digits and applies Luhn validation inside the trusted payment path; security-code collection accepts exactly three digits. A `202` response is only admission. The terminal result is delivered as a sanitized payment webhook.

See [Payment lifecycle events](/api/payments#lifecycle-events) for complete payload schemas and examples.

Reference: https://docs.vorbal.dev/api/payments/collect-secure-payment-cvv

## Authentication

- `Authorization` header (bearer token, required) — Application auth. Send `Authorization: Bearer <app_uuid>:<api_key>` using any active key in the app's collection. See [Authentication](https://voice-platform.docs.buildwithfern.com/api/authentication) for details.

## Request

### Path parameters

- `uuid` (string, required) — [Session](/api/sessions) identifier.

### Headers

- `Idempotency-Key` (string, optional) — Optional key for safely retrying mutating requests. See [Idempotency](https://voice-platform.docs.buildwithfern.com/idempotency) for details.
- `Operation-Id` (string, optional) — optional client-supplied lowercase RFC-4122 v4 UUID returned as operation_uuid; platform generates one when omitted; correlation metadata distinct from Idempotency-Key.

### Body (application/json)

- `between_digits_timeout_ms` (integer, required) — Milliseconds to wait between digits.
- `first_digit_timeout_ms` (integer, required) — Milliseconds to wait for the first digit.
- `terminators` (list of enum, required) — Distinct DTMF terminators. An empty array collects to the fixed secure length or timeout.
  - Allowed values: `#`, `*`
- `prompt_files` (list of string, optional) — Optional HTTP/HTTPS WAV or MP3 prompts played before the secure collection window opens.

## Response

### 202

Command accepted for async execution

- `operation_uuid` (string, required)
- `status` (enum, required)
  - Allowed values: `in_progress`, `completed`
- `already_ended` (true, optional) — Optional. Set to `true` on idempotent terminal commands when the session was already in a terminal state at the time the request was received. Absent otherwise.

## Examples

**Request**

```json
{
  "between_digits_timeout_ms": 2000,
  "first_digit_timeout_ms": 10000,
  "terminators": [
    "#"
  ],
  "prompt_files": [
    "https://cdn.example.com/payment-card.wav"
  ]
}
```

**Response**

```json
{
  "operation_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "status": "in_progress"
}
```

**SDK Code**

```python Payments_collectSecurePaymentCVV_example
import requests

url = "https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect"

payload = {
    "between_digits_timeout_ms": 2000,
    "first_digit_timeout_ms": 10000,
    "terminators": ["#"],
    "prompt_files": ["https://cdn.example.com/payment-card.wav"]
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Payments_collectSecurePaymentCVV_example
const url = 'https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"between_digits_timeout_ms":2000,"first_digit_timeout_ms":10000,"terminators":["#"],"prompt_files":["https://cdn.example.com/payment-card.wav"]}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Payments_collectSecurePaymentCVV_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect"

	payload := strings.NewReader("{\n  \"between_digits_timeout_ms\": 2000,\n  \"first_digit_timeout_ms\": 10000,\n  \"terminators\": [\n    \"#\"\n  ],\n  \"prompt_files\": [\n    \"https://cdn.example.com/payment-card.wav\"\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Payments_collectSecurePaymentCVV_example
require 'uri'
require 'net/http'

url = URI("https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"between_digits_timeout_ms\": 2000,\n  \"first_digit_timeout_ms\": 10000,\n  \"terminators\": [\n    \"#\"\n  ],\n  \"prompt_files\": [\n    \"https://cdn.example.com/payment-card.wav\"\n  ]\n}"

response = http.request(request)
puts response.read_body
```

```java Payments_collectSecurePaymentCVV_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"between_digits_timeout_ms\": 2000,\n  \"first_digit_timeout_ms\": 10000,\n  \"terminators\": [\n    \"#\"\n  ],\n  \"prompt_files\": [\n    \"https://cdn.example.com/payment-card.wav\"\n  ]\n}")
  .asString();
```

```php Payments_collectSecurePaymentCVV_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect', [
  'body' => '{
  "between_digits_timeout_ms": 2000,
  "first_digit_timeout_ms": 10000,
  "terminators": [
    "#"
  ],
  "prompt_files": [
    "https://cdn.example.com/payment-card.wav"
  ]
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Payments_collectSecurePaymentCVV_example
using RestSharp;

var client = new RestClient("https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"between_digits_timeout_ms\": 2000,\n  \"first_digit_timeout_ms\": 10000,\n  \"terminators\": [\n    \"#\"\n  ],\n  \"prompt_files\": [\n    \"https://cdn.example.com/payment-card.wav\"\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Payments_collectSecurePaymentCVV_example
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "between_digits_timeout_ms": 2000,
  "first_digit_timeout_ms": 10000,
  "terminators": ["#"],
  "prompt_files": ["https://cdn.example.com/payment-card.wav"]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.telekesher.dev/v1/sessions/uuid/payment/cvv/collect")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```