操作文档类型

文档类型(DocType)是一种特定类型的文档,例如:客户、员工或物料。

文档名称(DocumentName)是文档的唯一标识符,例如:CUST-00001、EMP-00001 或 ITEM-00001。

以下示例中缺少身份验证。更多信息请参阅[基本身份验证]和[OAuth2]。

GET /api/resource/{DocType}

获取该文档类型下的文档列表。

路径参数:

  • DocType(字符串)

你想要获取的文档类型。例如:’Customer’。

查询参数:

  • fields []

默认情况下,只返回 ‘name’ 字段。要添加更多字段,可以传入 fields 参数。例如:fields=[“name”,”country”]

  • filters [[(string)]]

你可以通过在 filters 参数中传入 SQL 条件来筛选列表。每个条件的格式为 [{doctype}, {field}, {operator}, {value}]。例如:filters=[[“Customer”, “country”, “=”, “India”]]

  • limit_page_length(整数)

所有列表都会分页显示。通过此参数可以更改页面大小(一次返回多少条记录)。默认值:20。

  • limit_start(整数)

要请求后续页面,请传入 limit_page_length 的倍数作为 limit_start。例如,要请求第二页,请将 limit_start 设为 20。

示例:

获取所有电话号码为 4915227058038 的客户的最多 20 个名称(ID)。

curl -X GET https://{your frappe instance}/api/resource/Customer?fields=["name"]\
 &filters=[["Customer","phone","=","4915227058038"]]

返回值:

 {
 "data": [
 {
 "name": "CUST-00001"
 },
 ]
 }

POST /api/resource/{DocType}

创建该文档类型的新文档。

路径参数:

  • DocType(字符串)

你想要创建的文档类型。例如:’Customer’。

Content-Type:application/json

请求体:{"fieldname": value}

示例:

创建一个名为 Mustermann 的新线索。

curl -X POST https://{your frappe instance}/api/resource/Lead \
 -H 'Content-Type: application/json' \
 -H 'Accept: application/json' \
 -d '{"lead_name":"Mustermann"}'

GET /api/resource/{DocType}/{DocumentName}

按名称(ID)获取特定文档。

路径参数:

  • DocType(字符串)

你想要获取的文档类型。例如:’Customer’。

  • DocumentName(字符串)

你想要获取的文档名称(ID)。例如:’EMP-00001’。

示例:

获取名称为(ID)CUST-00001 的客户。

curl -X GET https://{your frappe instance}/api/resource/Customer/CUST-00001

PUT /api/resource/{DocType}/{DocumentName}

更新特定文档。这类似于 PATCH HTTP 请求,你不需要发送整个文档,只需发送要更改的部分。

路径参数:

  • DocType(字符串)

你想要更新的文档类型。例如:’Customer’。

  • DocumentName(字符串)

你想要更新的文档名称(ID)。例如:’EMP-00001’。

Content-Type:application/json

请求体:{"fieldname": value}

示例:

更新下次联系日期。

curl -X PUT https://{your frappe instance}/api/resource/Lead/LEAD-00001 \
 -H 'Accept: application/json' \
 -H 'Content-Type: application/json' \
 -d '{"contact_date":"2018-10-08"}'

返回值:

{
 "data": {
 "doctype": "Lead",
 "name": "LEAD-00001",
 "contact_date": "2018-10-08",
 "...": "..."
 }
}

DELETE /api/resource/{DocType}/{DocumentName}

路径参数:

  • DocType(字符串)

你想要删除的文档类型。例如:’Customer’。

  • DocumentName(字符串)

你想要删除的文档名称(ID)。例如:’EMP-00001’。

延伸阅读

HTTP 请求头:

  • Content-Type
  • Accept
  • Authorization

作者:Raffael Meyer([email protected])

列出文档

要列出文档,请向 /api/resource/{doctype} 发送 GET 请求。

GET /api/resource/Person

