API 是软件之间的契约

API(Application Programming Interface)不是某段神秘代码,而是一份软件之间的交互契约。它规定调用方可以访问哪些地址、提交什么数据,以及服务方会返回怎样的结果。

把它理解成餐厅服务员很直观:菜单是接口文档,点单是请求,厨房是服务端,上菜是响应。顾客不需要进入厨房,但必须按照菜单提供的信息点单。

一个网络 API 通常由四部分组成:

要素作用示例
端点定位资源/v1/users/42
方法描述操作GETPOSTPATCHDELETE
请求携带参数、请求头和正文JSON、查询参数、令牌
响应返回状态、数据和错误信息状态码、响应头、JSON

API 的价值在于隔离实现。客户端只依赖公开契约,服务端可以更换数据库或重构内部代码,只要契约没有被破坏,调用方就不需要跟着重写。

客户端经过认证网关访问服务端,再接收结构化响应的 API 请求闭环
一次可靠的调用包含请求、认证、服务端处理和结构化响应

HTTP 方法与状态码

REST API 通常用名词表示资源,用 HTTP 方法表达动作:

GET    /v1/articles       获取文章列表
GET    /v1/articles/42    获取一篇文章
POST   /v1/articles       创建文章
PATCH  /v1/articles/42    更新部分字段
DELETE /v1/articles/42    删除文章

状态码负责说明结果,而不是装饰:

  • 2xx:请求成功,例如 200 OK201 Created
  • 400:请求格式或参数有误
  • 401:尚未通过身份认证
  • 403:身份有效,但没有操作权限
  • 404:目标资源不存在
  • 429:请求超过频率限制
  • 5xx:服务端处理失败

调用方不应只检查“有没有返回数据”,而应先判断状态码,再验证响应结构。

完成第一次可靠调用

下面使用公开测试接口读取一篇示例文章:

import requests

url = "https://jsonplaceholder.typicode.com/posts/1"

try:
    response = requests.get(
        url,
        headers={"Accept": "application/json"},
        timeout=10,
    )
    response.raise_for_status()

    data = response.json()
    title = data.get("title")

    if not isinstance(title, str):
        raise ValueError("响应中缺少有效的 title 字段")

    print(title)
except requests.Timeout:
    print("请求超时,请稍后重试")
except requests.HTTPError as error:
    print(f"服务返回错误状态:{error.response.status_code}")
except (requests.RequestException, ValueError) as error:
    print(f"调用失败:{error}")

这段代码比“发送请求后直接打印 JSON”多做了四件重要的事:

  1. 设置超时,避免程序无限等待
  2. 检查 HTTP 状态,避免把错误页面当成正常数据
  3. 验证关键字段,避免上游结构变化后静默产生错误
  4. 区分超时、HTTP 错误和数据错误,便于定位问题

认证信息不要写进代码

多数正式 API 使用密钥或访问令牌识别调用方:

import os
import requests

token = os.environ["SERVICE_API_TOKEN"]

response = requests.get(
    "https://api.example.com/v1/profile",
    headers={"Authorization": f"Bearer {token}"},
    timeout=10,
)
response.raise_for_status()

密钥应保存在环境变量或专门的密钥管理服务中,不要提交到 Git 仓库、截图、日志或前端代码。前端网页中出现的密钥最终都会被用户读取;需要保密的调用应经过自己的后端。

认证和授权也不是一回事:401 通常表示“你是谁尚未确认”,403 表示“已经知道你是谁,但你不能执行这项操作”。

排错时按链路检查

现象优先检查
无法连接或超时地址、网络、代理、DNS、超时设置
400参数名称、数据类型、JSON 格式
401令牌是否存在、过期,请求头格式是否正确
403账号权限、接口范围、IP 白名单
429频率限制、并发量、退避重试策略
5xx服务状态、请求 ID、服务端日志
状态为 200 但程序报错响应字段、数据类型、版本变化

调试时先用 curl 或 Postman 复现最小请求,再回到业务代码。这样可以快速判断问题位于接口本身、网络环境,还是程序的数据处理逻辑。

设计一个容易使用的 API

如果你是接口提供者,优质 API 通常具备以下特征:

  • 资源命名稳定,方法语义一致
  • 成功与失败都返回可预测的结构
  • 错误信息包含机器可读的错误码和人可读的说明
  • 列表接口支持分页、筛选和排序
  • 可能重复提交的操作考虑幂等性
  • 文档给出请求、响应和失败示例
  • 通过版本号管理不兼容变更

在 Agent 场景中,这些要求更加重要。模型需要清晰的工具名称、严格的参数结构和可解释的错误结果。接口越模糊,Agent 越容易猜错;接口越稳定,自动化流程越可靠。

最小实践清单

第一次接入新 API 时,只需要完成以下闭环:

  1. 阅读端点、方法、认证和返回格式
  2. 用最小请求确认接口可用
  3. 设置超时并检查状态码
  4. 验证真正依赖的响应字段
  5. 对限流和临时故障采用有限次数的退避重试
  6. 确保密钥不会进入仓库和日志

理解 API 的关键不是背完所有状态码,而是建立边界意识:客户端按契约发送请求,服务端按契约返回结果,双方都要对失败情况做明确处理。掌握这个模型后,无论接入数据服务、支付系统还是 AI 能力,思路都是相通的。