# Transport Fetch API reference

> Exports of @gramforge/transport-fetch.

Source: https://gramforge.n.yatsyk.com/docs/transport-fetch/jsdoc

## Functions

### albumSizeError

Runtime backstop for the compile-time {@link MediaGroupItems} tuple: a value
that reaches `sendMediaGroup` via a cast or an `unknown`-typed JSON decode is
length-checked here. Returns a `badRequest` `DeliveryResult` when out of the
2-10 range, or `null` when the size is valid.

```ts
albumSizeError(items: readonly MediaGroupItem[]): DeliveryResult<never> | null
```

### createBotClient

Build a {@link BotClient} bound to a token + `fetch`.

```ts
createBotClient(config: BotClientConfig): BotClient
```

### mapDelivery

Map the success value of a {@link DeliveryResult} while preserving every
error variant unchanged. Used to adapt one method's result type to another
(e.g. an `EditMessageResult` down to a `TelegramMessage`) without a cast and
without dropping the typed-error branches.

```ts
<A, B>(result: DeliveryResult<A>, transform: (value: A) => B): DeliveryResult<B>
```

### toWireEntities

Project a whole rendered entity list to wire objects.

```ts
toWireEntities(entities: readonly MessageEntity[]): readonly WireEntity[]
```

### toWireEntity

Project one rendered {@link MessageEntity} to its Bot API wire object.

```ts
toWireEntity(entity: MessageEntity): WireEntity
```

### toInlineMessageId

Brand a raw string as an {@link InlineMessageId}.

```ts
toInlineMessageId(value: string): InlineMessageId
```

### toRetryAfter

Brand a raw seconds number as a {@link RetryAfter}. Called only on a value
already zod-parsed from the wire `parameters.retry_after` field.

```ts
toRetryAfter(seconds: number): RetryAfter
```

### createLiveMessage

Construct a {@link LiveMessage} over an injected {@link LiveMessagePort}. Uses
the ambient `setTimeout`/`clearTimeout`/`Date.now` (mockable by fake timers in
tests); it never sleeps on a 429.

```ts
createLiveMessage(port: LiveMessagePort, options: LiveMessageOptions): LiveMessage
```

### isMessageNotModified

The single, tested predicate for Telegram's "message is not modified" reply.
There is no dedicated error code, so this matches the `description` wording
(isolated here so a future Bot API rewording is a one-line fix).

```ts
isMessageNotModified(result: DeliveryResult<unknown>): boolean
```

### parseWireResponse

THE wire boundary: read a `Response`'s JSON, `safeParse` the Bot API
envelope, then `safeParse` the success `result` against `dataSchema`. A
`res.json()` rejection becomes `networkError`; an unrecognized 200 body
becomes `serverError`; an `ok: false` body maps to its typed error variant.
Never throws, never returns unparsed data.

```ts
<T>(res: Response, dataSchema: WireSchema<T>): Promise<DeliveryResult<T>>
```

## Types

### FetchLike

The `fetch` implementation a client calls — global `fetch` by default.

```ts
type FetchLike = { (input: RequestInfo | URL, init?: RequestInit): Promise<Response>; (input: string | URL | Request, init?: RequestInit): Promise<Response>; }
```

### MediaGroupItems

A 2-to-10-item album, enforced at COMPILE TIME by an explicit tuple-length
union: 0/1 items and 11+ items fail to type-check (spec `bot-api-transport`,
"Album size out of range is a compile-time error"). A runtime guard in
`sendMediaGroup` backstops values that arrive via a cast.

```ts
type MediaGroupItems = | readonly [MediaGroupItem, MediaGroupItem]
  | readonly [MediaGroupItem, MediaGroupItem, MediaGroupItem]
  | readonly [MediaGroupItem, MediaGroupItem, MediaGroupItem, MediaGroupItem]
  | readonly [MediaGroupItem, MediaGroupItem, MediaGroupItem, MediaGroupItem, MediaGroupItem]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
```

### MediaSource

How a media item's file is referenced (no raw multipart upload here).

```ts
type MediaSource = | { readonly kind: "fileId"; readonly fileId: string }
  | { readonly kind: "url"; readonly url: string }
```

