REST API Overview
The TechMaju platform generates REST APIs for all your DocTypes automatically, allowing you to run arbitrary Python methods using their dotted module path.
Authentication Methods
There are three primary ways to authenticate through the TechMaju REST API:
Token-Based Authentication:
Generate API Key and API Secret:
Navigate to User List and select a user.
Click on the "Settings" tab (if applicable).
Expand the API Access section and click on "Generate Keys".
Copy the API Secret and store it securely.
Note the API Key in the same section.
Combine
api_keyandapi_secretwith a colon:and pass the tokenapi_key:api_secretto the Authorization header in your request:
javascript
fetch('http://<base-url>/api/method/service-resource', {
headers: {
'Authorization': 'token api_key:api_secret'
}
})
.then(r => r.json())
.then(r => {
console.log(r);
})sh
curl http://<base-url>/api/method/service-resource -H "Authorization: token api_key:api_secret"Password-Based Authentication:
Authenticate with username and password, which relies on cookies and session data:
javascript
fetch('http://<base-url>/api/method/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
usr: 'username or email',
pwd: 'password'
})
})
.then(r => r.json())
.then(r => {
console.log(r);
})sh
curl --cookie-jar snowcookie --request POST "http://<base-url>/api/method/login" -H 'Content-Type: application/json' -H 'Accept: application/json' --data-raw "{ \"usr\" : \"<username>\", \"pwd\": \"<password>\" }"Access Token-Based Authentication:
Use OAuth to generate an
access_tokenas per the documentation.Pass the
access_tokenin the Authorization header in your request:
javascript
fetch('http://<base-url>/api/method/service-resource', {
headers: {
'Authorization': 'Bearer access_token'
}
})
.then(r => r.json())
.then(r => {
console.log(r);
})Listing Documents
To get a list of records for a DocType, send a GET request to /api/resource/:doctype. By default, it returns 20 records with only their names:
GET /api/resource/:doctype
Response:
{
"data":[
{"name":"f765eef382"},
{"name":"2a26fa1c64"},
//...
]
}Fields Parameter
You can specify which fields to fetch using the fields parameter:
GET /api/resource/:doctype?fields=["field1", "field2"]
Response:
{
"data":[
{"description":"Description text","name":"f765eef382"},
//...
]
}Filters Parameter
You can filter records using the filters parameter. Filters should be specified as an array, where each filter is of the format: [field, operator, value].
GET /api/resource/:doctype?filters=[["field1", "=", "value1"], ["field2", ">", "value2"]]
Response:
{
"data":[
{"name":"f765eef382"},
//...
]
}The filters parameter joins all the specified filters using the AND SQL operator. If you need OR filters, you can use the or_filters parameter. The syntax for or_filters is the same as filters.
Order_by Parameter
You can also provide the sort field and order using the order_by parameter. It should be of the format fieldname asc or fieldname desc. The space should be URL encoded:
GET /api/resource/:doctype?order_by=title%20descLimit Parameter
You can page the results by providing the limit_start and limit parameters:
GET /api/resource/:doctype?limit_start=5&limit=10
Response:
{
"data": [
{"name":"6234d15099"},
//...
]
}Retrieve as List
By default, you will receive the data as List[dict]. You can retrieve your data as List[List] by passing as_dict=False:
GET /api/resource/:doctype?limit_start=5&limit=5&as_dict=False
Response:
{
"data": [
["6234d15099"],
//...
]
}Debug
To debug the query built for your requests, you can pass debug=True with the request. This returns the executed query and execution time under exc of the payload:
GET /api/resource/:doctype?limit_start=10&limit=5&debug=True
Response:
{
"data": [
{"name":"4bcf8b701c"},
//...
],
"exc": "[\"select `tabToDo`.`name`\\n\\t\\t\\tfrom `tabToDo`\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t order by `tabToDo`.`modified` DESC\\n\\t\\t\\tlimit 5 offset 10\", \"Execution time: 0.0 sec\"]"
}CRUD Operations
TechMaju provides endpoints for CRUD operations for all DocTypes. Ensure headers are set for JSON responses:
{
"Accept": "application/json",
"Content-Type": "application/json",
}Create
POST /api/resource/:doctype
POST /api/resource/:doctype
Body: {"description": "New ToDo"}
Response:
{
"data": {
"name": "af2e2d0e33",
"owner": "Administrator",
"creation": "2019-06-03 14:19:00.281026",
"modified": "2019-06-03 14:19:00.281026",
"modified_by": "Administrator",
"idx": 0,
"docstatus": 0,
"status": "Open",
"priority": "Medium",
"description": "New ToDo",
"doctype": "ToDo"
}
}Read
GET /api/resource/:doctype/:name
GET /api/resource/:doctype/:name
Response:
{
"data": {
"name": "bf2e760e13",
"owner": "Administrator",
"creation": "2019-06-03 14:19:00.281026",
"modified": "2019-06-03 14:19:00.281026",
"modified_by": "Administrator",
"idx": 0,
"docstatus": 0,
"status": "Open",
"priority": "Medium",
"description": "<p>Test description</p>",
"doctype": "ToDo"
}
}Update
PUT /api/resource/:doctype/:name
PUT /api/resource/:doctype/:name
Body: {"description": "New description"}
Response:
{
"data": {
"name": "bf2e760e13",
"owner": "Administrator",
"creation": "2019-06-03 14:19:00.281026",
"modified": "2019-06-03 14:21:00.785117",
"modified_by": "Administrator",
"idx": 0,
"docstatus": 0,
"status": "Open",
"priority": "Medium",
"description": "New description",
"doctype": "ToDo"
}
}Delete
DELETE /api/resource/:doctype/:name
DELETE /api/resource/:doctype/:name
Response: {"message": "ok"}Remote Method Calls
TechMaju allows you to trigger REST API endpoints for handling custom logic.
GET /api/method/service-resource
Response:
{
"message": "Hello World"
}If your method returns some values, you should send a GET request.
If your method changes the state of the database, use POST. After a successful POST request, the framework will automatically call frappe.db.commit() to commit the changes to the database.
A successful response will return a JSON object with a message key.
An errored response will return a JSON object with exc key which contains the stack trace and exc_type which contains the thrown Exception.
The return value of the method will be converted to a JSON and sent as the response.
File Uploads
There is a dedicated method /api/method/upload_file that accepts binary file data and uploads it into the system.
Here is the curl command for it:
sh
curl -X POST http://<base-url>/api/method/upload_file -H 'Accept: application/json' -H 'Authorization: token xxxx:yyyy' -F file=@/path/to/file/file.pngIf you are using client-side JavaScript to upload files, you can append the uploaded files as FormData and send an XHR request. Here is the implementation code in Frappe Desk:
javascript
var formData = new FormData();
formData.append('file', fileInputElement.files[0]);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/method/upload_file', true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Authorization', 'token xxxx:yyyy');
xhr.onload = function () {
if (xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
console.log(response);
} else {
console.error(xhr.statusText);
}
};
xhr.send(formData);Best Practices: Client vs Server
Depending on whether the API endpoint is internal vs external, it is recommended to use either the client-side or server-side artifacts, respectively.
Internal APIs | External APIs |
|---|
Client-Side |
|
|
Server-Side |
|
|