所有列表默认每页返回 20 条记录。要更改每页大小,可以传递查询参数 limit_page_length。要请求后续页面,请传递 limit_start。

响应以 JSON 对象形式返回,列表是一个数组,键为 data。

响应:

{
 "data": [
 {
 "name": "000000012"
 },
 {
 "name": "000000008"
 }
 ]
}

默认情况下,列表中只包含 name 字段。要添加更多字段,可以在 GET 请求中传递 fields 参数。fields 必须是一个包含字段名的 JSON 数组。

GET /api/resource/Person/?fields=[“name”,”first_name”]

响应:

{
 "data": [
 {
 "first_name": "Jane",
 "name": "000000012"
 },
 {
 "first_name": "John",
 "name": "000000008"
 }
 ]
}

你可以通过传递查询参数 filters 来使用 SQL 条件筛选列表。filters 必须是一个包含一个或多个过滤条件的 JSON 数组。每个条件的格式为 [{doctype}, {field}, {operator}, {operand}]。

例如,获取所有名字为 “Jane” 的人员的 name(id):

GET /api/resource/Person?filters=[[“Person”,”first_name”,”=”,”Jane”]]

响应:

 { "data": [ { "name": "000000012" } ] }

作者:Rushabh Mehta ([email protected])、Raffael Meyer ([email protected])

OAuth 2

使用请求头 Authorization: Bearer <access_token></access_token> 来执行需要身份验证的请求。你可以通过组合以下两个请求来获取一个持有者令牌(bearer token)。

这里有一篇非常棒的 OAuth 入门介绍:OAuth 2.0 和 OpenID Connect(通俗易懂版)

GET /api/method/frappe.integrations.oauth2.authorize

获取用户的授权码,以便代表用户访问 ERPNext。

参数(在查询字符串中):

  • client_id(字符串)

你的 OAuth2 应用程序的 ID

  • state(字符串)

你的客户端应用程序用来在请求和回调之间维护状态的任意值。授权服务器在将用户代理重定向回客户端时会包含这个值。该参数应用于防止跨站请求伪造。

  • response_type(字符串)

“code”

  • scope(字符串)

应授予你的应用程序的访问范围。

  • redirect_uri(字符串)

应用程序授权后,用户将被重定向到的回调 URI。然后可以从参数中提取授权码。

  • code_challenge_method(字符串)

(可选)可以是 s256 或 plain 中的一个。

  • code_challenge(字符串)

(可选)当 code_challenge_method=s256 时可以是 base64encode(sha256(random_string)),或者当 code_challenge_method=plain 时可以是 random_string。参考 https://tools.ietf.org/html/rfc7636#appendix-A

示例:

curl -X POST https://{your frappe instance}/api/method/frappe.integrations.oauth2.authorize \
 --data-urlencode 'client_id=511cb2ac2d' \
 --data-urlencode 'state=444' \
 # base64encode(sha256('420')) => 21XaP8MJjpxCMRxgEzBP82sZ73PRLqkyBUta1R309J0
 # --data-urlencode 'code_verifier=21XaP8MJjpxCMRxgEzBP82sZ73PRLqkyBUta1R309J0' \
 --data-urlencode 'response_type=code'
 --data-urlencode 'scope=openid%20all' \
 --data-urlencode 'redirect_uri=https://app.getpostman.com/oauth2/callback'

返回:

  • HTTP 状态码:200
  • text/html

这将打开授权页面,然后会将你重定向到 redirect_uri。

如果用户点击”允许”,重定向 URI 将被调用,并在查询参数中附带授权码:

https://{redirect uri}?code=plkj2mqDLwaLJAgDBAkyR1W8Co08Ud&state=444

如果用户点击”拒绝”,你将收到一个错误:

https://{redirect uri}?error=access_denied

使用 ID Token 的授权码授予的令牌交换

POST /api/method/frappe.integrations.oauth2.get_token
Header Content-Type: application/x-www-form-urlencoded

