@coloop-ai/respondent-sdk

中文文档
0.1.0发布于 2026/09/22MITTypeScriptESM + CJS近 30 天下载 1.9万

Type-security SDK for the President.io Partner API,由提供者的OpenAPI spec生成.

中文使用文档
文档目录18 节
  1. 安装
  2. 快开始
  3. 环境
  4. 认证
  5. 处理错误
  6. 请求超时
  7. 取消请求
  8. 观察请求
  9. 倾斜
  10. 高级别方法
  11. 网络呼号
  12. 提供方的文档和没有的
  13. 生成 Zod 计划
  14. 生成客户端访问
  15. 在提供者的类别中已知的怪事
  16. 脚本
  17. 节点版本
  18. 许可证

@ coloop-ai/ 答复者- sdk

License: MIT TypeScript

类型安全客户端绑定 答复者.io 合伙人API. 操作来自提供者的 OpenAPI 文档和 包裹在一个基因组SDK.

项目由CoLoop维护,不附属于或核可 由答复者.io——在使用前审查其API术语.

安装

pnpm add @coloop-ai/respondent-sdk

zod 是一个运行时间依赖( e)^3.25.0 || ^4.0.0(笑声) (掌声) 生成 Zod 计划导入自 zod/v4。 。 。 .

快开始

import { RespondentSdk } from '@coloop-ai/respondent-sdk'

const respondent = new RespondentSdk({
  apiKey: process.env.RESPONDENT_API_KEY!, // sent as x-api-key
  apiSecret: process.env.RESPONDENT_API_SECRET!, // sent as x-api-secret
  timeoutMs: 10_000, // abort requests that hang for 10s
})

// Lookup IDs differ between staging and production, so resolve them at
// runtime rather than hardcoding them.
const topics = await respondent.lookups.topics({ pageSize: 1 })
const topicId = topics.results[0]?.id
if (!topicId) throw new Error('No project topics on this environment')

const project = await respondent.projects.create({
  publicTitle: 'Coffee habits study',
  publicInternalName: 'coffee-habits-q1',
  targetMarketType: 'b2c',
  typeOfResearch: 'remote',
  targetResearchMethodology: 'oneOnOne',
  participantTimeRequiredMinutes: 30,
  incentiveAmount: 50,
  targetNumberOfParticipants: 5,
  externalResearcher: {
    researcherId: 'researcher-1',
    researcherName: 'Ada Lovelace',
    bookingUrl: 'https://example.com/book',
  },
  targetProjectTopics: [topicId],
})

await respondent.screenerQuestions.create(project.id, {
  text: 'How often do you drink coffee?',
  questionType: 'radio',
  answers: [
    { text: 'Daily', answerValue: 1 }, // 1 qualifies
    { text: 'Never', answerValue: 2 }, // 2 disqualifies
  ],
})

// `publicDescription` is required at publish time, so set it first.
await respondent.projects.update(project.id, {
  publicDescription: 'A 30 minute chat about how you drink coffee.',
})

await respondent.projects.publish(project.id)

然后让每个申请人走进招募周期:

const responses = await respondent.screenerResponses.list(project.id, {
  status: 'PENDING',
})

for (const response of responses.results ?? []) {
  await respondent.screenerResponses.qualify(project.id, response.id, {
    qualifyStatus: true,
    qualifiedOverriden: false,
    disqualifyReasons: [],
    message: '',
  })

  await respondent.screenerResponses.invite(project.id, response.id, {
    meetingLink: 'https://example.com/session',
    bookingLink: 'https://example.com/book',
  })
}

// Then, in a later request — only once the session has actually happened,
// because this is what starts the incentive payment:
//
//   await respondent.screenerResponses.markAttended(projectId, responseId)

一个可运行的版本生活在 examples/recruit-participants-demo.ts。 。 。 .

环境

环境基础 URL
生产https://api.respondent.io
粘贴https://api-staging.respondent.io

生产是默认的。 目标通过导出常数中转 :

