# @aishorty/sdk 中文文档

规范地址：https://npmcn.com/package/%40aishorty/sdk/

版本：0\.1\.0
npm 元数据更新时间：2026-08-05T02:30:03.077Z
中文译文更新时间：2026-11-05T21:47:52.559Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40aishorty/sdk
原文对照：https://npmcn.com/package/%40aishorty/sdk/?lang=original
项目主页：https://aishorty.com/developers
源码仓库：https://github.com/DevinoSolutions/shorty-sdk

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：264 kB，9 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=20
- 运行依赖：0 个
- 首次发布：2026-07-29T13:41:20.615Z
- 最新版本发布：2026-07-29T13:41:20.979Z
- 近 30 天下载量：15904（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：1（近 12 个月 1 个）

## 中文简介

官方 TypeScript SDK for the Shorty 公用API (aishorty.com/v一).

## 安装

```sh
npm install @aishorty/sdk
```

也可以使用：`pnpm add @aishorty/sdk`、`yarn add @aishorty/sdk`、`bun add @aishorty/sdk`

## README

# @aishorty/ sdk (英语)

官方类型SDK [短长](https://aishorty.com/) 公开 API (单位:千美元)`https://aishorty.com/v1`) (中文(简体) ). 转录媒体,总结录像和网页, 生成字幕,以及民意合成工作——有打出错误,自动重复, 光标 pagination, 以及标准- Webhooks 签名验证 .

-   **零运行时间依赖关系.** 土著 `fetch`, (中文(简体) ), `node:crypto`, (中文(简体) ), `AbortSignal`。 。 。 .
-   **节点.js 20.** 无害环境管理和共同JS建立完整的申报类型.
-   **仅服务器侧** -你的API密钥是个秘密 如果是客户扔出去了 检测浏览器环境.

## 安装

```bash
npm install @aishorty/sdk
# or: pnpm add @aishorty/sdk  /  yarn add @aishorty/sdk
```

## 快速启动

```ts
import { Shorty } from '@aishorty/sdk'

const shorty = new Shorty({ apiKey: process.env.SHORTY_API_KEY })

// Start a summary job for a YouTube video…
const job = await shorty.summaries.create({
    source: 'youtube',
    url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
})

// …then wait for it to finish.
const finished = await shorty.jobs.waitFor(job.job_id)
console.log(finished.status, finished.output)
```

## 认证

Shorty 完全接受一个认证形式: a **Bearer API 密钥** (单位:千美元)`shk_live_…`),发送 以下列方式处理每项请求: `Authorization: Bearer <key>`中创建密钥 操纵台.

```ts
// Explicit:
const shorty = new Shorty({ apiKey: 'shk_live_…' })

// Or omit it and the SDK reads process.env.SHORTY_API_KEY:
const shorty = new Shorty()
```

钥匙是用闭合的——它从未出现在 `JSON.stringify(client)`, (中文(简体) ), `util.inspect(client)`或调试日志.

### 客户选项

| 选项 | 默认 | 说明 |
| --- | --- | --- |
| `apiKey` | `process.env.SHORTY_API_KEY` |  `shk_live_…` 键。 落地时抛出. |
| `baseUrl` | `https://aishorty.com` | API 来源( 路径已包含 `/v1`) (中文(简体) ). |
| `timeoutMs` | `60000` | 潜入暂停. |
| `maxRetries` | `2` | 第一次尝试后再重复. |
| `fetch` | `globalThis.fetch` | 覆盖获取执行 . |
| `debug` | `false` | `true` 日志为 stderr; 函数接收已编辑的日志行. |
| `dangerouslyAllowBrowser` | `false` | 允许在 `window` 存在(不建议). |

## 资源

```ts
await shorty.usage.get()

const page = await shorty.articles.list({ limit: 20 })
await shorty.articles.search({ q: 'transformers', article_type: 'YOUTUBE_ARTICLE' })
await shorty.articles.get(articleId)

await shorty.transcriptions.list()
await shorty.transcriptions.get(id)
await shorty.transcriptions.create({ url: 'https://example.com/audio.mp3' })

await shorty.summaries.create({ source: 'url', url: 'https://example.com/post' })
await shorty.summaries.create({ source: 'text', content: 'Long text to summarize…' })

await shorty.subtitles.create({ url: 'https://example.com/clip.mp4', style: 'TIKTOK' })
await shorty.subtitles.download(jobId, { kind: 'srt' })

await shorty.jobs.get(jobId)
await shorty.jobs.waitFor(jobId)
```