注意:此端点也可用于获取刷新的访问令牌。只需在请求体中发送 refresh_token 即可。

用(上面获取的)授权码换取访问令牌。

参数(在请求体中):

  • grant_type(字符串)

“authorization_code”

  • code(字符串)

在重定向 URI 中收到的授权码。

  • client_id(字符串)

你的 OAuth2 应用程序的 ID

  • redirect_uri(字符串)

客户端应用注册的重定向 URI

示例:

curl -X POST https://{your frappe instance}/api/method/frappe.integrations.oauth2.get_token \
 -H 'Content-Type: application/x-www-form-urlencoded' \
 -H 'Accept: application/json' \
 -d 'grant_type=authorization_code&code=wa1YuQMff2ZXEAu2ZBHLpJRQXcGZdr
 &redirect_uri=https%3A%2F%2Fapp.getpostman.com%2Foauth2%2Fcallback&client_id=af615c2d3a'

出于测试目的,你也可以像这样在 URL 中传递参数(并在浏览器中打开):

https://{your frappe instance}/api/method/frappe.integrations.oauth2.get_token?grant_type=authorization_code&code=A1KBRoYAN1uxrLAcdGLmvPKsRQLvzj&client_id=511cb2ac2d&redirect_uri=https%3A%2F%2Fapp.getpostman.com%2Foauth2%2Fcallback

返回:

 {
 "access_token": "pNO2DpTMHTcFHYUXwzs74k6idQBmnI",
 "token_type": "Bearer",
 "expires_in": 3600,
 "refresh_token": "cp74cxbbDgaxFuUZ8Usc7egYlhKbH1",
 "scope": "openid all",
 "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o"
 }

使用 ID Token 的授权码授予的令牌交换(PKCE)

POST /api/method/frappe.integrations.oauth2.get_token
Header Content-Type: application/x-www-form-urlencoded

用(上面获取的)授权码换取访问令牌。

参数(在请求体中):

  • grant_type(字符串)

“authorization_code”

  • code(字符串)

在重定向 URI 中收到的授权码。

  • client_id(字符串)

你的 OAuth2 应用程序的 ID

  • redirect_uri(字符串)

客户端应用注册的重定向 URI

  • code_verifier(字符串)

在 Authorization Request 期间与 code_challenge_method 和 code_challenge 一起使用的 random_string。

Content-Type: application/x-www-form-urlencoded

示例:

curl -X POST https://{your frappe instance}/api/method/frappe.integrations.oauth2.get_token \
 -H 'Content-Type: application/x-www-form-urlencoded' \
 -H 'Accept: application/json' \
 -d 'grant_type=authorization_code&code=wa1YuQMff2ZXEAu2ZBHLpJRQXcGZdr
 &redirect_uri=https%3A%2F%2Fapp.getpostman.com%2Foauth2%2Fcallback&client_id=af615c2d3a&code_verifier=420'

出于测试目的,你也可以像这样在 URL 中传递参数(并在浏览器中打开):

https://{your frappe instance}/api/method/frappe.integrations.oauth2.get_token?grant_type=authorization_code&code=A1KBRoYAN1uxrLAcdGLmvPKsRQLvzj&client_id=511cb2ac2d&redirect_uri=https%3A%2F%2Fapp.getpostman.com%2Foauth2%2Fcallback&code_verifier=420

返回:

{
 "access_token": "pNO2DpTMHTcFHYUXwzs74k6idQBmnI",
 "token_type": "Bearer",
 "expires_in": 3600,
 "refresh_token": "cp74cxbbDgaxFuUZ8Usc7egYlhKbH1",
 "scope": "openid all",
 "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o"
}

撤销令牌端点

POST /api/method/frappe.integrations.oauth2.revoke_token
Header: Content-Type: application/x-www-form-urlencoded

撤销令牌端点。

参数:

  • token

要撤销的访问令牌。

返回:

始终返回空响应,HTTP 状态码为 200。

 {}

Open ID Connect id_token