import {
  RESPONDENT_STAGING_BASE_URL,
  RespondentSdk,
} from '@coloop-ai/respondent-sdk'

const respondent = new RespondentSdk({
  apiKey: process.env.RESPONDENT_STAGING_API_KEY!,
  apiSecret: process.env.RESPONDENT_STAGING_API_SECRET!,
  baseUrl: RESPONDENT_STAGING_BASE_URL,
})

粘接和生产是独立的世界: 单独的证书,单独的 网络用户,以及 不同的查找标识 工业、技能、专题和工作 标题。 运行时解析搜索ID respondent.lookups.* 改为 硬编码.

提供者的 OpenAPI 文档只声明中转服务器 。 生产 URL来自 他们的文档,则 生成客户端的默认值被绑定为生产 openapi-ts.config.ts。 。 。 .

认证

每个请求都带两个信头, x-api-key (身份证)和 x-api-secret (密语). 全权证书由答辩方伙伴小组签发 生产准入需要经过审查的中试演示和 签署了《生活津贴》。 没有OAuth流量,也没有文件记载的范围模型.

证书和配置客户端保存于 #private 字段,没有 所以记录或连载 RespondentSdk 实例 无法打印,错误包含一个编辑的请求摘要而不是 Request 对象。 软件包没有导出 到达配置客户端: 生成的操作为平面 函数将客户端作为参数,所以没有类持有 建立客户登记册.

服务器控制的文本也被擦除。 答复头被减为a 名称的简短允许列表 — 一个标题 NAME 也由服务器控制, 所以一个 清单中未包括其价值—— 以及尚存价值, 和 statusText 和有效载荷, 发生任何密钥或 密钥替换为 [redacted]。将信息、代码和细节读回 所以它们也被覆盖了 一个反映 x-api-key 回来 X-Request-Id,或引用到错误消息中,或回答 带有一个以它命名的标题,但不能将其设置在错误上. cause 这是 基本错误,附则不变.

SDK也设定了 redirect: 'error'。节点将自定义信头转发到 源码变化方向调整——不同于 Authorization - 所以在重新定向后 将手 x-api-key 财务报告和审定财务报表 x-api-secret 指向任何主机重定向名称。 A 类 重定向请求以 a 失败 RespondentSdkTransportError 换句话说.

处理错误

每一个 SDK 产生的故障都会产生一个子类: RespondentSdkError,所以请 失败模式可以区分 :

