API 参考

基础 URL: https://open.utm.bar/v1
认证方式: Authorization: Bearer sk_live_xxxxX-API-Key: sk_live_xxxx


短链接

创建短链接

POST /v1/links

所需权限: links:write

请求体

字段类型必填说明
original_urlstring目标跳转 URL
titlestring链接展示名称
custom_codestring自定义短码(a-z A-Z 0-9 - _,长度 2–64)
external_idstring外部系统引用 ID,透传存储(最大 255 字符)
expires_atISO 8601过期时间,null 表示永不过期
utm_sourcestringUTM source 参数
utm_mediumstringUTM medium 参数
utm_campaignstringUTM campaign 参数
utm_termstringUTM term 参数
utm_contentstringUTM content 参数
campaign_idstring将链接归入指定活动(活动 UUID)
domain_idstring自定义域名 ID(来自 POST /v1/domains)
curl -X POST https://open.utm.bar/v1/links \
  -H "Authorization: Bearer sk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "original_url": "https://example.com/page",
    "title": "我的链接",
    "custom_code": "launch-2026",
    "utm_source": "twitter",
    "utm_medium": "social"
  }'

响应 201 Created

{
  "data": {
    "id": "...",
    "code": "launch-2026",
    "short_url": "https://utm.bar/launch-2026",
    "original_url": "https://example.com/page",
    "title": "我的链接",
    "is_active": true,
    "click_count": 0,
    "external_id": "order_98765",
    "expires_at": null,
    "domain_id": null,
    "domain": null,
    "campaign_id": null,
    "utm_source": "twitter",
    "utm_medium": "social",
    "created_at": "2026-05-25T00:00:00Z"
  }
}

传入 domain_id 可绑定自定义域名,详见自定义域名。绑定后 short_url 将使用你自己的域名替代 utm.bar。 自定义短码冲突时返回 409 Conflict


列出短链接

GET /v1/links

所需权限: links:read

查询参数

参数类型默认值说明
pageinteger1页码
page_sizeinteger20每页条数(最大 100)
qstring按标题或目标 URL 搜索
is_activeboolean按启用/禁用状态过滤
curl "https://open.utm.bar/v1/links?page=1&page_size=20" \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK

{
  "data": {
    "items": [ /* 链接对象数组 */ ],
    "total": 42,
    "page": 1,
    "page_size": 20
  }
}

获取单条链接

GET /v1/links/:id

所需权限: links:read

curl https://open.utm.bar/v1/links/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK — 返回单个链接对象。路径参数为创建时返回的链接 id (UUID)。


按 External ID 获取链接

GET /v1/links/external/:external_id

所需权限: links:read

根据创建时传入的 external_id 反向查找短链接,语义与按链接 ID 查找对称。未找到返回 404。

curl https://open.utm.bar/v1/links/external/order_98765 \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK

{
  "data": {
    "id": "...",
    "code": "launch-2026",
    "short_url": "https://utm.bar/launch-2026",
    "original_url": "https://example.com/page",
    "external_id": "order_98765",
    "is_active": true,
    "click_count": 42,
    "domain_id": null,
    "domain": null,
    "campaign_id": null,
    "created_at": "2026-05-25T00:00:00Z"
  }
}

更新链接元数据

PATCH /v1/links/:id

所需权限: links:write

original_urlcode 创建后不可修改。如需更换目标地址,请创建新链接并停用旧的。

请求体(所有字段可选)

字段类型说明
titlestring新标题
expires_atISO 8601 / null更新或清除过期时间
utm_sourcestring更新 UTM source
utm_mediumstring更新 UTM medium
utm_campaignstring更新 UTM campaign
utm_termstring更新 UTM term
utm_contentstring更新 UTM content
curl -X PATCH https://open.utm.bar/v1/links/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer sk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{ "title": "新标题", "expires_at": "2026-12-31T23:59:59Z" }'

响应 200 OK — 返回更新后的链接对象。


禁用链接

POST /v1/links/:id/disable

所需权限: links:delete

curl -X POST https://open.utm.bar/v1/links/550e8400-e29b-41d4-a716-446655440000/disable \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK


启用链接

POST /v1/links/:id/enable

所需权限: links:write

curl -X POST https://open.utm.bar/v1/links/550e8400-e29b-41d4-a716-446655440000/enable \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK


删除链接

DELETE /v1/links/:id

所需权限: links:delete

删除操作不可撤销。如果日后可能还需要这个链接,建议改用禁用操作。

curl -X DELETE https://open.utm.bar/v1/links/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer sk_live_xxxx"

响应 204 No Content


获取点击统计

GET /v1/links/:id/stats

所需权限: links:read

查询参数

参数类型默认值说明
startYYYY-MM-DD近 7 天起始日期(含)
endYYYY-MM-DD今天截止日期(含)
tzIANA 时区名UTC用于按时区聚合日期边界
granularitystringday聚合粒度:day / week / month / year

daily 中的 date 始终为 YYYY-MM-DD 格式,表示该周期的起始日week 为周一,month 为1日,year 为1月1日)。

