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:

    1. Navigate to User List and select a user.

    2. Click on the "Settings" tab (if applicable).

    3. Expand the API Access section and click on "Generate Keys".

    4. Copy the API Secret and store it securely.

    5. Note the API Key in the same section.

  • Combine api_key and api_secret with a colon : and pass the token api_key:api_secret to 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_token as per the documentation.

  • Pass the access_token in 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%20desc

Limit 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.png

If 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

  • ✅Recommended.

  • Secure within the same origin.

  • Reduces latency and server load.

  • ❌Not Recommended.

  • Blocked due to CORS.

  • Security risks (exposure of API keys).

  • Vulnerable to XSS and data privacy issues.

Server-Side

  • ❌Not Recommended.

  • Use built-in API functionalities provided instead of custom API endpoints.

  • ✅Recommended.

  • Best practice for secure storage of API keys.

  • Controlled access with error handling and data validation.

Discard
Save

On this page

Review Changes ← Back to Content
Message Status Space Raised By Last update on