错误升起时cause
RespondentSdkApiErroraPI以非-2xx状态(status, (中文(简体) ), statusText, (中文(简体) ), payload, (中文(简体) ), responseHeaders, (中文(简体) ), code, (中文(简体) ), detail(中文(简体) )无——已读 payload
RespondentSdkTransportError没有到达任何回复——DNS、连接重设或拒绝重定向隐藏的获取错误
RespondentSdkResponseError其身体无法解码的成功状态(status, (中文(简体) ), statusText, (中文(简体) ), responseHeaders(中文(简体) )页:1 SyntaxError
RespondentSdkTimeoutError配置内容 timeoutMs 逾期(timeoutMs(中文(简体) )无——已读 timeoutMs

一个失败是故意的不是 SDK 错误: 当你通过您的 拥有 AbortSignal它拒绝你 signal.reason 完全如您所愿,你已经准备好了.

每个 SDK 错误都带有编辑请求摘要 request (单位:千美元)url, (中文(简体) ), method, (中文(简体) ), 标题 x-api-key 编号 : x-api-secret 改为 [redacted]),以及 携带 cause 仅当存在潜在错误时。 没有带错误 Response数字 : RespondentSdkApiError 财务报告和审定财务报表 RespondentSdkResponseError 曝光 status, (中文(简体) ), statusText (单位:千美元) responseHeaders 地图代替。 那张地图只能保存 允许的列表标题 retry-after,利率限制头, content-type, (中文(简体) ), date 和请求编号头——其数值被擦除; 每个其它标题都被删除,名字也包括在内. isRespondentSdkError 与其中任何一个匹配; isRespondentSdkApiError, (中文(简体) ), isRespondentSdkTransportError, (中文(简体) ), isRespondentSdkResponseError 财务报告和审定财务报表 isRespondentSdkTimeoutError 狭.

import {
  RespondentSdk,
  isRespondentSdkApiError,
} from '@coloop-ai/respondent-sdk'

try {
  await respondent.projects.close(projectId, {})
} catch (error) {
  if (!isRespondentSdkApiError(error)) throw error

  if (error.status === 429) {
    console.warn('Respondent throttled request', error.payload)
    return
  }

  throw new Error(
    `Failed to close project (${String(error.status)}): ${error.message}`,
  )
}

提供者不记录一个错误响应计划, 及其 OpenAPI 文档未声明出错机构. RespondentSdkApiError 因此,探测 error, (中文(简体) ), message 财务报告和审定财务报表 detail 字段,用于可读信息并坠落 回HTTP状态线. error.payload 总是持有生体.

费率限额记录为250项请求/秒(500起,100 000 000起/天) 和50项请求/第二次(100起,200 000起/日)进行中。 429号 反应机构和任何 Retry-After 头为无相.

请求超时

设定 timeoutMs 以中止超过期限的请求。 最后期限涵盖 读取响应正文,而不仅仅是接收响应头,所以是一个服务器 答案,然后摊子仍然游走它。 SDK拒绝 RespondentSdkTimeoutError,可以视之为可重试.

最多只能是正数 2_147_483_647 (约24.8天)和 建筑师会投出相反的. setTimeout 将更长的延迟回合包成 1ms,所以很长的最后期限 几乎会立即中止所有请求.

import {
  RespondentSdk,
  RespondentSdkTimeoutError,
} from '@coloop-ai/respondent-sdk'

const respondent = new RespondentSdk({
  apiKey: process.env.RESPONDENT_API_KEY!,
  apiSecret: process.env.RESPONDENT_API_SECRET!,
  timeoutMs: 5_000,
})

try {
  await respondent.projects.list()
} catch (error) {
  if (error instanceof RespondentSdkTimeoutError) {
    console.warn('Respondent request timed out, retrying shortly')
  }
}

取消请求

每个操作都使用带有 AbortSignal数字 :

const controller = new AbortController()
setTimeout(() => controller.abort(new Error('user navigated away')), 1_000)

await respondent.projects.list(
  { status: 'DRAFT' },
  {
    signal: controller.signal,
  },
)

电话用信号拒绝 reason 完全如您所愿,你已经准备好了 一个配置 timeoutMs 仍然应用在您的信号上; 无论哪个火先获胜.

观察请求

过 onRequestSettled 以便他听到每一个请求,一旦它解决, 无论它成功还是失败。 该事件带有已编辑的请求摘要 (单位:千美元)url, (中文(简体) ), method,并替换了带有证书的页眉 [redacted], (中文(简体) ), 回应 status 当一个人到达时, durationMs,以及 error 当呼叫时 拒绝:非-2xx状态的 SDK 错误、运输故障或超时, 或你自己的流产原因。 它用于伐木和测量,不能 掷出.

const respondent = new RespondentSdk({
  apiKey: process.env.RESPONDENT_API_KEY!,
  apiSecret: process.env.RESPONDENT_API_SECRET!,
  onRequestSettled: (event) => {
    const { method, url } = event.request
    if (event.error === undefined) {
      console.info(`respondent ${method} ${url} ${String(event.status)}`)
    } else {
      console.error(`respondent ${method} ${url} failed`, event.error)
    }
  },
})

一个边缘:2xx的身体无法被解码,报告时有其状态,没有 error因为反应本身还不错 电话仍然拒绝 RespondentSdkResponseError。 。 。 .

倾斜

列表终点 page (默认) 1, (中文(简体) ), pageSize (默认) 50和 includeCount (默认) false返回时 { totalResults?, page, pageSize, results }。 。 。 . totalResults 只有在您通过时才出现 includeCount: true。 。 。 .

高级别方法

RespondentSdk 将操作组合成模块:

  • respondent.projects —— 说 list, (中文(简体) ), create, (中文(简体) ), retrieve, (中文(简体) ), update, (中文(简体) ), delete, (中文(简体) ), copy, (中文(简体) ), publish, (中文(简体) ), pause, (中文(简体) ), close, (中文(简体) ), audienceSizeEstimate, (中文(简体) ), replaceExternalScreenerQuestions, (中文(简体) ), uploadFile, (中文(简体) ), pitchSuggestions。 。 。 .
  • respondent.screenerQuestions —— 说 list, (中文(简体) ), create, (中文(简体) ), replaceAll, (中文(简体) ), retrieve, (中文(简体) ), update, (中文(简体) ), delete, (中文(简体) ), reorder。 。 。 .
  • respondent.screenerResponses —— 说 list, (中文(简体) ), retrieve, (中文(简体) ), payoutSummary, (中文(简体) ), qualify, (中文(简体) ), invite, (中文(简体) ), schedule, (中文(简体) ), markAttended, (中文(简体) ), markNoShow, (中文(简体) ), reject, (中文(简体) ), report, (中文(简体) ), favorite, (中文(简体) ), hide, (中文(简体) ), cancelInvite, (中文(简体) ), cancelBooking, (中文(简体) ), cancelBookingAndReinvite, (中文(简体) ), participantCancelBooking, (中文(简体) ), ingestExternalScreenerAnswers, (中文(简体) ), payout。 。 。 .
  • respondent.quota —— 说 create, (中文(简体) ), retrieve, (中文(简体) ), update, (中文(简体) ), delete。 。 。 .
  • respondent.webhooks —— 说 list, (中文(简体) ), create, (中文(简体) ), retrieve, (中文(简体) ), deactivate, (中文(简体) ), listEventTypes, (中文(简体) ), simulate。 。 。 .
  • respondent.pricing —— 说 balanceSummary。 。 。 .
  • respondent.profiles —— 说 retrieve, (中文(简体) ), createTestParticipant (只结.
  • respondent.teamRespondents —— 说 list, (中文(简体) ), retrieve, (中文(简体) ), batchInvite。 。 。 .
  • respondent.messaging —— 说 conversations (单位:千美元)list, (中文(简体) ), create, (中文(简体) ), retrieve, (中文(简体) ), update, (中文(简体) ), markAsRead, (中文(简体) ), addParticipant, (中文(简体) ), removeParticipant和 messages (单位:千美元)list, (中文(简体) ), retrieve, (中文(简体) ), inbox, (中文(简体) ), create) (中文(简体) ). 常务代表 (单位:千美元)listConversations, (中文(简体) ), createConversation, (中文(简体) ), listMessages, (中文(简体) ), createMessage, (中文(简体) ), inbox坐在舱内本身.
  • respondent.lookups —— 说 values, (中文(简体) ), industries, (中文(简体) ), jobTitles, (中文(简体) ), skills, (中文(简体) ), topics。 。 。 .

终点 提供者的标记已贬值(GET /v1/teams/{teamId}/projects, (中文(简体) ), POST /v1/messaging/messages, 团队范围收件箱, 和腐烂的 添加- participant 路由) 没有被包. 它们仍然可以通过 生成客户端 .

网络呼号

Webhook 有效载荷和签名计划不在提供者的 OpenAPI 中 文档,所以 @coloop-ai/respondent-sdk/webhooks 和Zod一起做手模,还有.. 添加签名验证 .

命令事项: 校验字节, 存储事件并声明其 id 在一个 原子步骤,回答2xx,只有这样,工作才能完成——从中读回 存储记录.

使这种变化持久化的活性:一行被储存在工作之前一直等待 成功, 唯一开始工作的事情 是投票 等待的行, 因此,在索赔交易之外,没有什么东西可以拖取交货.

import type { UnknownWebhookEvent } from '@coloop-ai/respondent-sdk/webhooks'
import {
  WebhookEvent,
  getWebhookSignatureHeader,
  verifyAndDedupeWebhook,
} from '@coloop-ai/respondent-sdk/webhooks'

/**
 * Write the whole event down and claim its `uuid`, in ONE atomic step — a
 * unique index on `uuid` plus an "insert, ignore conflict" statement that
 * stores the payload alongside it.
 *
 * Inserting the `uuid` on its own is NOT "processed". It records only that the
 * event is safely on disk. Two concurrent copies of a replay both look new if
 * the check and the claim are separate steps.
 */
async function claimAndStore(
  event: UnknownWebhookEvent,
): Promise<'stored' | 'duplicate'> {
  const inserted = await db
    .insertInto('respondent_webhook_inbox')
    .values({ uuid: event.uuid, payload: JSON.stringify(event) })
    .onConflict((c) => c.column('uuid').doNothing())
    .executeTakeFirst()
  return inserted.numInsertedOrUpdatedRows === 1n ? 'stored' : 'duplicate'
}

export async function handleWebhook(request: Request) {
  // Read the RAW BYTES, before any JSON parsing. Not `request.text()`: that
  // decodes leniently, so it has already replaced invalid UTF-8 with U+FFFD
  // before the SDK can reject the body.
  const rawBody = new Uint8Array(await request.arrayBuffer())

  const outcome = await verifyAndDedupeWebhook({
    rawBody,
    signatureHeader: getWebhookSignatureHeader(request.headers),
    privateKey: process.env.RESPONDENT_WEBHOOK_PRIVATE_KEY!,
    claimAndStore,
  })

  if (outcome.status === 'invalid_signature') {
    return new Response('Forbidden', { status: 403 })
  }
  if (outcome.status === 'stored') {
    // A nudge, not the trigger. The row is already pending on disk and the
    // poll below picks it up regardless, so a failed wake-up strands nothing —
    // which is why its failure is swallowed rather than answered non-2xx.
    await wakeWebhookWorker().catch(() => {})
  }
  // A duplicate or an unparseable body is 2xx too: the provider retries
  // anything else, and a replay must not do the work twice.
  return new Response('OK')
}

工作开始于对尚未完成的行的民意调查,所以从不 取决于上面的警钟是否成功:

// Run this on a schedule, and on each wake-up.
async function drainPendingDeliveries() {
  const pending = await db
    .selectFrom('respondent_webhook_inbox')
    .select(['uuid'])
    .where('processedAt', 'is', null)
    .orderBy('receivedAt')
    .limit(100)
    .execute()

  for (const row of pending) {
    await processStoredDelivery(row.uuid)
  }
}

async function processStoredDelivery(uuid: string) {
  const row = await db
    .selectFrom('respondent_webhook_inbox')
    .select(['payload'])
    .where('uuid', '=', uuid)
    .where('processedAt', 'is', null)
    .executeTakeFirst()
  if (!row) return // already processed, or never stored

  const parsed = WebhookEvent.safeParse(JSON.parse(row.payload))
  if (parsed.success) {
    switch (parsed.data.event) {
      case 'SCREENER_RESPONSES.CREATED': {
        const { id, projectId } = parsed.data.payload.resource
        // Payloads carry IDs only — fetch the response to read it.
        const response = await respondent.screenerResponses.retrieve(
          projectId,
          id,
        )
        break
      }
      case 'PROJECTS.UPDATED': {
        console.log(parsed.data.payload.resource.updatedFields)
        break
      }
    }
  } else {
    console.warn('Unhandled webhook payload', parsed.error)
  }

  // Only now is the delivery processed.
  await db
    .updateTable('respondent_webhook_inbox')
    .set({ processedAt: new Date() })
    .where('uuid', '=', uuid)
    .execute()
}

在请求处理人内部进行业务工作,在索赔之后,如何 交货丢失: uuid 已经声称,所以当工作抛出 提供者的重试作为复制品回来,工作永远不会发生. 储存 事件首先使重试没有必要——记录在磁盘上,a 抛出它等待下一次尝试.

紧接后 claimAndStore 返回失败,当队列是 唯一触发器: 行会犯, 排队抛出, 提供者的重试 读作重复, 从来没有运行过作品。 要么写工作 在与收件箱行相同的交易中,或如上所述,对待决交易进行投票 排行并视入等为最优化.

A 类 Uint8Array 一旦签名, 机体就用致命的 UTF-8 验证解码 已经核实了,所以一个不合法的UTF-8的尸体 回来了作为 malformed_body 而不是被修复。 宽放的解码器取代 U+FFFD 用于 无效序列, JSON.parse 接受已修复的文本, 以及您的事件 然后商店就是供货商从未送来的 检查只用字节 : 通过 new Uint8Array(await request.arrayBuffer()),因为 await request.text() 已经为您做了宽大解码 string rawBody 当它到达时被接受.

如果您不想重新播放检查, 请用手进行验证 : verifyWebhookSignatureFromRawBody 抓起线条字节 verifyWebhookSignatureFromParsedBody 散开 JSON.stringify(parsedBody)读取 下一节,然后选择.

这五个事件类型是 PROJECTS.UPDATED, (中文(简体) ), SCREENER_RESPONSES.CREATED, (中文(简体) ), SCREENER_RESPONSES.UPDATED, (中文(简体) ), MESSAGES.CREATED 财务报告和审定财务报表 CONVERSATIONS.CREATED。 。 。 . WebhookEvent 双倍的受歧视的工会类型 (单位:千美元)import type { WebhookEvent })和工会验证人 (单位:千美元)WebhookEvent.safeParse) (中文(简体) ). 每个事件计划都是个松散的物体,所以 提供商后来补充说,保留而不是剥去. UnknownWebhookEvent 接受 SDK 尚未建模的事件类型 .