ID Token 是一个 JWT。

  • aud 声明包含已注册的 client_id。
  • iss 声明包含 frappe 服务器 URL。
  • sub 声明包含 Frappe 用户的 userid。
  • roles 声明包含用户角色。
  • exp 声明包含过期时间。
  • iat 声明包含签发时间。

示例:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkouIERvZSIsImVtYWlsIjoiakBkb2UuY29tIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDIwMjIsImF1ZCI6ImNsaWVudF9pZCJ9.ZEdnrHjLbArahVTN19b4zoRFoBO5a2BakRkR82O1VU8

使用 PyJWT 验证并提取它。

import jwt

id_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkouIERvZSIsImVtYWlsIjoiakBkb2UuY29tIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDIwMjIsImF1ZCI6ImNsaWVudF9pZCIsInJvbGVzIjpbIlN5c3RlbSBNYW5hZ2VyIiwiU2FsZXMgTWFuYWdlciJdLCJub25jZSI6Ijc4OTEyMyIsImlzcyI6Imh0dHBzOi8vZXJwLmV4YW1wbGUuY29tIn0.F8Wbh5dtD1loZPltJLj_sqF9DZNeBvEbo-ITtf3UPqk"

client_id = 'client_id'
client_secret = 'client_secret'

payload = jwt.decode(
 id_token,
 audience=client_id,
 key=client_secret,
 algorithm="HS256",
 options={"verify_exp": False}, # Enabled by default to verify expiration time
)

print(payload)
# Output

{'sub': '1234567890', 'name': 'J. Doe', 'email': '[email protected]', 'iat': 1516239022, 'exp': 1516242022, 'aud': 'client_id', 'roles': ['System Manager', 'Sales Manager'], 'nonce': '789123', 'iss': 'https://erp.example.com'}

OpenID 用户信息端点

请求

GET /api/method/frappe.integrations.oauth2.openid_profile
Header: Authorization: Bearer valid_access_token

响应

{
 "sub": "1234567890",
 "name": "J. Doe",
 "given_name": "J",
 "family_name": "Doe",
 "iss": "https://erp.example.com",
 "picture": "https://erp.example.com/files/jdoe.jpg",
 "email": "[email protected]",
 "iat": 1516239022,
 "exp": 1516242022,
 "aud": "client_id",
 "roles": ["System Manager", "Sales Manager"]
}

内省令牌端点

POST /api/method/frappe.integrations.oauth2.introspect_token
Header: Content-Type: application/x-www-form-urlencoded

撤销令牌端点。

参数:

  • token_type_hint

access_token 或 refresh_token,如果未提供则默认为 access_token

  • token

要内省的访问令牌或刷新令牌。取决于 token_type_hint

返回:

{
 "client_id": "511cb2ac2d",
 "trusted_client": 1,
 "active": true,
 "exp": 1619523326,
 "scope": "openid all",
 "sub": "1234567890",
 "name": "J. Doe",
 "given_name": "J",
 "family_name": "Doe",
 "iss": "https://erp.example.com",
 "picture": "https://erp.example.com/files/jdoe.jpg",
 "email": "[email protected]",
 "iat": 1516239022,
 "exp": 1516242022,
 "aud": "511cb2ac2d",
 "roles": ["System Manager", "Sales Manager"]
}

或者

{
 "active": false,
 "_server_messages": "..."
}

进一步阅读

请查看 Guides / Integration / How To Set Up Oauth 了解如何创建新的 OAuth 2 客户端。

  • Content-Type 请求头,
  • Authorization 请求头,
  • OAuth 2 规范,
  • 持有者令牌(Bearer token)。

作者:

  • Raffael Meyer ([email protected])
  • Revant Nandgaonkar ([email protected])

基于令牌的身份验证

自 v11.0.3 版本起可用

HTTP Authorization 请求头包含用于向服务器验证用户身份的凭据。它由授权类型(token 或 Basic)和相应的令牌组成。

