***
id: f1262a67-d3bf-4429-a6e5-615144cbd33e
title: CallTap
keywords: 'SignalWire, Realtime SDK, Node.js, call tap, audio tap, call monitoring'
slug: /node/reference/voice/call-tap
sidebar-title: CallTap
description: >-
CallTap object reference for tapping voice call audio streams. Stream call
audio to external destinations via RTP for monitoring or recording.
max-toc-depth: 3
----------------
[calltap]: #
[tap]: /docs/server-sdk/v4/node/reference/voice/call/tap
[tapAudio]: /docs/server-sdk/v4/node/reference/voice/call/tap-audio
Represents a current or past tapping of a call.
Obtain instances of this class by starting a Tap with one of the following methods:
* [`Call.tap`][tap]
* [`Call.tapAudio`][tapAudio]
### Example
As soon as the other party answers the phone, start transmitting the audio of
the call to an external service.
```js
import { SignalWire } from "@signalwire/realtime-api";
const client = await SignalWire({ project: "ProjectID Here", token: "Token Here" })
const call = await client.voice.dialPhone({
to: process.env.TO_NUMBER,
from: process.env.FROM_NUMBER,
timeout: 30
})
const tap = await call.tapAudio({
direction: "both",
device: {
type: "ws",
uri: "wss://2769-100-7-113-61.ngrok-free.app",
}
}).onStarted();
// wait 10 seconds then stop the tap
setTimeout(async () => {
console.log("Stopping tap");
await tap.stop();
}, 10000);
// wait for the tap to end
await tap.ended();
console.log("Tap ended");
await call.playTTS({
text: "Tap ended"
});
// hangup the call
call.hangup();
```
## **Properties**
The unique ID for this tap session.
The current state of the tap session.
Whether the tap has ended. Returns `true` if the state is `"finished"`.
## **Methods**
### ended
* **ended**(): `Promise`\<[`CallTap`][calltap]>
Returns a promise that is resolved only after this tap finishes (or is stopped).
#### Returns
`Promise`\<[`CallTap`][calltap]>
A promise that resolves to [`CallTap`][calltap] object when the tap session has been
ended.
#### Example
```js
import { SignalWire } from "@signalwire/realtime-api";
const client = await SignalWire({ project: "your-project-id", token: "your-api-token" });
const call = await client.voice.dialPhone({
from: "+1xxxxxxxxxx",
to: "+1yyyyyyyyyy",
timeout: 30
});
const tap = await call.tapAudio({
direction: "both",
device: {
type: "ws",
uri: "wss://example.domain.com/endpoint"
},
listen: {
onStarted: () => console.log("Tap started"),
onEnded: () => console.log("Tap ended")
}
}).onStarted();
// Wait for tap to finish
await tap.ended();
console.log("Tap session completed");
```
***
### stop
* **stop**(): `Promise`\<[`CallTap`][calltap]>
Stops the tapping.
#### Returns
`Promise`\<[`CallTap`][calltap]>
A promise that resolves to [`CallTap`][calltap] object when the tap session has been stopped.
#### Example
```js
import { SignalWire } from "@signalwire/realtime-api";
const client = await SignalWire({ project: "your-project-id", token: "your-api-token" });
const call = await client.voice.dialPhone({
from: "+1xxxxxxxxxx",
to: "+1yyyyyyyyyy",
timeout: 30
});
// Start tapping audio to an RTP endpoint
const tap = await call.tapAudio({
direction: "both",
device: {
type: "rtp",
addr: "192.0.2.1",
port: "5000",
codec: "PCMU"
}
}).onStarted();
console.log("Tap started with ID:", tap.id);
// Stop the tap after processing
await tap.stop();
console.log("Tap stopped");
```
***
## **Events**
### onStarted
* **CallTap.listen**(`{ onStarted: Callback }}`)
Emitted when the tapping starts. Your event handler will receive an instance of [`CallTap`][calltap].
#### Parameters
The tap that started. See [`CallTap`][calltap].
### onEnded
* **CallTap.listen**(`{ onEnded: Callback }}`)
Emitted when the tapping ends. Your event handler will receive an instance of [`CallTap`][calltap].
#### Parameters
The tap that ended. See [`CallTap`][calltap].