提供方的文档和没有的

这个 privateKey 用于签名的返回方式 POST /v1/webhooks,还有 以 GET /v1/webhooks 财务报告和审定财务报表 GET /v1/webhooks/{webhookId} 所有三个答案都与 同样的 WebhookDto ——所以一个丢失的密钥可以被读回而不是被再创建. 供养者 只签名样本 显示一个HMAC在车体上方, 底部64- 编码, 在 Respondent-Webhook-Signature 页眉为 <algorithm>=<signature>。 。 。 .

三个空白问题:

  1. 散列算法没有文献记录 . 他们的样本解析了算法 退出头部值本身,并发布无示例头。 因为 信头是攻击者控制的, 校验只接受一个 允许列表( e)sha256, (中文(简体) ), sha512 (默认情况下). 把它加宽 allowedAlgorithms 一旦提供者确认他们发送了哪一个.
  2. 他们签的字节在任何地方都没有说明. 他们的花草样本 JSON.stringify(request.body) ——被解析并被重序的对象——即 无法保证复制到线上的字节。 这个SDK 船舶的读取和主张都没有证明: verifyWebhookSignatureFromRawBody (默认和什么) verifyAndDedupeWebhook (b) 将交付的字节拖走 verifyWebhookSignatureFromParsedBody 散开 JSON.stringify(parsedBody)。 。 。 . 只有真正的送货才能解决问题. 将网点指向终点 记录原始正文和签名头,并发送一个与 respondent.webhooks.simulate(webhookId, { event }),看看谁是援助者 返回时 true直到你这样做, 将选择视为未经证实.
  3. 没有时间戳头和回放保护. HMAC 证明 真实性,而非新鲜度,供应商对最多5个交货进行重试 时间。 关于事件的重复 uuid —— 说 verifyAndDedupeWebhook 这样做是为了 你,一个原子 claimAndStore 将事件记录为 它声称身份证明.