curl "https://open.utm.bar/v1/links/550e8400-e29b-41d4-a716-446655440000/stats?start=2026-01-01&end=2026-05-25&granularity=month&tz=Asia/Shanghai" \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK

{
  "data": {
    "total_clicks": 1024,
    "unique_clicks": 876,
    "tz": "Asia/Shanghai",
    "granularity": "month",
    "daily": [
      { "date": "2026-01-01", "clicks": 200, "unique_clicks": 180 },
      { "date": "2026-02-01", "clicks": 180, "unique_clicks": 160 }
    ],
    "countries": [
      { "name": "China", "clicks": 600 },
      { "name": "United States", "clicks": 200 }
    ],
    "devices": [
      { "name": "Mobile", "clicks": 700 },
      { "name": "Desktop", "clicks": 300 }
    ],
    "browsers": [
      { "name": "Chrome", "clicks": 500 }
    ],
    "oses": [
      { "name": "Android", "clicks": 400 }
    ],
    "referers": [
      { "name": "Direct", "clicks": 300 },
      { "name": "https://twitter.com", "clicks": 150 }
    ]
  }
}

批量获取点击统计

POST /v1/links/batch-stats

所需权限: links:read

一次请求最多查询 50 条短链接的点击统计,格式与单链接统计接口一致,适合批量展示仪表盘数据。

请求体

字段类型必填说明
idsstring[]链接 ID 数组(UUID,最多 50 条)
startYYYY-MM-DD起始日期,默认近 7 天
endYYYY-MM-DD截止日期,默认今天
tzIANA 时区名时区,默认 UTC
granularitystring聚合粒度:day(默认)/ week / month / year
curl -X POST https://open.utm.bar/v1/links/batch-stats \
  -H "Authorization: Bearer sk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["550e8400-e29b-41d4-a716-446655440000", "660e8400-e29b-41d4-a716-446655440001"],
    "start": "2026-05-01",
    "end": "2026-05-25",
    "tz": "Asia/Shanghai",
    "granularity": "week"
  }'

响应 200 OK

{
  "data": {
    "start": "2026-05-01",
    "end": "2026-05-25",
    "tz": "Asia/Shanghai",
    "granularity": "week",
    "items": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "total_clicks": 1024,
        "unique_clicks": 876,
        "daily": [
          { "date": "2026-04-28", "clicks": 200, "unique_clicks": 180 }
        ],
        "countries": [{ "name": "China", "clicks": 600 }],
        "devices": [{ "name": "Mobile", "clicks": 700 }],
        "browsers": [{ "name": "Chrome", "clicks": 500 }],
        "oses": [{ "name": "Android", "clicks": 400 }],
        "referers": [{ "name": "Direct", "clicks": 300 }]
      },
      {
        "id": "660e8400-e29b-41d4-a716-446655440001",
        "total_clicks": 0,
        "unique_clicks": 0,
        "daily": [],
        "countries": [], "devices": [], "browsers": [], "oses": [], "referers": []
      }
    ]
  }
}

无权限或不存在的链接 ID 该条目会附带 "error" 字段说明原因,不影响其他条目返回。


活动(Campaigns)

活动用于将多条短链接归组,便于整体追踪一次营销投放的效果。

创建活动

POST /v1/campaigns

所需权限: campaigns:write

请求体

字段类型必填说明
namestring活动名称
descriptionstring活动描述
base_urlstring关联的目标网站域名
external_idstring外部系统活动 ID(最大 255 字符,团队内唯一)
curl -X POST https://open.utm.bar/v1/campaigns \
  -H "Authorization: Bearer sk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q2 增长活动",
    "base_url": "https://example.com",
    "external_id": "campaign_q2_2026"
  }'

响应 201 Created

{
  "data": {
    "id": "...",
    "name": "Q2 增长活动",
    "description": "",
    "base_url": "https://example.com",
    "external_id": "campaign_q2_2026",
    "total_links": 0,
    "total_clicks": 0,
    "created_at": "2026-05-25T00:00:00Z",
    "updated_at": "2026-05-25T00:00:00Z"
  }
}

列出活动

GET /v1/campaigns

所需权限: campaigns:read

查询参数

参数类型默认值说明
pageinteger1页码
limitinteger20每页条数(最大 100)

响应 200 OKitems 为活动对象数组,附带 totalpagepage_size


获取活动详情

GET /v1/campaigns/:id

所需权限: campaigns:read

响应 200 OK — 返回单个活动对象。


按 External ID 获取活动

GET /v1/campaigns/external/:external_id

所需权限: campaigns:read

根据创建时传入的 external_id 反向查找活动。未找到返回 404


删除活动

DELETE /v1/campaigns/:id

所需权限: campaigns:write

删除活动不会删除其下的短链接,链接会变为无活动归属状态。

响应 204 No Content


获取活动下的链接

GET /v1/campaigns/:id/links

所需权限: campaigns:read

查询参数

参数类型默认值说明
pageinteger1页码
limitinteger50每页条数(最大 200)

响应 200 OK — 结构与列出短链接一致。


