作者:Sand,2017.11.07
本文档为REST API调用规范,旨在为第三方应用提供访统一的问平台调用与交互方式,通过这些接口可以访问患者的健康数据,医疗资源及医疗机构等数据。
所有API都是通过向平台的REST服务器发送HTTP请求来实现,REST服务器支持gzip,可有效降低网络开销,建议第三方应用加入gzip支持。
平台API均被版本化,当前版本为v1.0,版本号通过URL指定,例如:
api/v1.0/user?age=20
请务必在请求中包含版本号以便请求能够得到正确响应。
所有API请求均通过HTTPS协议。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方法点击进去之后,根据方法的实际情况:
若方法需要认证,此时返回API的错误信息。结构如下
{
message: "需要认证",
documentation_url: http://ehr.yihu.com/docs/help.html
}
另外,平台提供了Swagger工具,用户可以直接访问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字段指向可能对解决问题有帮助的页面。
平台API在适当的时候会使用HTTP重定义功能。客户端应该假设所有的请求都有可能发生重定向。客户端接收到HTTP重定向时, 这不是一个错误并且客户端需要跟随重定向链接。重定向链接包含在URI资源的返回头*Location*字段中。
HTTP状态码 | 描述 |
301 | 永久重定向。所请求的资源已被永久转移到*Location*指定的位置,客户端应该使用该URI重新请求该资源。 |
302,307 | 临时重定向。所请求的资源暂时转移到*Location*指定的位置,客户端应该使用该URI重新请求该资源。 |
平台使用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 6570URI 模板。
>> 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字段中。建议使用此字段的值作为资源导航,而不是自己构建URL。某些情况下,分页信息会使用SHA1并且不提供页码。
Link: <https://ehr.yihu.com/api/user/repos?page=3&per_page=100>; rel="next",
<https://ehr.yihu.com/api/repos?page=50&per_page=100>; 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。
所有的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.
未实现。
未实现。
你可以在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代码处理这种回调结果。以下是一个简单的示例:
<html>
<head>
<script type="text/javascript">
function foo(response) {
var meta = response.meta;
var data = response.data;
console.log(meta);
console.log(data);
}
var script = document.createElement('script');
script.src = 'https://ehr.yihu.com?callback=foo';
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
<p>Open up your browser's console.</p>
</body>
</html>
所有的响应头内容均与原HTTP响应头一致,除了LInk字段。此处的Link字段已经提前为你解析好,并包装为*[url, options]*数组。
例如,正常的HTTP响应头中Link结构如下:
Link: <url1>; rel="next", <url2>; 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参数,其值使用时区数据库中的名称。
curl -H "Time-Zone: Asia/Shanghai" -X POST https://ehr.yihu.com/linguist/contents/new_file.md
使用上一次的已知时区信息
如果找不到Time-Zone参数,并且你生成了一个授权请求,我们将使用上次授权用户所在的时区。每次你浏览健康档案的时候都会更新这个值。
UTC
如果上述几种情况中均不包含任何时区信息,我们将使用UTC。