两个较小的硬化笔记: 载有多个签名头的快递 以未署名方式处理, 一份文摘只有在有条形加法的情况下才解码 基础64. Buffer.from(value, 'base64') 自己默默接受跟踪 垃圾,并接受多个拼写 相同的文摘.

其他行动事实:每个小队都有1个正在运行的网页,事件起火 只针对通过 API 创建的项目, 您必须在 3 秒内返回 2xx, 并且 故障每隔10分钟重审5次。 网络呼号 配置在装配中不结转到生产中.

生成 Zod 计划

每个 OpenAPI 组件计划也作为 Zod 计划在下面排放 @coloop-ai/respondent-sdk/zod名称 z<SchemaName>。用它们来作曲 供货商在自己计划中的语句:

import * as z from 'zod/v4'
import { zGender, zScreenerResponseStatus } from '@coloop-ai/respondent-sdk/zod'

const Participant = z.object({
  gender: zGender,
  status: zScreenerResponseStatus,
})

生成的文件导入自 zod/v4,这决定了两者 [email protected]+ 财务报告和审定财务报表 zod@4。 。 。 .

生成客户端访问

如果您需要完全控制请求选项, 请呼叫生成的操作 直接说 每个函数都是简单的函数,它占用了您配置的客户端; 没有生成的类,因此没有保存配置的注册 客户:

import { getV1Projects, sdk } from '@coloop-ai/respondent-sdk'

const client = sdk.createClient({
  baseUrl: 'https://api.respondent.io',
  headers: {
    'x-api-key': process.env.RESPONDENT_API_KEY!,
    'x-api-secret': process.env.RESPONDENT_API_SECRET!,
  },
  responseStyle: 'data',
})

const response = await getV1Projects({
  client,
  headers: {
    'x-api-key': process.env.RESPONDENT_API_KEY!,
    'x-api-secret': process.env.RESPONDENT_API_SECRET!,
  },
  query: { status: 'DRAFT' },
})

提供者声明 x-api-key 财务报告和审定财务报表 x-api-secret 作为标题参数比较 而不是作为 OpenAPI 安全方案,所以生成的类型需要它们每次调用 即使客户已经设定了 三项行动—— GET /v1/team-respondents, (中文(简体) ), GET /v1/team-respondents/profiles/{profileId} 财务报告和审定财务报表 PUT /v1/team-respondents/batch-invite ——声明完全没有标题参数, 这几乎肯定是一种疏忽 而不是未经证实的 路由; SDK 向每个请求发送证书.

responseStyle 接受 'data' (只有反应机构)或 'fields' (单位:千美元){ data, request, response }) (中文(简体) ). RespondentSdk 用途 'fields' 内部和 返回尸体.

