广告投放API对接实战指南:多版本接口协同与鉴权要点

作者:渣渣辉2026.11.07 03:14浏览量:0

简介:本文面向后端开发者,系统梳理广告投放API对接中的接口版本差异、鉴权头命名冲突与资源MIME类型等高频问题,给出从授权到广告组创建的完整依赖链路与调试要点,帮助读者减少反复试错,构建稳定可维护的对接流程。

广告投放 API 对接实战指南:多版本接口协同与鉴权要点

在广告投放系统的后端开发中,对接开放 API 往往是”文档看得懂、调通要半天”的典型场景。尤其是当同一业务域被拆分成多套接口版本时,请求头、内容类型、路径风格各自为政,稍有不慎就会收到 403 或 415,而错误信息往往语焉不详。本文按实际对接顺序,梳理从授权到广告组创建的完整链路,并对最容易踩坑的几个环节做重点说明,帮助读者建立一套可复用的调试方法。

一、先理解整体架构:这不是一套接口

很多同学在对接初期会默认”广告 API 是一个整体”,于是用同一套请求头去打所有端点,结果必然受挫。实际情况是,广告投放能力通常被拆分为两个层次:

  • 活动管理层(Campaign 层):负责广告活动的创建、预算与投放周期管理,路径风格多为 /adsApi/v1/... 这类版本化前缀。
  • 投放实体层(AdGroup 及以下):负责广告组、商品广告、关键词、定向、否定词等细粒度资源,路径风格多为 /sp/...。

这两套接口在请求头命名、Content-Type 取值、响应结构上都不一致。因此第一件事不是写代码,而是把接口分组,为每组建立独立的 HTTP 客户端配置。工程上建议按”接口族”封装两个基础客户端,各自持有独立的默认请求头与序列化策略,避免在业务代码里到处手动拼 header。

整体创建依赖关系如下(组合/预算组为可选项):

  1. OAuth 授权
  2. → 查询广告账户档案
  3. → 创建组合(可选)
  4. → 创建广告活动(活动管理层接口)
  5. → 创建广告组(投放实体层接口)
  6. → 创建商品广告 / 关键词 / 定向 / 否定词
  7. → 创建活动级否定关键词 / 活动级否定定向

注意依赖方向:广告组必须挂在活动下,商品广告与关键词必须挂在广告组下。任何跨层创建都会因资源 ID 缺失而失败,因此实现上应把这条链路建模为有序任务,而不是并发发起。

二、鉴权:两套请求头命名,混用即 403

所有请求都需要 Bearer 形式的访问令牌,标准流程是 OAuth 2.0 授权码模式:

  1. 引导用户跳转至授权页,scope 需包含广告活动管理权限(如 advertising::campaign_management);
  2. 用户同意后回调携带授权码;
  3. 用授权码换取访问令牌与刷新令牌;
  4. 后续请求在 Authorization 头中携带 Bearer <access_token>;
  5. 令牌过期前用刷新令牌续期,并做好并发刷新时的互斥,避免多线程同时刷新导致旧令牌失效。

真正的坑在于客户端标识与账户标识的请求头命名:

  • 活动管理层接口使用一组以”客户端 ID + 账户 ID”命名的请求头;
  • 投放实体层接口使用另一组以”客户端 ID + 作用域”命名的请求头。

两组名称相似但字面不同,混用会直接返回 403。实践中建议:

  • 在配置层显式定义两组常量,命名上体现差异,禁止在业务代码中硬编码字符串;
  • 在 HTTP 客户端拦截器中按接口族自动注入,业务层只感知”调用哪个客户端”;
  • 对 403 做分类处理:区分”令牌无效”与”请求头不匹配”,后者应在日志中打印实际使用的头名称以便排查。

三、Content-Type:不能写通用 JSON 类型

这是第二个高频雷区。投放实体层的多数资源要求使用带资源标识的 vendor MIME 类型,例如关键词资源使用 application/vnd.spKeyword.v3+json 这类形式,而不是笼统的 application/json。写错通常返回 415(不支持的媒体类型)或 400(请求体解析失败)。

应对策略:

  • 为每个资源维护”资源名 → MIME 类型”的映射表,作为序列化层的一部分;
  • 在发送前做一次断言校验,避免运行时才发现;
  • 注意区分请求体类型与响应体类型,部分接口的响应也可能带 vendor 类型,反序列化时不要假设一定是标准 JSON;
  • 批量操作类接口(如列表更新)往往有独立的 MIME 约定,需单独登记。

一个简化的客户端伪代码如下:

  1. RESOURCE_MIME = {
  2. "adGroup": "application/vnd.spAdGroup.v3+json",
  3. "productAd": "application/vnd.spProductAd.v3+json",
  4. "keyword": "application/vnd.spKeyword.v3+json",
  5. "target": "application/vnd.spTarget.v3+json",
  6. "negativeKeyword": "application/vnd.spNegativeKeyword.v3+json",
  7. }
  8. def post_resource(client, resource, payload):
  9. headers = client.base_headers.copy()
  10. headers["Content-Type"] = RESOURCE_MIME[resource]
  11. return client.post(f"/sp/{resource}s", json=payload, headers=headers)

四、按顺序落地:从账户档案到否定定向

第一步,查询账户档案。 授权完成后先调用档案接口获取可投放的账户标识,后续所有请求的账户上下文都来源于此。建议缓存档案信息并设置合理过期时间,避免每次业务请求都重复拉取。

第二步,创建组合(可选)。 若业务需要按预算组管理活动,先创建组合并拿到组合 ID;不需要则跳过,但要在数据模型中预留字段,避免后续迁移。

第三步,创建广告活动。 走活动管理层接口,注意其请求体字段命名与投放实体层不同(例如预算、投放日期的表达方式)。建议为活动创建单独定义 DTO,不要与广告组 DTO 复用。

第四步,创建广告组。 走投放实体层接口,必须携带上一步返回的活动 ID。广告组的默认出价、投放位置等字段会显著影响后续资源的可用性,建议在创建时就明确设置,而非依赖平台默认值。

第五步,批量创建下层资源。 商品广告、关键词、定向、否定关键词、否定定向均挂在广告组下;活动级否定关键词与活动级否定定向挂在活动下。这一层建议:

  • 采用批量接口而非循环单条创建,降低请求数与限流风险;
  • 对部分成功的结果做逐条解析,把失败项写入重试队列,而不是整体回滚;
  • 记录每条资源的业务主键与平台 ID 的映射,便于后续更新与对账。

五、调试与可观测性建议

  1. 按接口族分日志:两套接口的错误码含义不完全一致,日志中标注接口族可大幅缩短定位时间。
  2. 保留原始请求快照:在调试阶段记录路径、请求头(脱敏后)、Content-Type 与请求体,便于在接口调试工具中复现。
  3. 限流与重试:对 429 与 5xx 采用指数退避重试,对 4xx 不重试,避免放大故障。
  4. 幂等设计:创建类接口建议以业务唯一键做本地去重,防止重试导致重复资源。
  5. 契约测试:为每个资源类型准备最小可用请求体样本,纳入持续集成,接口升级时可第一时间发现字段或 MIME 变更。

六、小结

广告投放 API 对接的难点不在于业务逻辑复杂,而在于多版本接口并存的细节差异。把接口按族分组、把请求头与内容类型下沉到客户端配置、把创建链路建模为有序任务,并在调试阶段保留足够的可观测信息,基本可以覆盖绝大多数踩坑场景。对于更上层的投放策略与数据分析,则可在此基础上逐步叠加,而不必反复纠缠于协议层的细枝末节。