Authorization: <type> <token>
</token></type>

该令牌由 api-key 和 api-secret 通过冒号连接而成。

生成 API 密钥和 API 机密

  1. 前往用户列表并打开一个用户。
  2. 点击“设置”选项卡。(如果看不到选项卡,请跳过此步骤)
  3. 展开 API 访问部分,然后点击“生成密钥”。
  4. 您将看到一个包含 API 机密的弹窗。请复制此值并妥善保管(例如密码管理器)。
  5. 您还会在此部分看到另一个字段“API 密钥”。

现在,使用这两个密钥即可对 API 请求进行身份验证。使用这些密钥发出的每个请求都将记录到您在步骤 1 中选择的用户名下。这也意味着系统将针对该用户进行角色权限检查。您也可以专门为 API 调用创建一个新用户。

令牌

HTTP 请求头:

Authorization: token <api_key>:<api_secret>
</api_secret></api_key>

Python 示例:

import requests

url = "http://frappe.local:8000/api/method/frappe.auth.get_logged_user"
headers = {
    'Authorization': "token 
<api_key>:<api_secret>"
}
response = requests.request("GET", url, headers=headers)
</api_secret></api_key>

基本认证

如果使用“基本”认证方案,凭据由 api_key 和 api_secret 组合而成,构造方式如下:

  1. 将两个值用冒号连接:<api_key>:<api_secret></api_secret></api_key>
  2. 将生成的字符串进行 base64 编码:base64encode(<api_key>:<api_secret>)</api_secret></api_key>

HTTP 请求头:

Authorization: Basic base64encode("<api_key>:<api_secret>")
</api_secret></api_key>

Python 示例:

import requests
import base64

url = "http://frappe.local:8000**/api/method/frappe.auth.get_logged_user**"
headers = {
    'Authorization': "Basic %s" % base64.b64encode(
<api_key>:<api_secret>)
}
response = requests.request("GET", url, headers=headers)
</api_secret></api_key>

访问令牌

如果使用 OAuth 2 访问令牌来验证请求,该令牌是 Frappe Server 在设置 OAuth 2 并生成令牌后提供的不透明 access_token 字符串。请参阅 Guides / Integration / How To Use OAuth 2

HTTP 请求头:

Authorization: Bearer access_token

Python 示例:

import requests
import base64

url = "http://frappe.local:8000**/api/method/frappe.auth.get_logged_user**"
headers = {
    "Authorization": "Bearer %s" % access_token
}
response = requests.request("GET", url, headers=headers)

更多资源

  • 授权请求头

简单认证

POST /api/method/login

内容类型:application/x-www-form-urlencoded

参数(在请求体中):

  • usr(字符串)

用户名

  • pwd(字符串)

密码

示例:

curl -X POST https://{your frappe instance}/api/method/login \
 -H 'Content-Type: application/json' \
 -H 'Accept: application/json' \
 -d '{"usr":"Administrator","pwd":"admin"}'

返回结果:

  • HTTP 状态码:200
  • application/json:
 {
 "home_page": "/desk",
 "full_name": "Administrator",
 "message": "Logged in"
 }
  • Cookie:sid(发送此 Cookie 以验证后续请求)。有效期三天。
 sid=05d8d46aaebff1c87a90f570a3ff1c0f570a3ff1c87a90f56bacd4;
 path=/;
 domain=.{your frappe instance};
 Expires=Sat, 29 Sep 2018 00:59:54 GMT;

错误信息:

  • HTTP 状态码:401
  • text/html:密码或用户名错误。

GET /api/method/logout

示例:

 curl -X GET https://{your frappe instance}/api/method/logout

返回结果:

  • HTTP 状态码:200
  • application/json:{}

GET /api/method/frappe.auth.get_logged_user

获取当前已认证用户的 ID。

示例:

 curl -X GET https://{your frappe instance}/api/method/frappe.auth.get_logged_user