所有请求/答复类型均导出自 @coloop-ai/respondent-sdk。 。 。 .

在提供者的类别中已知的怪事

在此录制, 这样它们不会被误认为 SDK 错误 :

  • CreateB2cProjectDto.targetGenders 编号 : CreateB2bProjectDto.targetGenders 是一个 单人 Gender,而所有其他人口目标 (单位:千美元)targetEthnicities, (中文(简体) ), targetAgeGroups, (中文(简体) ), targetEducation, (中文(简体) ), targetHouseholdIncome)是数组。 复数名有惑.
  • QualifyScreenerResponseDto 标记所有需要的四个字段,包括 拼写错误 qualifiedOverriden 编辑 disqualifyReasons 编号 : message 字段 只有在取消资格时才适用.
  • ProfileLocation.zipcode 财务报告和审定财务报表 ScreenerResponseInvitation.message 声明 "type": "string" 与 "default": null销售商剥离这些缺省 -- 而Zod生成器的代码是不编译的.
  • ScreenerResponsesPaginatedDto 不标记 results 需要时 其他发泡DTO是,所以 response.results 仅此而已.
  • PUT /v1/projects/{projectId}/files/form-data 声明 Content-Type 财务报告和审定财务报表 Content-Length 标题参数 uploadFile 身体财产可选择。 销售者删除两个标题参数并制作 需要文件 : 获取内容设置类型—— 带有多段边框, 任何人事先都不能知道--长度和上传-- 没有文件的电话从来就没有用过.
  • 三次小组答复行动宣布不 x-api-key 编号 : x-api-secret 标题参数, 而其他操作都会这样做 .
  • 文件宣布没有安全方案,没有错误计划,没有429 答复,以及 servers 区块列表只运行.