获取活动统计

GET /v1/campaigns/:id/stats

所需权限: campaigns:read

查询参数

参数类型默认值说明
daysinteger30统计近 N 天(最大 365)
curl "https://open.utm.bar/v1/campaigns/campaign-uuid/stats?days=30" \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK

{
  "data": {
    "campaign_id": "...",
    "days": 30,
    "total_clicks": 3840,
    "unique_clicks": 2910,
    "daily": [
      { "date": "2026-05-01", "clicks": 120, "unique_clicks": 95 }
    ],
    "links": [
      {
        "short_code": "launch-tw",
        "utm_source": "twitter",
        "utm_medium": "social",
        "utm_campaign": "launch-2026",
        "clicks": 1200
      }
    ],
    "sources": [
      { "name": "twitter", "clicks": 1200 },
      { "name": "email",   "clicks": 980 }
    ],
    "mediums": [
      { "name": "social", "clicks": 1200 },
      { "name": "cpc",    "clicks": 980 }
    ]
  }
}

自定义域名

绑定你自己的域名(如 s.example.com)作为短链接域名,代替默认的 utm.bar。域名绑定并验证通过后,创建短链时传入 domain_id 即可使用该自定义域名生成 short_url

绑定域名

POST /v1/domains

所需权限: domains:write

请求体

字段类型必填说明
domainstring要绑定的域名(如 s.example.comexample.com
  • 子域名(如 s.example.com):通过 CNAME 记录验证,指向平台提供的公共域名。
  • Apex 域名(如 example.com):通过 A 记录验证,指向平台提供的公共 IP。
curl -X POST https://open.utm.bar/v1/domains \
  -H "Authorization: Bearer sk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "s.example.com" }'

响应 201 Created

{
  "data": {
    "id": "d_abc123...",
    "domain": "s.example.com",
    "status": "pending",
    "is_apex": false,
    "verification_type": "cname",
    "verification_value": "redirect.utm.bar",
    "created_at": "2026-07-03T00:00:00Z"
  }
}

列出已绑定域名

GET /v1/domains

所需权限: domains:read

返回当前团队绑定的所有域名,按创建时间倒序。

curl https://open.utm.bar/v1/domains \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK

{
  "data": {
    "items": [
      {
        "id": "d_abc123...",
        "domain": "s.example.com",
        "status": "active",
        "is_apex": false,
        "verification_type": "cname",
        "verification_value": "redirect.utm.bar",
        "verified_at": "2026-07-03T01:00:00Z",
        "cert_expires_at": "2026-10-01T00:00:00Z",
        "created_at": "2026-07-03T00:00:00Z"
      }
    ]
  }
}

获取域名详情

GET /v1/domains/:id

所需权限: domains:read

curl https://open.utm.bar/v1/domains/d_abc123... \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK — 返回单个域名对象。


删除域名绑定

DELETE /v1/domains/:id

所需权限: domains:write

删除域名绑定不会删除关联的短链接,它们会回退到默认的 utm.bar 域名。

curl -X DELETE https://open.utm.bar/v1/domains/d_abc123... \
  -H "Authorization: Bearer sk_live_xxxx"

响应 204 No Content


验证域名 DNS

POST /v1/domains/:id/verify

所需权限: domains:write

触发 DNS 验证检查。如果 DNS 记录配置正确,域名将被标记为已验证,SSL 证书将在后台自动签发。

域名状态流转:pending →(DNS 匹配)→ verifying →(SSL 签发完成)→ active

curl -X POST https://open.utm.bar/v1/domains/d_abc123.../verify \
  -H "Authorization: Bearer sk_live_xxxx"

响应 200 OK

{
  "data": {
    "matched": true,
    "message": "DNS 验证成功,SSL 证书正在后台签发。"
  }
}

DNS 尚未配置时:

{
  "data": {
    "matched": false,
    "message": "DNS 记录尚未配置,请按要求添加 DNS 记录后重试。"
  }
}

频率限制

限流以团队为粒度,同一团队下所有 API Key 共享配额。

请求类型限制
写操作(创建 / 更新 / 禁用 / 删除)60 次 / 分钟
读操作(列表 / 详情 / 统计)300 次 / 分钟

超限时返回 429 Too Many Requests,响应头包含:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1748140860
Retry-After: 30

权限范围

Scope授权操作
links:read列表查询、获取详情、获取统计、批量统计
links:write创建链接、更新元数据、启用链接
links:delete禁用链接、删除链接
campaigns:read列出活动、获取活动详情/链接/统计
campaigns:write创建活动、删除活动
domains:read列出域名、获取域名详情
domains:write绑定域名、删除域名、验证 DNS

错误响应

所有错误使用统一的结构:

{
  "error": "error_code",
  "message": "人类可读的错误描述",
  "request_id": "req_abc123"
}
状态码error含义
400invalid_request参数校验失败
401unauthorizedKey 缺失或无效
403forbiddenKey 缺少所需权限
404not_found资源不存在
409conflict自定义短码已被占用
429rate_limited超出频率限制
500internal_error服务端错误