返回结果:

  • HTTP 状态码:200
  • application/json:
 {
 "message": "Administrator"
 }

作者:Raffael Meyer([email protected])

介绍

Frappe 自带一个 HTTP API,可分为远程过程调用(RPC)和表述性状态转移(REST)两类。RPC 用于调用白名单方法,REST 用于操作资源。

基础 URL 是 https://{your frappe instance}。此处展示的每个请求都应附加到你的基础 URL 末尾。例如,如果你的实例是 demo.erpnext.com,那么 GET /api/resource/User 意味着 GET https://demo.erpnext.com/api/resource/User。

API v1

所有 v1 API 端点均以 /api/ 为前缀。从 Frappe Framework 版本 15 开始,它们也可以使用 /api/v1/ 作为前缀。

RPC

对端点 /api/method/dotted.path.to.method 的请求将调用一个白名单 Python 方法。

例如,GET /api/method/frappe.auth.get_logged_user 将调用 frappe 认证模块中的此函数:

@frappe.whitelist()
def get_logged_user():
 return frappe.session.user

响应:

{
 "message": "Administrator"
}

REST

Frappe 中的所有文档均可通过前缀为 /api/resource/ 的 RESTful API 访问。你可以对它们执行所有 CRUD 操作:

  • 创建

你可以通过向端点 /api/resource/{doctype} 发送 POST 请求来创建文档。

  • 读取

你可以使用端点 /api/resource/{doctype}/{name} 按名称获取文档。

  • 更新

你可以通过向端点 /api/resource/{doctype}/{name} 发送 PUT 请求来更新文档。这类似于 PATCH HTTP 请求,你无需发送整个文档,只需发送要更改的部分即可。

  • 删除

你可以通过向端点 /api/resource/{doctype}/{name} 发送 DELETE 请求来按名称删除文档。

API v2

> API v2 自 Frappe Framework v15 起可用

所有 v2 API 端点均以 /api/v2/ 为前缀。

RPC v2

与 v1 类似,RPC 端点可在 /api/v2/method/ 前缀下使用。可用的端点如下:

  • /api/v2/method/login – 处理用户登录(隐式)
  • /api/v2/method/logout – 注销当前用户
  • /api/v2/method/ping – 检查服务器状态
  • /api/v2/method/upload_file – 上传文件
  • /api/v2/method/dotted.path.to.method – 调用任何白名单方法
  • /api/v2/method// – 从 DocType 控制器调用白名单方法
  • /api/v2/method/run_doc_method – 对文档运行白名单方法

REST v2

API v2 通过前缀 /api/v2/document/ 和 /api/v2/doctype/ 提供了更符合 RESTful 风格的接口。支持以下操作:

文档操作

  • 创建

    通过向 /api/v2/document/{doctype} 发送 POST 请求来创建文档。

  • 读取

    通过向 /api/v2/document/{doctype}/{name}/ 发送 GET 请求来获取文档。

  • 更新

    通过向 /api/v2/document/{doctype}/{name}/ 发送 PATCH 或 PUT 请求来更新文档。

  • 删除

    通过向 /api/v2/document/{doctype}/{name}/ 发送 DELETE 请求来删除文档。

  • 复制

    通过向 /api/v2/document/{doctype}/{name}/copy 发送 GET 请求来获取文档的全新副本。

  • 执行方法

    通过向 /api/v2/document/{doctype}/{name}/method/{method} 发送 GET 或 POST 请求来对文档执行方法。

    method 的常见值:add_comment?text=hello、submit、cancel、rename?name=newname。

DocType 操作

  • 获取元数据

    通过向 /api/v2/doctype/{doctype}/meta 发送 GET 请求来获取 DocType 元数据。

  • 获取计数

    通过向 /api/v2/doctype/{doctype}/count 发送 GET 请求来获取记录总数。

  • 列出文档

    通过向 /api/v2/document/{doctype} 发送 GET 请求来列出文档。支持通过查询参数进行分页和字段选择。