文档
计费
订阅信息、Stripe 结帐/门户集成、试用维护和签名的 Webhook 摄取。
从英文自动翻译。 查看英文原文
将这些请求发送到您自己正在运行的 sidecar。值保留在此浏览器中。
这是如何运作的
sidecar 侦听启动时选择的环回端口并将其打印在其中 ready 线;使用该 URL 和 CADCAMFUN_TOKEN 它是从开始的。请求直接从该页面发送到该地址。
sidecar 仅将 CORS 标头发送到 Tauri 源并发送到 http://localhost 或 http://127.0.0.1 在任何端口上。浏览器会阻止托管文档的响应,因此请在本地运行文档(bun run dev 中 packages/web) 使用游乐场,或将请求复制为curl。要在不接触真实数据的情况下进行实验,请使用以下命令启动 sidecar CADCAMFUN_DATA_DIR 指向一个一次性目录 - 请参阅 aPI 演练.
运营
15 个端点,位于 billing 组,由 sidecar 自己生成 开放API文档。受保护的操作需要 Authorization: Bearer $CADCAMFUN_TOKEN;看 验证。行为和限制在 子系统指南.
| 得到 | /api/subscription/info | billing.info |
| 得到 | /api/subscriptions | billing.current |
| 邮政 | /api/subscriptions | billing.subscribe |
| 邮政 | /api/subscriptions/portal | billing.portal |
| 得到 | /api/better-auth-stripe/subscription | billing.baGet |
| 邮政 | /api/better-auth-stripe/subscription | billing.baCheckout |
| 放 | /api/better-auth-stripe/subscription | billing.baUpdate |
| 删除 | /api/better-auth-stripe/subscription | billing.baCancel |
| 邮政 | /api/better-auth-stripe/billing-portal | billing.baPortal |
| 邮政 | /api/better-auth-stripe/feature-access | billing.baFeature |
| 邮政 | /api/better-auth-stripe/sync | billing.baSync |
| 得到 | /api/cron/update-expired-trials | billing.cronGet |
| 邮政 | /api/cron/update-expired-trials | billing.cronPost |
| 得到 | /api/health/stripe | billing.stripeHealth |
| 邮政 | /api/webhooks/stripe | billing.stripeWebhook |
/api/subscription/info
billing.info 需要 Authorization: Bearer <token>.
| 姓名 | 在 | 类型 | 必需的 |
|---|---|---|---|
| userId | 询问 | 细绳 | null | 选修的 |
200 目的 application/json
{ id: string plan: string status: string currentPeriodEnd: string | null cancelAtPeriodEnd: boolean | null stripeCustomerId: string | null stripeSubscriptionId: string | null }
400 BillingBadRequestEncoded application/json
BillingBadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
403 BillingForbiddenEncoded application/json
BillingForbiddenEncoded
404 BillingNotFoundEncoded application/json
BillingNotFoundEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
响应示例 捕获·400
{
"_tag": "BillingBadRequest",
"error": "User ID is required"
} SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingInfoInput
const result = await client.billing.info({}) curl
curl --request GET "${CADCAMFUN_URL}/api/subscription/info" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
/api/subscriptions
billing.current 需要 Authorization: Bearer <token>.
200 目的 application/json
{ plan: string status: string periodEnd: string | null cancelAtPeriodEnd: boolean isOnTrial?: boolean | null trialEnd?: string | null }
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
响应示例 捕获·200
{
"plan": "FREE",
"status": "active",
"periodEnd": null,
"cancelAtPeriodEnd": false
} SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// no input
const result = await client.billing.current() curl
curl --request GET "${CADCAMFUN_URL}/api/subscriptions" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
billing.subscribe 需要 Authorization: Bearer <token>.
{ priceId?: string | null startTrial?: boolean | null }
200 目的 application/json
{ url?: string | null success?: boolean | null message?: string | null redirectUrl?: string | null }
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
404 NotFoundEncoded application/json
NotFoundEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingSubscribeInput
const result = await client.billing.subscribe({
priceId: "",
startTrial: false
}) curl
curl --request POST "${CADCAMFUN_URL}/api/subscriptions" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
--header "Content-Type: application/json" \
--data-binary @request.json 尝试一下
/api/subscriptions/portal
billing.portal 需要 Authorization: Bearer <token>.
{ returnUrl?: string | null }
200 目的 application/json
{ url: string }
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
404 NotFoundEncoded application/json
NotFoundEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingPortalInput
const result = await client.billing.portal({
returnUrl: ""
}) curl
curl --request POST "${CADCAMFUN_URL}/api/subscriptions/portal" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
--header "Content-Type: application/json" \
--data-binary @request.json 尝试一下
/api/better-auth-stripe/subscription
billing.baGet 需要 Authorization: Bearer <token>.
200 目的 application/json
{ id?: string | null plan: string status: string currentPeriodEnd: string | null cancelAtPeriodEnd: boolean stripeCustomerId?: string | null stripeSubscriptionId?: string | null source: "better-auth" }
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
响应示例 捕获·200
{
"id": "c942817d-0162-4291-84ff-77321d387acc",
"plan": "FREE",
"status": "active",
"currentPeriodEnd": null,
"cancelAtPeriodEnd": false,
"stripeCustomerId": null,
"stripeSubscriptionId": null,
"source": "better-auth"
} SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// no input
const result = await client.billing.baGet() curl
curl --request GET "${CADCAMFUN_URL}/api/better-auth-stripe/subscription" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
billing.baCheckout 需要 Authorization: Bearer <token>.
{ plan?: string | null successUrl?: string | null cancelUrl?: string | null trialDays?: number | "Infinity" | "-Infinity" | "NaN" | null }
200 目的 application/json
{ url: string source: "better-auth" }
400 BillingBadRequestEncoded application/json
BillingBadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingBaCheckoutInput
const result = await client.billing.baCheckout({
plan: "",
successUrl: "",
cancelUrl: "",
trialDays: 0
}) curl
curl --request POST "${CADCAMFUN_URL}/api/better-auth-stripe/subscription" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
--header "Content-Type: application/json" \
--data-binary @request.json 尝试一下
billing.baUpdate 需要 Authorization: Bearer <token>.
{ newPlan?: string | null }
200 目的 application/json
{ success: true message: string source: "better-auth" }
400 BillingBadRequestEncoded application/json
BillingBadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingBaUpdateInput
const result = await client.billing.baUpdate({
newPlan: ""
}) curl
curl --request PUT "${CADCAMFUN_URL}/api/better-auth-stripe/subscription" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
--header "Content-Type: application/json" \
--data-binary @request.json 尝试一下
billing.baCancel 需要 Authorization: Bearer <token>.
200 目的 application/json
{ success: true message: string source: "better-auth" }
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// no input
const result = await client.billing.baCancel() curl
curl --request DELETE "${CADCAMFUN_URL}/api/better-auth-stripe/subscription" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
/api/better-auth-stripe/billing-portal
billing.baPortal 需要 Authorization: Bearer <token>.
{ returnUrl?: string | null }
200 目的 application/json
{ url: string source: "better-auth" }
400 BillingBadRequestEncoded application/json
BillingBadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingBaPortalInput
const result = await client.billing.baPortal({
returnUrl: ""
}) curl
curl --request POST "${CADCAMFUN_URL}/api/better-auth-stripe/billing-portal" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
--header "Content-Type: application/json" \
--data-binary @request.json 尝试一下
/api/better-auth-stripe/feature-access
billing.baFeature 需要 Authorization: Bearer <token>.
{ feature?: string | null features?: unknown | null }
200 目的 application/json
{ feature?: string | null hasAccess?: boolean | null source: "better-auth" features?: Array<{ feature: string hasAccess: boolean error?: string | null }> | null }
400 BillingBadRequestEncoded application/json
BillingBadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingBaFeatureInput
const result = await client.billing.baFeature({
feature: "",
features: null
}) curl
curl --request POST "${CADCAMFUN_URL}/api/better-auth-stripe/feature-access" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
--header "Content-Type: application/json" \
--data-binary @request.json 尝试一下
/api/better-auth-stripe/sync
billing.baSync 需要 Authorization: Bearer <token>.
200 目的 application/json
{ success: true message: string subscription: { id?: string | null plan: string status: string currentPeriodEnd: string | null cancelAtPeriodEnd: boolean stripeCustomerId?: string | null stripeSubscriptionId?: string | null source: "better-auth" } | null source: "better-auth" }
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
500 BillingFailureEncoded application/json
BillingFailureEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// no input
const result = await client.billing.baSync() curl
curl --request POST "${CADCAMFUN_URL}/api/better-auth-stripe/sync" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
/api/cron/update-expired-trials
billing.cronGet 需要 Authorization: Bearer <token>.
| 姓名 | 在 | 类型 | 必需的 |
|---|---|---|---|
| 秘密 | 询问 | 细绳 | null | 选修的 |
200 目的 application/json
{ success: true updatedCount: number | "Infinity" | "-Infinity" | "NaN" message: string timestamp: string }
401 CronUnauthorizedEncoded | CronUnauthorizedEncoded |未经授权的编码 application/json
CronUnauthorizedEncoded | UnauthorizedEncoded
500 CronFailureEncoded application/json
CronFailureEncoded
响应示例 捕获·200
{
"success": true,
"updatedCount": 0,
"message": "Successfully updated 0 expired trials",
"timestamp": "2026-10-15T04:52:23.475Z"
} SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingCronGetInput
const result = await client.billing.cronGet({}) curl
curl --request GET "${CADCAMFUN_URL}/api/cron/update-expired-trials" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
billing.cronPost 需要 Authorization: Bearer <token>.
| 姓名 | 在 | 类型 | 必需的 |
|---|---|---|---|
| 秘密 | 询问 | 细绳 | null | 选修的 |
200 目的 application/json
{ success: true updatedCount: number | "Infinity" | "-Infinity" | "NaN" message: string timestamp: string }
401 CronUnauthorizedEncoded | CronUnauthorizedEncoded |未经授权的编码 application/json
CronUnauthorizedEncoded | UnauthorizedEncoded
500 CronFailureEncoded application/json
CronFailureEncoded
SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// BillingCronPostInput
const result = await client.billing.cronPost({}) curl
curl --request POST "${CADCAMFUN_URL}/api/cron/update-expired-trials" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
/api/health/stripe
billing.stripeHealth 需要 Authorization: Bearer <token>.
200 目的 application/json
{ status: "healthy" message: string timestamp: string service: "stripe" }
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
503 StripeUnhealthyEncoded application/json
StripeUnhealthyEncoded
响应示例 捕获·503
{
"_tag": "StripeUnhealthy",
"status": "unhealthy",
"message": "Stripe is not configured on this installation",
"timestamp": "2026-10-15T04:52:23.476Z",
"service": "stripe"
} SDK示例
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
// no input
const result = await client.billing.stripeHealth() curl
curl --request GET "${CADCAMFUN_URL}/api/health/stripe" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" 尝试一下
/api/webhooks/stripe
billing.stripeWebhook 需要 Authorization: Bearer <token>.
string 200 目的 application/json
{ received: true }
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
获取示例
// Not generated in the Promise SDK (multipart, binary or raw body): call it with fetch.
const response = await fetch(`${process.env.CADCAMFUN_URL}/api/webhooks/stripe`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
}) curl
curl --request POST "${CADCAMFUN_URL}/api/webhooks/stripe" \
--header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
--header "Content-Type: application/octet-stream" \
--data-binary @request-body 尝试一下
此操作需要 application/octet-stream;使用curl 或fetch 示例。
模式
可从该组的参数、主体和响应访问命名模式。一个 ? 标记可选字段; | null 标记可能存在空值的字段。
BadRequestEncoded{ _tag: "BadRequest" message: string }
BillingBadRequestEncoded{ _tag: "BillingBadRequest" error: string }
BillingFailureEncoded{ _tag: "BillingFailure" error: string }
BillingForbiddenEncoded{ _tag: "BillingForbidden" error: string }
BillingNotFoundEncoded{ _tag: "BillingNotFound" error: string }
CronFailureEncoded{ _tag: "CronFailure" success: false error: string timestamp: string }
InternalErrorEncoded{ _tag: "InternalError" message: string }
NotFoundEncoded{ _tag: "NotFound" message: string }
StripeUnhealthyEncoded{ _tag: "StripeUnhealthy" status: "unhealthy" message: string timestamp: string service: "stripe" }
呼叫该群组
操作 ID 的形式为 billing.<name>。生成的Promise SDK(@cadcamfun/api/sdk)将其中大部分暴露为 client.<namespace>.<method>(input), 在哪里 input 是路径参数和主体字段的一个平面对象;每张卡的 SDK 示例显示了确切的访问器和输入类型。不会生成分段上传、二进制或 JavaScript 响应以及原始 Webhook;这些卡片显示 fetch 改为。
import { CadCam, ClientError } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
try {
await client.projects.list()
} catch (error) {
if (error instanceof ClientError) {
// Transport | UnexpectedStatus | UnsupportedContentType | MalformedResponse | SseEventTooLarge
} else {
// a declared error body: switch on error._tag
}
} 故障排除
| 症状 | 可能的原因 | 使固定 |
|---|---|---|
| 每次调用 401 | 上次启动的令牌或丢失 Bearer 前缀 | 发送 Authorization: Bearer <token> 使用边车启动时的令牌。 |
| 在任何事情发生之前的 400 | 主体或参数与架构不匹配 | 将有效负载与卡上的请求架构进行比较。 |
| 在别处可见的记录上出现 403 或 404 | 代理账户不同 | 发送正确的 x-session-token,或使用拥有该记录的本地配置文件。 |
| 409 | 状态冲突,例如重复的名称或过时的分支头 | 重新读取资源并使用当前数据重试。 |
| 尝试显示“被 CORS 阻止” | 这些文档是从非环回源提供的 | 在本地运行文档或将请求复制为curl。 |
| 连接被拒绝 | Sidecar 在新端口上重新启动 | 从新读取端口 ready 行。 |