每一个方法都有一个跟踪 `opts?` 与 `{ signal, timeoutMs, headers }` (和 `idempotencyKey` (关于创建方法).

## 倾斜

`list()` 返回 a `Page`标注 `for await` 走路时 **每个** 项目 横跨所有页( SDK 遵循您的不透明光标, 重用您的 原始过滤器),或手动页.

```ts
// Auto-iterate all items:
for await (const article of await shorty.articles.list({ limit: 50 })) {
    console.log(article.id, article.title)
}

// Manual page control:
let page = await shorty.articles.list({ limit: 50 })
while (page) {
    console.log(page.data.length, 'items; hasMore =', page.hasMore)
    page = (await page.nextPage()) ?? null
    if (!page) break
}
```

> 光标是 **过滤带**: 在一个查询下刻出光标不能为 在不同的过滤器上重放 。 SDK从不变异你的配方 拨号,所以这是自动处理的,只是不要把光标交给一个 不同 `list()` 电话.

## 任务( I) `waitFor`

写作( A)`transcriptions.create`, (中文(简体) ), `summaries.create`, (中文(简体) ), `subtitles.create`返回时 (单位:千美元) `202` `{ job_id, status, tracking_url }`。通过 `jobs.get(id)`,或使用 方便传票人:

```ts
try {
    const done = await shorty.jobs.waitFor(job.job_id, {
        pollIntervalMs: 2000, // default
        timeoutMs: 600_000, // default
        // signal: abortController.signal,
    })
    console.log('done:', done.output)
} catch (err) {
    if (err instanceof JobFailedError) {
        // The job ended in ERROR/CANCELLED — err.jobError has the reason.
    }
    if (err instanceof APITimeoutError) {
        // The deadline elapsed before the job finished.
    }
}
```

`waitFor` 是一个 **客户端循环** ——不是服务器功能. 它决定了 `SUCCESS`掷出 `JobFailedError` 打开 `ERROR`编号 :`CANCELLED`,以及 `APITimeoutError` 在最后期限.

## 错误

每个非-2xx响应都会丢出一个打出的错误. 课由问题决定 `code` 首先,返回到 HTTP 状态类,用于任何未知/缺位代码 (所以一个新的服务器代码从不突破) `instanceof` 处理).

```ts
import {
    APIError,
    AuthenticationError,
    PermissionDeniedError,
    NotFoundError,
    ConflictError,
    ValidationError,
    RateLimitError,
    QuotaExhaustedError,
    APIServerError,
    APIConnectionError,
    APITimeoutError,
} from '@aishorty/sdk'

try {
    await shorty.usage.get()
} catch (err) {
    if (err instanceof QuotaExhaustedError) {
        // Period allowance spent — back off until the next window.
    } else if (err instanceof RateLimitError) {
        console.log('retry after', err.retryAfterSeconds, 's')
    } else if (err instanceof APIError) {
        console.log(err.status, err.code, err.title, err.detail, err.requestId)
        console.log(err.errors) // field-level validation errors, when present
    }
}
```

每个 `APIError` 携带 `status`, (中文(简体) ), `code`, (中文(简体) ), `problemType`, (中文(简体) ), `title`, (中文(简体) ), `detail`, (中文(简体) ), `requestId`, (中文(简体) ), `errors?`, (中文(简体) ), `headers`,和(关于429s) `retryAfterSeconds`编辑 `.message` 实值 `title: detail (request_id)` 并且从不包含您的 API 密钥.

### 错误代码引用

| 代码 | 状态 | SDK 错误类 |
| --- | --- | --- |
| `unauthorized` | 401 (中文(简体) ) | `AuthenticationError` |
| `invalid_api_key` | 401 (中文(简体) ) | `AuthenticationError` |
| `insufficient_scope` | 403 (韩语) | `PermissionDeniedError` |
| `feature_not_enabled` | 403 (韩语) | `PermissionDeniedError` |
| `resource_not_found` | 404 (韩语) | `NotFoundError` |
| `idempotency_conflict` | 409个 | `ConflictError` |
| `idempotency_in_progress` | 409个 | `ConflictError` |
| `resource_not_ready` | 409个 | `ConflictError` |
| `validation_failed` | 400个 | `ValidationError` |
| `idempotency_key_reused` | 422个 | `ValidationError` |
| `request_too_large` | 413号 | `ValidationError` |
| `rate_limited` | 429个 | `RateLimitError` |
| `quota_exhausted` | 429个 | `QuotaExhaustedError` |
| `internal_error` | 500个 | `APIServerError` |
| `service_unavailable` | 第503条 | `APIServerError` |