### WebAppInlineResult

The inline result passed to `answerWebAppQuery`.

```ts
type WebAppInlineResult = WebAppInlineResultArticle
```

### DeliveryResult

Outcome of a single Bot API call. `ok` carries the method's parsed result;
every other variant is a typed, non-throwing failure.

```ts
type DeliveryResult = DeliveryResult<T>
```

### WireEntity

A Bot API `MessageEntity` object as it appears on the wire.

```ts
type WireEntity = {
  readonly type: string;
  readonly offset: number;
  readonly length: number;
  readonly url?: string;
  readonly language?: string;
  readonly user?: { readonly id: number };
}
```

### InlineMessageId

The opaque id of an inline message (from an inline query / web-app result).

```ts
type InlineMessageId = Brand<string, "InlineMessageId">
```

### RetryAfter

Seconds a caller must wait before retrying, from a 429 `retry_after`.

```ts
type RetryAfter = Brand<number, "RetryAfter">
```

### EditTarget

Which message an `editMessageText` targets.

```ts
type EditTarget = | { readonly kind: "chatMessage"; readonly chatId: ChatId; readonly messageId: MessageId }
  | { readonly kind: "inlineMessage"; readonly inlineMessageId: InlineMessageId }
```

### KnownOrUnknown

Presence of a value, modeled as a DU rather than `T | undefined`.

```ts
type KnownOrUnknown = KnownOrUnknown<T>
```

### EditMessageResult

Result of an `editMessageText` call. A chat-message edit returns the updated
`Message`; an inline-message edit returns the wire literal `true` (there is
no message object) — modeled as an explicit DU, never `Message | undefined`.

```ts
type EditMessageResult = | { readonly kind: "edited"; readonly message: TelegramMessage }
  | { readonly kind: "inlineEdited" }
```

## Interfaces

### AnswerCallbackQueryArgs

Arguments for `answerCallbackQuery`.

```ts
interface AnswerCallbackQueryArgs
```

- `callbackQueryId: string`
- `text: string`
- `showAlert: boolean`

### AnswerWebAppQueryArgs

Arguments for `answerWebAppQuery`.

```ts
interface AnswerWebAppQueryArgs
```

- `webAppQueryId: string`
- `result: WebAppInlineResultArticle`

### BotClient

The raw Bot API client surface.

```ts
interface BotClient
```

- `sendMessage(args: SendMessageArgs): Promise<DeliveryResult<TelegramMessage>>`
- `sendPhoto(args: SendPhotoArgs): Promise<DeliveryResult<TelegramMessage>>`
- `editMessageText(args: EditMessageTextArgs): Promise<DeliveryResult<EditMessageResult>>`
- `sendMediaGroup(args: SendMediaGroupArgs): Promise<DeliveryResult<readonly TelegramMessage[]>>`
- `answerCallbackQuery(args: AnswerCallbackQueryArgs): Promise<DeliveryResult<true>>`
- `answerWebAppQuery(args: AnswerWebAppQueryArgs): Promise<DeliveryResult<SentWebAppMessage>>`
- `liveMessage(args: LiveMessageArgs): LiveMessage` — A create-once/edit-many live-progress message in `chatId`.

### BotClientConfig

Configuration for {@link createBotClient}.

```ts
interface BotClientConfig
```

- `token: string` — The bot token (the `bot<token>` path segment is added internally).
- `fetch: { (input: RequestInfo | URL, init?: RequestInit): Promise<Response>; (input: string | URL | Request, init?: RequestInit): Promise<Response>; }` — Override the `fetch` used (tests inject a fake); defaults to `globalThis.fetch`.
- `baseUrl: string` — Override the API origin; defaults to `https://api.telegram.org`.

### EditMessageTextArgs

Arguments for `editMessageText` (chat-message or inline-message target).

```ts
interface EditMessageTextArgs
```

- `target: EditTarget`
- `message: MessageText`
- `replyMarkup: InlineKeyboardMarkup`

### LiveMessageArgs

Arguments for {@link BotClient.liveMessage}.

```ts
interface LiveMessageArgs
```

- `chatId: ChatId`
- `minEditIntervalMs: number`