scripts/normalize-openapi.ts 保持所有三个正常化, 每个报告 当计谋被更新的时候 pnpm run schema:validate 如果失败 卖出的文件会从正常形式中消失.

脚本

  • pnpm run schema:update - 唯一触及网络的脚本:获取 提供者的 OpenAPI 文档, 正常化, 在内存中验证, 然后替换 schemas/openapi.json 解剖论.
  • pnpm run generate - 验证供应商的光谱并再生 src/generated/** 从它。 离线和可复制:始终相同的承诺 生成相同的输出.
  • pnpm run generate:check – 重新生成到抓取目录中并失败 与承诺不同 src/generated。 。 。 .
  • pnpm run schema:validate - 验证销售商的规格并检查它仍然是 已经恢复正常.
  • pnpm run tc - 排入排出量.
  • pnpm run lint – ESLint横跨仓库.
  • pnpm run test -维特.
  • pnpm run test:dist - 烟雾测试 已建成的捆绑 node --test。无 dev工具链,因此它也在节点18上运行. 建设先.
  • pnpm run format - 更漂亮的检查.
  • pnpm run build - 双重无害环境管理/CJS捆绑 dist/ 通过tsdown.
  • pnpm run prepare -运行 build,因此软件包也从 基特语( git)github:Genei-Ltd/respondent-sdk#<sha>) (中文(简体) ).
  • pnpm run check - 计划验证, generate:check,类型检查,林特, 格式检查,构建,测试,然后是 Dist 烟雾测试。 这是运行 在出版前, 以及CI运行.

节点版本

已公布的一揽子目标节点18及以上engines.node) (中文(简体) ). B. 拟订《公约》 SDK需要更新运行时间—— devEngines.runtime 请求22.18+节点,即: 什麽 @hey-api/openapi-ts,ESLint和Vitest需要.

这一差距得到弥补,而不是假设: .github/workflows/check.yml 运行 pnpm run check 在节点22上,然后装入已建成的捆绑并锻炼它们—— 无害环境管理和CJS的切入点,每个子路径,请求,拒绝的再定向 超时和多段上传——在节点18,20,22和24上. 这些烟雾测试 (单位:千美元)tests/dist-smoke.mjs运行 pnpm run test:dist(a) 使用情况 node --test 编辑 软件包本身的运行时间依赖性, 仅此而已 .

许可证

根据麻省理工学院的许可获释. 见 LICENSE 详细情况.

版本与发布记录

@coloop-ai/respondent-sdk 共发布 1 个版本,首次发布于 2026/09/22;过去 12 个月发布了 1 个版本。

版本发布日期距今
0.1.0latest2026/09/221 个月前

关于 @coloop-ai/respondent-sdk 的常见问题

@coloop-ai/respondent-sdk 是什么?

Type-security SDK for the President.io Partner API,由提供者的OpenAPI spec生成.

如何安装 @coloop-ai/respondent-sdk?

在项目目录运行 npm install @coloop-ai/respondent-sdk,或使用 pnpm add / yarn add / bun add。

@coloop-ai/respondent-sdk 支持 TypeScript 吗?

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

@coloop-ai/respondent-sdk 支持 ESM 还是 CommonJS?

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

@coloop-ai/respondent-sdk 需要什么版本的 Node.js?

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

@coloop-ai/respondent-sdk 可以商用吗?

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

@coloop-ai/respondent-sdk 的下载量有多少?

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

@coloop-ai/respondent-sdk 还在维护吗?

最新版本 0.1.0 发布于 2026/09/22(1 个月前);至今共发布 1 个版本,其中过去 12 个月发布了 1 个;首次发布于 2026/09/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。