API ==================== > 作者:Sand,2017.11.07 概述 --------------------- 本文档为REST API调用规范,旨在为第三方应用提供访统一的问平台调用与交互方式,通过这些接口可以访问患者的健康数据,医疗资源及医疗机构等数据。 所有API都是通过向平台的REST服务器发送HTTP请求来实现,REST服务器支持gzip,可有效降低网络开销,建议第三方应用加入gzip支持。 术语解释 --------------------- - Client ID: 在平台注册App时,由平台提供的唯一App标识。 - Client Secret:在平台注册App时为其分配的应用密码。 - 用户名:在平台注册用户时,由平台提供的唯一用户标识。 - 用户密码:与用户ID相匹配的用户密码,由用户保管。 - 机构代码:在平台注册机构时,使用此机构在国家机构数据库中注册的代码。 - 机构公钥:在平台注册机构时,平台为机构提供的公钥。 版本 --------------------- 平台API均被版本化,当前版本为v1.0,版本号通过URL指定,例如: api/v1.0/user?age=20 请务必在请求中包含版本号以便请求能够得到正确响应。 请求与响应通用模式 --------------------- 所有API请求均通过HTTPS协议。API服务器地址: - [医生端](https://ehr.yihu.com/api) - [患者端](https://da.yihu.com/api) 数据发送与接收均以JSON作为载体。例如:数组参数array。普通字符串直接使用URL。 curl -i https://ehr.yihu.com/api/v1.0/users HTTP/1.1 200 OK Server: nginx Date: Fri, 12 Oct 2012 23:33:14 GMT Content-Type: application/json; charset=utf-8 Connection: keep-alive Status: 200 OK ETag: "a00049ba79152d03380c34652f2cb612" Content-Length: 5 Cache-Control: max-age=0, private, must-revalidate JSON结构中字段为空的时候,使用null表示,而不是将其丢弃。所有时间戳数据均以ISO 8601格式返回: YYYY-MM-DDTHH:MM:SSZ ### 资源摘要 当请求资源列表时,返回值是特定资源属性的一个子集,而非所有属性,即“资源摘要”(某些资源的属性会占用过多的系统资源), 鉴于性能原因应用默认不返回这些属性。若要获取这些属性,通过资源的详细信息来获取。 例如,当请求用户列表的时候,你将得到用户列表,其中只有部分属性有返回值 GET /users ### 资源详情 当请求单个资源时,平台将会返回这个资源的所有属性,即“资源详情”(注意,用于不同的用户权限,其返回值可能有所不同)。 例如,当请求某个用户的详细信息时,将会返回这个用户的所有数据: GET /users/1024 参数 --------------------- 很多API都含有可选参数。例如,对于GET请求,非路径变量参数可以通过HTTP查询参数指定: curl -i "https://ehr.yihu.com/v1/users/1024?age=20" 在这个示例中,用户的年龄参数通过*:age*查询字符串来指定。 对于POST, PUT与DELETE请求,不在URL中指定的参数必须封装成JSON,并指定Content-Type为'application/json': curl -i -u username -d '{"age":["20"]}' https://ehr.yihu.com/users 全局入口 --------------------- 通过向根路径发送GET请求,将会得到平台所有支持的API列表: curl https://ehr.yihu.com/api 可以从返回的JSON得到你所需要的API列表。入口处显示平台API列表可以点击进去。列表只显示各API的第一个GET方法链接。若含有多个GET方法会被忽略。 GET方法点击进去之后,根据方法的实际情况: - 若方法不需要认证,可以修改URL中的查询参数就可以得到结果 - 若方法需要认证,此时返回API的错误信息。结构如下 { message: "需要认证", documentation_url: http://ehr.yihu.com/docs/help.html } 另外,平台提供了[Swagger](https://ehr.yihu.com/swagger-ui.html)工具,用户可以直接访问API列表。 客户端错误 --------------------- 客户端请求时,服务端可能会返回以下三种类型的API错误,具体的错误信息在响应体中: - 若请求参数是一个无效的JSON,服务端将返回400错误: HTTP/1.1 400 Bad Request Content-Length: 35 {"message":"Problems parsing JSON"} - 若客户端发送的是一个错误的JSON值,服务端将返回400错误: HTTP/1.1 400 Bad Request Content-Length: 40 {"message":"Body should be a JSON object"} - 若客户端发送的数据包含无效的字段,服务端将返回422错误: HTTP/1.1 422 Unprocessable Entity Content-Length: 149 { "message": "Validation Failed", "errors": [ { "resource": "Issue", "field": "title", "code": "missing_field" } ] } 所有的错误对象都含有相应的资源与属性字段,用以告诉客户端可能的错误原因。另外,错误对象中还有一个错误代码,用于告诉哪个字段发生错误。 错误代码列表如下:
错误名称 描述
missing 资源不存在
missing_field 请求的资源不含请求的字段
invalid 字段的格式无效。请参考指定的资源文档以获取详细信息
already_exists 此资源的字段值与另一个资源一样。这种情况大多发生在资源的主键重复,例如:对象ID
以上是通用的错误对象,资源也可能返回一些自定义错误消息,自定义错误消息包含一个message字段描述该错误,且大多数错误消息都 含有一个documentation_url字段指向可能对解决问题有帮助的页面。 HTTP重定向 --------------------- 平台API在适当的时候会使用HTTP重定义功能。客户端应该假设所有的请求都有可能发生重定向。客户端接收到HTTP重定向时, 这不是一个错误并且客户端需要跟随重定向链接。重定向链接包含在URI资源的返回头*Location*字段中。
HTTP状态码 描述
301 永久重定向。所请求的资源已被永久转移到*Location*指定的位置,客户端应该使用该URI重新请求该资源。
302,307 临时重定向。所请求的资源暂时转移到*Location*指定的位置,客户端应该使用该URI重新请求该资源。
HTTP动词 --------------------- 平台使用HTTP动词代表一个操作,目前支持以下动词
动词 描述
GET 获取资源
POST 创建资源
PUT 更新一个或多个资源
DELETE 删除资源
授权 --------------------- 平台API有以下两种鉴权模式。大多数情况下,若不请求中不包含token会返回 *403 Forbidden*,但有些API出于保护资源的目的可能会返回*404 Not Found*错误。 - OAuth2 Token(包含在请求头中) curl -H "Authorization: token OAUTH-TOKEN" https://ehr.yihu.com/api - OAuth2 Token(作为请求参数的一部分) curl https://ehr.yihu.com/api/resource?access_token=OAUTH-TOKEN 更多关于OAuth2的信息,请参考(OAuth2规范)[https://developer.github.com/v3/oauth/]。OAuth2 Token获取请查询授权接口。 - OAuth2 Id/Secret获取 curl 'https://ehr.yihu.com/api/users/whatever?client_id=xxxx&client_secret=yyyy' 该请求返回的Token仅能用于服务端-服务端的场景,请不要部署两个一样的应用,然后分别向服务端请求Token,会互相覆盖。 请保管好应用Secret,不要泄露。 - 登录失败处理 使用非法凭据来请求资源将会返回*401 Unauthorized*错误: curl https://ehr.yihu.com/api/resource?access_token=OAUTH-TOKEN HTTP/1.1 401 Unauthorized { "message": "Bad credentials", "documentation_url": "https://ehr.yihu.com/api" } 如果在短时间内,服务端接收到多个使用非法凭据的请求,后续该开发者的所有API请求在一段时间内都将被拒绝(包括使用合法凭据的请求),返回的错误为*403 Forbidden* curl -i https://ehr.yihu.com/api/resource?access_token=INVALID-OAUTH-TOKEN HTTP/1.1 403 Forbidden { "message": "Maximum number of login attempts exceeded. Please try again later.", "documentation_url": "https://ehr.yihu.com/api" } 超媒体 --------------------- 所有的资源都含有一个或多个\*_url的属性,以链接到其他资源。这样做可以帮助客户端减少自己构建其关联资源的构建代码。强烈建议客户端使用这些URL。 这样做对以后开发者升级API会有帮助。所有的URL都符合 [RFC 6570](https://github.com/hannesg/uri_template)URI 模板。 >> tmpl = URITemplate.new('/notifications{?since,all,participating}') >> tmpl.expand => "/notifications" >> tmpl.expand :all => 1 => "/notifications?all=1" >> tmpl.expand :all => 1, :participating => 1 => "/notifications?all=1&participating=1" 分页 --------------------- 当请求的资源过多时,会默认以15条/页的数据返回。可以指定新的页码*page*与页大小*size*以返回更多的数据。 curl 'https://aehr.yihu.com/api/users?page=2&per_page=100' 注意,分布起始值为1,若请求中不提供page参数,默认返回第一页的数据。 ### Link头 分页信息包含在响应头的Link字段中。建议使用此字段的值作为资源导航,而不是自己构建URL。某些情况下,分页信息会使用SHA1并且不提供页码。 Link: ; rel="next", ; rel="last" Link字段包含一个或多个超媒体链接关系。*rel*可能值如下:
名称 描述
next 下一页结果
last 最后一页结果
first 第一页结果
previous 前一页结果
请求频率与限制 --------------------- 对认证过的请求,客户端每个小时的请求频率限制为5000次,对于未认证过的请求,客户端的请求频率限制为60次/小时。未认证的请求与IP绑定而不是与用户名绑定。 此情况对于搜索类型的API不适用,其频率限制有自身的规则。 通过检查HTTP响应头可以得到当前的请求频率限制: curl -i https://ehr.yihu.com/api/users/whatever HTTP/1.1 200 OK Date: Mon, 01 Jul 2013 17:27:06 GMT Status: 200 OK X-RateLimit-Limit: 60 X-RateLimit-Remaining: 56 X-RateLimit-Reset: 1372700873 从请求头中你可以得知你所需要的信息:
字段名称 描述
X-RateLimit-Limit 每小时最大请求次数
X-RateLimit-Remaining 当前时间内剩余请求次数
X-RateLimit-Reset 下一次请求次数重置时间,UTC epoch秒数
若想要将X-RateLimit-Reset时间转换为可读的,可以使用以下代码转换: new Date(1372700873 * 1000) // => Mon Jul 01 2013 13:47:53 GMT-0400 (EDT) 一旦请求次数用完,你将得到以下错误消息: HTTP/1.1 403 Forbidden Date: Tue, 20 Aug 2013 14:50:41 GMT Status: 403 Forbidden X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1377013266 { "message": "xxx.xxx.xxx.xxx的API请求超过限制(好消息:认证提限优惠大酬宾,活动参见链接)", "documentation_url": "https://ehr.yihu.com/docs/api/v1/#rate-limiting" } - 增加未授权的应用请求次数 若想增加未授权的应用请求次数,你需要在查询字段串中传递客户端的Client Id与Secret: curl -i 'https://ehr.yihu.com/api/v1/users/whatever?client_id=xxxx&client_secret=yyyy' HTTP/1.1 200 OK Date: Mon, 01 Jul 2013 17:27:06 GMT Status: 200 OK X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4966 X-RateLimit-Reset: 1372700873 这个方法应该仅用于服务端-服务端的请求,请务必不要泄漏App Secret。 使用User Agent --------------------- 所有的API都需要在请求头中包含User-Agent。没有User-Agent的请求将被拒绝。请在此字段中使用您的用户名或Client名称。 这样做可以在出现问题的时候方便联系你们。 例如: User-Agent: client 1FtXTrSL8D User-Agent: user developer 如果提供的User-Agent是无效值,你将收到以下错误信息: curl -iH 'User-Agent: ' https://ehr.yihu.com/api/v1/meta HTTP/1.0 403 Forbidden Connection: close Content-Type: text/html Request forbidden by administrative rules. Please make sure your request has a User-Agent header. Check https://ehr.yihu.com/api for other possible causes. 条件式请求 --------------------- 未实现。 跨域资源共享(Cross-Origin Resource Sharing,CORS) --------------------- 未实现。 JSON-P回调 --------------------- 你可以在GET请求参数中添加?callback参数以将请求结果包装成JSON函数,这种方式经常用在向第三方Web页面中嵌入健康档案平台的内容(跨域)。 平台将会把回调结果中的HTTP头作为API返回值的一部分: curl https://ehr.yihu.com/api/v1?callback=foo foo({ "meta": { "status": 200, "X-RateLimit-Limit": "5000", "X-RateLimit-Remaining": "4966", "X-RateLimit-Reset": "1372700873", "Link": [ // pagination headers and other links ["https://ehr.yihu.com/api/v1?page=2", {"rel": "next"}] ] }, "data": { // 回调的实际响应值 } }) 你可以编写JavaScript代码处理这种回调结果。以下是一个简单的示例:

Open up your browser's console.

所有的响应头内容均与原HTTP响应头一致,除了LInk字段。此处的Link字段已经提前为你解析好,并包装为*[url, options]*数组。 例如,正常的HTTP响应头中Link结构如下: Link: ; rel="next", ; rel="foo"; bar="baz" JSON-P中的Link结构如下: { "Link": [ [ "url1", { "rel": "next" } ], [ "url2", { "rel": "foo", "bar": "baz" } ] ] } 时区 --------------------- 部分API需要提供时间戳参数,部分API会返回含时区的时间戳。我们根据以下规则(优先级从大到小)决定API的时区信息: **显示使用ISO 8601格式的时间戳,即包含时区信息的时间戳** 对于允许显示指定时间戳的API,我们将使用指定的时区。这种时间戳看起像这样:*2016-04-26T08:25:07.504+0800*。 **在HTTP请求头中使用Time-Zone参数** 在HTTP请求头中附加Time-Zone参数,其值使用[时区数据库中的名称](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)。 curl -H "Time-Zone: Asia/Shanghai" -X POST https://ehr.yihu.com/linguist/contents/new_file.md **使用上一次的已知时区信息** 如果找不到Time-Zone参数,并且你生成了一个授权请求,我们将使用上次授权用户所在的时区。每次你浏览健康档案的时候都会更新这个值。 **UTC** 如果上述几种情况中均不包含任何时区信息,我们将使用UTC。