Remote Procedure Calls (RPC) are a powerful way to interact with Odoo
from external systems. In Odoo 18, just like earlier versions,
JSON-RPC remains one of the most efficient and lightweight ways to
remotely call Odoo methods using Python or any other language that
can send HTTP requests and handle JSON.
What is JSON-RPC?
JSON-RPC is a stateless, lightweight remote procedure call protocol
encoded in JSON. It allows you to send commands or queries to a
remote server and get results, without needing to keep an open
connection or session. Since JSON is easily readable and widely used
in web and app development, JSON-RPC is a practical choice for
communicating with the Odoo backend.
Compared to XML-RPC, JSON-RPC is more concise and faster, especially
over HTTP.
Connecting to Odoo with JSON-RPC
To connect to Odoo 18 using JSON-RPC, you need to define a method
that sends a properly formatted JSON payload to the /jsonrpc
endpoint.
Here’s a simple Python example:
import json
import random
import urllib.request
host = 'localhost'
port = 8018 # update this if your Odoo port is different
database = 'Demo'
user = 'admin'
password = 'admin'
def json_rpc(url, method, params):
data = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": random.randint(0, 1000000000),
}
req = urllib.request.Request(
url=url,
data=json.dumps(data).encode(),
headers={"Content-Type": "application/json"},
)
response = urllib.request.urlopen(req).read()
reply = json.loads(response.decode("UTF-8"))
if reply.get("error"):
raise Exception(reply["error"])
return reply["result"]
def call(url, service, method, *args):
return json_rpc(url, "call", {
"service": service,
"method": method,
"args": args
})
url = f"http://{host}:{port}/jsonrpc"
uid = call(url, "common", "login", database, user, password)
print(f"User ID: {uid}")
Reading Records via JSON-RPC
Once authenticated, you can fetch records from any model. Here's how
you can read a record from the project.task model:
task_data = call(
url, "object", "execute", database, uid, password,
"project.task", "read", [1]
)
print("Task Data:", task_data)
Parameters:
- database: Your database name
- uid: The logged-in user's ID
- password: The user's password
- model: The model to operate on (e.g., "project.task")
- method: The method to execute (e.g., "read")
- ids: List of record IDs to read
Searching and Reading (search_read)
To find and fetch records in one go, use search_read:
task_data = call(
url, "object", "execute", database, uid, password,
"project.task", "search_read",
[[['name', 'ilike', 'Office']]],
["id", "name", "stage_id"]
)
print(task_data)
This returns all tasks with names containing "Office".
Creating Records
To create a new project and a corresponding task:
project_data = {'name': 'New Project via JSON-RPC'}
project_id = call(url, "object", "execute", database, uid, password, "project.project", "create", project_data)
if project_id:
task_data = {
'name': 'Initial Task',
'project_id': project_id
}
task_id = call(url, "object", "execute", database, uid, password, "project.task", "create", task_data)
Updating Records
Use the write method to update an existing record:
update_data = {'name': 'Updated Project Name'}
call(url, "object", "execute", database, uid, password, "project.project", "write", [project_id], update_data)
Note: The record must exist and be accessible to the user.
Deleting Records
You can delete a record using the unlink method:
call(url, "object", "execute", database, uid, password, "project.project", "unlink", [project_id])
Make sure you pass a list of IDs, even if you're deleting just one
record.
Calling Custom Methods
In Odoo, you can also call your custom methods defined in a model, as
long as they are exposed through the API:
result = call(
url, "object", "execute", database, uid, password,
"your.model.name", "your_method_name", [arg1, arg2]
)
Tip: Methods must not be private (no underscore prefix) and must not
raise access errors.