运输级别失败 `APIConnectionError` (与 `cause`)或(或) `APITimeoutError`。 。 。 .

## 检讨和公正

SDK 自动重试瞬间故障至 `maxRetries` 时间 第一次尝试后( 默认 2) .

**复试:** 连接出错 ^ 每一次超时 `408` • 妇女 `429` `rate_limited` (或 a 个) `429` 没有可解析代码)- `500` 编号 : `502` 编号 : `503` 编号 : `504`。 。 。 .

**从未重复过 :** `429` `quota_exhausted` (支出期间津贴——重试) 有别的吗 `4xx` 请求您通过自己的程序中止 `signal`。 。 。 .

**备份 :** (单位:千美元) `Retry-After` 标题在出现时是荣耀的(均为三角秒) 和 HTTP 日期表,上限为60s;否则全速回转, `random(0, min(0.5 · 2^attempt, 8))` 秒数.

**邮政安全:** 一个不安全的 `POST` 被重审 **仅限** 当它携带一个 `Idempotency-Key`。这三种方法是自动生成和再利用 页:1 **不变** 每次重试都按键,所以重试被复制 服务器侧 。 自己通过 `opts.idempotencyKey` 做一个调用独能 整个进程重新启动 :

```ts
await shorty.summaries.create(
    { source: 'text', content: '…' },
    { idempotencyKey: 'my-stable-key-123' },
)
```

`client.request(...)` 邮递员是 **没有** 重审,除非你通过一个 `idempotencyKey` 你自己来.

## 网络呼号

校验进入的短网 `verifyWebhookSignature`它执行 [标准网络呼号](https://www.standardwebhooks.com/) v1计划(HMAC-SHA256, `webhook-id` 编号 : `webhook-timestamp` 编号 : `webhook-signature` 信头,旋转通过 多个空间分隔的签名,5分钟的回放容受度,恒定时间 页:1.

```ts
import { verifyWebhookSignature } from '@aishorty/sdk'

// Express example — note express.raw(), NOT express.json():
app.post('/webhooks/shorty', express.raw({ type: '*/*' }), (req, res) => {
    const result = verifyWebhookSignature({
        payload: req.body, // the RAW body (Buffer/Uint8Array or string)
        headers: req.headers, // Headers object or lowercase-keyed record
        secret: process.env.SHORTY_WEBHOOK_SECRET!, // whsec_…
    })
    if (!result.valid) {
        return res.status(400).json({ error: result.reason })
    }
    // Safe to handle. Parse the body only AFTER verifying.
    const event = JSON.parse(Buffer.from(req.body).toString('utf8'))
    res.sendStatus(200)
})
```

> **仅限生身.** 你必须核实 **精确字节** 你收到了吗? 别 `JSON.parse` 再来..`JSON.stringify` 在核实之前 重排序列化重排序按键并更改白空格, 而白空格 **将** 失败 核查。 在自动解析JSON的框架中,首先抓取生体 (例如:. `express.raw()`,或 `await request.text()` 在Next.js路线中.

`verifyWebhookSignature` 返回歧视性结果 :

```ts
type WebhookVerifyResult =
    | { valid: true }
    | {
          valid: false
          reason:
              | 'missing_headers'
              | 'malformed_timestamp'
              | 'timestamp_out_of_tolerance'
              | 'no_matching_signature'
      }
```

## 许可证

麻省理工学院

## 常见问题

### @aishorty/sdk 是什么？

官方 TypeScript SDK for the Shorty 公用API \(aishorty\.com/v一\)\.

### 如何安装 @aishorty/sdk？

在项目目录运行 npm install @aishorty/sdk，或使用 pnpm add / yarn add / bun add。

### @aishorty/sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @aishorty/sdk 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @aishorty/sdk 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @aishorty/sdk 可以商用吗？

@aishorty/sdk 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @aishorty/sdk 的下载量有多少？

根据 npm 官方下载统计，@aishorty/sdk 在 2026/10/05 – 2026/11/03 这 30 天内被下载 15,904 次，日均约 530 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @aishorty/sdk 还在维护吗？

最新版本 0\.1\.0 发布于 2026/07/29（3 个月前）；至今共发布 1 个版本，其中过去 12 个月发布了 1 个；首次发布于 2026/07/29。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

