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

# createChannelRouter()

> **createChannelRouter**(`options`): `Readonly`\<\{ `delivery`(`event`): `Promise`\<\{ `runId`: `string`; } | `undefined`>; `receive`(`inbound`): `Promise`\<\{ `duplicate`: `boolean`; `runId`: `string`; }>; `reply`(`request`): `Promise`\<\{ `providerRequestId`: `string`; }>; `send`(`request`): `Promise`\<\{ `providerRequestId`: `string`; }>; }>

**Parameters**

| Parameter | Type |
| - | - |
| `options` | [`ChannelRouterOptions`](/docs/agent-sdk/harness-sdk/channels/router#channelrouteroptions) |

**Returns**
`Readonly`\<\{ `delivery`(`event`): `Promise`\<\{ `runId`: `string`; } | `undefined`>; `receive`(`inbound`): `Promise`\<\{ `duplicate`: `boolean`; `runId`: `string`; }>; `reply`(`request`): `Promise`\<\{ `providerRequestId`: `string`; }>; `send`(`request`): `Promise`\<\{ `providerRequestId`: `string`; }>; }>

## ChannelRouterOptions

**Properties**
**accept**

> `readonly` **accept**: (`request`) => `Promise`\<\{ `runId`: `string`; }>

**Parameters**

| Parameter | Type |
| - | - |
| `request` | [`ChannelAcceptance`](/docs/agent-sdk/harness-sdk/channels/router#channelacceptance) |

**Returns**
`Promise`\<\{ `runId`: `string`; }>

**adapters**

> `readonly` **adapters**: readonly [`ChannelAdapter`](/docs/agent-sdk/harness-sdk/channels/router#channeladapter)\[]

**ledger**

> `readonly` **ledger**: [`ChannelLedger`](/docs/agent-sdk/harness-sdk/channels/router#channelledger)

**policy**

> `readonly` **policy**: [`OutboundChannelPolicy`](/docs/agent-sdk/harness-sdk/channels/router#outboundchannelpolicy)

## ChannelAdapter

**Properties**
**channel**

> `readonly` **channel**: `string`

**Methods**
**send()**

> **send**(`request`): `Promise`\<\{ `providerRequestId`: `string`; }>

**Parameters**

| Parameter | Type |
| - | - |
| `request` | [`ChannelSendRequest`](/docs/agent-sdk/harness-sdk/channels/router#channelsendrequest) |

**Returns**
`Promise`\<\{ `providerRequestId`: `string`; }>

## ChannelLedger

**Methods**
**acceptInbound()**

> **acceptInbound**(`channel`, `externalMessageId`, `conversationId`, `accept`): `Promise`\<`Readonly`\<\{ `duplicate`: `boolean`; `runId`: `string`; }>>

Atomically claims an inbound provider message and persists its run mapping
as one recovery unit. Persistent implementations must share this claim across
router processes and must not release a claim after `accept` succeeds.

**Parameters**

| Parameter | Type |
| - | - |
| `channel` | `string` |
| `externalMessageId` | `string` |
| `conversationId` | `string` |
| `accept` | () => `Promise`\<`string`> |

**Returns**
`Promise`\<`Readonly`\<\{ `duplicate`: `boolean`; `runId`: `string`; }>>

**findOutbound()**

> **findOutbound**(`channel`, `providerRequestId`): `Promise`\<`string` | `undefined`>

**Parameters**

| Parameter | Type |
| - | - |
| `channel` | `string` |
| `providerRequestId` | `string` |

**Returns**
`Promise`\<`string` | `undefined`>

**findRun()**

> **findRun**(`runId`): `Promise`\<`Readonly`\<\{ `channel`: `string`; `conversationId`: `string`; }> | `undefined`>

**Parameters**

| Parameter | Type |
| - | - |
| `runId` | `string` |

**Returns**
`Promise`\<`Readonly`\<\{ `channel`: `string`; `conversationId`: `string`; }> | `undefined`>

**recoverOutbound()**

> **recoverOutbound**(`channel`, `runId`, `idempotencyKey`): `Promise`\<\{ `providerRequestId`: `string`; } | `undefined`>

Reconciles a previous provider success without authorizing or sending again.

**Parameters**

| Parameter | Type |
| - | - |
| `channel` | `string` |
| `runId` | `string` |
| `idempotencyKey` | `string` |

**Returns**
`Promise`\<\{ `providerRequestId`: `string`; } | `undefined`>

**sendOutbound()**

> **sendOutbound**(`channel`, `runId`, `idempotencyKey`, `send`): `Promise`\<\{ `providerRequestId`: `string`; }>

Reserves and completes one correlated outbound attempt. Implementations
must retain the stable idempotency key through retries/recovery so a
provider never observes an unkeyed resend after persistence uncertainty.

**Parameters**

| Parameter | Type |
| - | - |
| `channel` | `string` |
| `runId` | `string` |
| `idempotencyKey` | `string` |
| `send` | (`idempotencyKey`) => `Promise`\<\{ `providerRequestId`: `string`; }> |

**Returns**
`Promise`\<\{ `providerRequestId`: `string`; }>

## OutboundChannelPolicy

**Methods**
**authorize()**

> **authorize**(`request`): `Promise`\<`boolean`>

**Parameters**

| Parameter | Type |
| - | - |
| `request` | `Readonly`\<\{ `channel`: `string`; `serviceAccountId`: `string` \| `undefined`; }> |

**Returns**
`Promise`\<`boolean`>

## ChannelContent

> **ChannelContent** = `Readonly`\<`Record`\<`string`, `unknown`>>

Generic discrete-message channel contract.

The harness never accepts provider payloads or provider-specific addressing
fields. A reference adapter owns those transformations before this boundary.

## NormalizedChannelInbound

**Properties**
**channel**

> `readonly` **channel**: `string`

**content**

> `readonly` **content**: [`ChannelContent`](/docs/agent-sdk/harness-sdk/channels/router#channelcontent)

**conversationId**

> `readonly` **conversationId**: `string`

**externalMessageId**

> `readonly` **externalMessageId**: `string`

**receivedAt**

> `readonly` **receivedAt**: `number`

## ChannelAcceptance

**Properties**
**channel**

> `readonly` **channel**: `string`

**content**

> `readonly` **content**: [`ChannelContent`](/docs/agent-sdk/harness-sdk/channels/router#channelcontent)

**conversationId**

> `readonly` **conversationId**: `string`

**externalMessageId**

> `readonly` **externalMessageId**: `string`

**receivedAt**

> `readonly` **receivedAt**: `number`

## ChannelSendRequest

**Properties**
**content**

> `readonly` **content**: [`ChannelContent`](/docs/agent-sdk/harness-sdk/channels/router#channelcontent)

**conversationId**

> `readonly` **conversationId**: `string`

**idempotencyKey?**

> `readonly` `optional` **idempotencyKey?**: `string`

Stable retry token supplied for replies that require delivery correlation.

## ChannelReplyRequest

**Properties**
**content**

> `readonly` **content**: [`ChannelContent`](/docs/agent-sdk/harness-sdk/channels/router#channelcontent)

**idempotencyKey**

> `readonly` **idempotencyKey**: `string`

Caller-supplied stable key for this retryable reply.

**runId**

> `readonly` **runId**: `string`

**serviceAccountId?**

> `readonly` `optional` **serviceAccountId?**: `string`

## ChannelOutboundRequest

**Properties**
**channel**

> `readonly` **channel**: `string`

**content**

> `readonly` **content**: [`ChannelContent`](/docs/agent-sdk/harness-sdk/channels/router#channelcontent)

**conversationId**

> `readonly` **conversationId**: `string`

**idempotencyKey**

> `readonly` **idempotencyKey**: `string`

Caller-supplied stable key for this retryable out-of-band send.

**runId**

> `readonly` **runId**: `string`

Exact harness run to correlate this out-of-band send with delivery events.

**serviceAccountId?**

> `readonly` `optional` **serviceAccountId?**: `string`

## ChannelDeliveryEvent

**Properties**
**channel**

> `readonly` **channel**: `string`

**occurredAt**

> `readonly` **occurredAt**: `number`

**providerRequestId**

> `readonly` **providerRequestId**: `string`

**status**

> `readonly` **status**: `string`

## ChannelAuthorizationError

**Constructors**
**Constructor**

> **new ChannelAuthorizationError**(): `ChannelAuthorizationError`

**Returns**
`ChannelAuthorizationError`

**Properties**
**cause?**

> `optional` **cause?**: `unknown`

**message**

> **message**: `string`

**name**

> **name**: `string`

**stack?**

> `optional` **stack?**: `string`

**stackTraceLimit**

> `static` **stackTraceLimit**: `number`

The `Error.stackTraceLimit` property specifies the number of stack frames
collected by a stack trace (whether generated by `new Error().stack` or
`Error.captureStackTrace(obj)`).

The default value is `10` but may be set to any valid JavaScript number. Changes
will affect any stack trace captured *after* the value has been changed.

If set to a non-number value, or set to a negative number, stack traces will
not capture any frames.

**Methods**
**captureStackTrace()**

> `static` **captureStackTrace**(`targetObject`, `constructorOpt?`): `void`

Creates a `.stack` property on `targetObject`, which when accessed returns
a string representing the location in the code at which
`Error.captureStackTrace()` was called.

```js theme={null}
const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack;  // Similar to `new Error().stack`
```

The first line of the trace will be prefixed with
`${myObject.name}: ${myObject.message}`.

The optional `constructorOpt` argument accepts a function. If given, all frames
above `constructorOpt`, including `constructorOpt`, will be omitted from the
generated stack trace.

The `constructorOpt` argument is useful for hiding implementation
details of error generation from the user. For instance:

```js theme={null}
function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
```

**Parameters**

| Parameter | Type |
| - | - |
| `targetObject` | `object` |
| `constructorOpt?` | `Function` |

**Returns**
`void`

**prepareStackTrace()**

> `static` **prepareStackTrace**(`err`, `stackTraces`): `any`

**Parameters**

| Parameter | Type |
| - | - |
| `err` | `Error` |
| `stackTraces` | `CallSite`\[] |

**Returns**
`any`

**See**
[https://v8.dev/docs/stack-trace-api#customizing-stack-traces](https://v8.dev/docs/stack-trace-api#customizing-stack-traces)