### MediaGroupItem

A single album item. Its caption presence is a DU, never `undefined`.

```ts
interface MediaGroupItem
```

- `type: "photo" | "video" | "document" | "audio"`
- `source: MediaSource`
- `caption: { readonly kind: "known"; readonly value: CaptionText; } | { readonly kind: "unknown"; }`

### SendMediaGroupArgs

Arguments for `sendMediaGroup`.

```ts
interface SendMediaGroupArgs
```

- `chatId: ChatId`
- `items: MediaGroupItems`

### SendMessageArgs

Arguments for `sendMessage`.

```ts
interface SendMessageArgs
```

- `chatId: ChatId`
- `message: MessageText`
- `replyMarkup: InlineKeyboardMarkup`

### SendPhotoArgs

Arguments for `sendPhoto` — a single photo (by `file_id` or public URL) with
an optional {@link CaptionText}. Telegram fetches a `url` photo itself, so it
must be a publicly reachable absolute URL (not a relative path).

```ts
interface SendPhotoArgs
```

- `chatId: ChatId`
- `photo: MediaSource`
- `caption: CaptionText`
- `replyMarkup: InlineKeyboardMarkup`

### WebAppInlineResultArticle

The `answerWebAppQuery` inline-result subset this change ships (design Open
Question, resolved): only an `article` result whose body is a rendered
`MessageText` — the shape the mini-app "send to a chat" composer flow needs.
Photo/video/other `InlineQueryResult` variants are added when `miniapp` lands
as new DU members (non-breaking).

```ts
interface WebAppInlineResultArticle
```

- `kind: "article"`
- `id: string`
- `title: string`
- `message: MessageText`

### LiveMessage

A live-progress message handle.

```ts
interface LiveMessage
```

- `update(text: string): void` — Record the latest text and schedule a debounced flush (synchronous).
- `flush(): Promise<DeliveryResult<TelegramMessage>>` — Force an immediate write of the pending text now, bypassing the debounce.
- `finish(finalText: string): Promise<DeliveryResult<TelegramMessage>>` — Write `finalText` once immediately and close the instance.

### LiveMessageOptions

Options for {@link createLiveMessage}.

```ts
interface LiveMessageOptions
```

- `minEditIntervalMs: number` — Minimum spacing between issued edits, in milliseconds.

### LiveMessagePort

The transport seam `LiveMessage` drives: a `send` that establishes the target
message and an `edit` that updates it, both returning a {@link DeliveryResult}.
`transport-fetch` and `transport-grammy` each supply their own implementation.

```ts
interface LiveMessagePort
```

- `send(text: string): Promise<DeliveryResult<TelegramMessage>>`
- `edit(target: EditTarget, text: string): Promise<DeliveryResult<TelegramMessage>>`

### SentWebAppMessage

The confirmation returned by `answerWebAppQuery`: a `SentWebAppMessage` whose
`inline_message_id` is present only when the message can later be edited.

```ts
interface SentWebAppMessage
```

- `inlineMessageId: { readonly kind: "known"; readonly value: string; } | { readonly kind: "unknown"; }`

### TelegramMessage

A Telegram `Message`, projected to the branded ids the transport exposes.

```ts
interface TelegramMessage
```

- `messageId: MessageId`
- `chatId: ChatId`
- `date: number`

## Constants

### EditMessageResultSchema

{@link EditMessageResult} response schema.

```ts
const EditMessageResultSchema: WireSchema<EditMessageResult>
```

### SentWebAppMessageSchema

{@link SentWebAppMessage} response schema.

```ts
const SentWebAppMessageSchema: WireSchema<SentWebAppMessage>
```

### TelegramMessageArraySchema

An array of {@link TelegramMessage}s, as `sendMediaGroup` returns.

```ts
const TelegramMessageArraySchema: WireSchema<readonly TelegramMessage[]>
```

### TelegramMessageSchema

{@link TelegramMessage} response schema.

```ts
const TelegramMessageSchema: WireSchema<TelegramMessage>
```

### TrueResultSchema

The `answerCallbackQuery` result — the Bot API returns the literal `true`.

```ts
const TrueResultSchema: WireSchema<true>
```
