Skip to content

Commit 0940667

Browse files
committed
wip
1 parent f9cead3 commit 0940667

File tree

1 file changed

+168
-122
lines changed

1 file changed

+168
-122
lines changed

content/developer/reference/external_json2_api.rst

Lines changed: 168 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,153 @@ External JSON-2 API
77
Odoo is usually extended internally via modules, but many of its features and all of its data are
88
also available from the outside for external analysis or integration with various other softwares.
99
Part of the :ref:`reference/orm/model` API is easily available over HTTP via the ``/json/2``
10-
endpoint. The actual models, their fields and methods are specific to every database and can be
11-
consulted at the ``/doc`` page.
10+
endpoint. The actual models, fields and methods available are specific to every database and can be
11+
consulted on their ``/doc`` page.
1212

13+
API
14+
===
1315

14-
Request
16+
POST a json object at the ``/json/2/<model>/<method>`` URL.
17+
18+
Headers:
19+
20+
:Autorization: Required, ``bearer`` followed by an API Key.
21+
:Content-Type: Required, ``application/json; charset=utf-8``, other charsets are supported as well.
22+
:X-Odoo-Database: Optional, the name of the database on which to connect.
23+
:User-Agent: Recommended when integrating with another software.
24+
25+
Body:
26+
27+
:ids: a JSON array of record ids on which to call the method.
28+
:context: a JSON object of additional values like the lang, used when crafting the environment.
29+
30+
The body must be a json-object containing the arguments for the model's method. Both ``ids`` and
31+
``context`` are special arguments: they are used to craft the environment and recordset on which the
32+
method is executed.
33+
34+
The headers ``Host``, ``Authorization`` with an API key and ``Content-Type`` are required. The
35+
``X-Odoo-Database`` header is only necessary when multiple databases are hosted behind a same
36+
``Host``. A ``User-Agent`` with the name of the software where the request comes from is
37+
recommended.
38+
39+
In case of **success**, a **200** status, and the return value of the called method serialized as
40+
json in the body.
41+
42+
In case of **error**, a **4xx**/**5xx** status, and the error message serialized as a json string in
43+
the body. The complete traceback is available in the server log, at the same date and time as the
44+
error response.
45+
46+
47+
Configuration
48+
=============
49+
50+
API Key
51+
-------
52+
53+
An API key must be set in the ``Authorization`` request header, as a bearer token.
54+
55+
Create a new API key for a user via :guilabel:`Preferences`, :guilabel:`Account Security`, and
56+
:guilabel:`New API Key`.
57+
58+
.. have the three images appear next to each other
59+
.. list-table::
60+
61+
* - .. image:: external_api/preferences2.png
62+
:align: center
63+
64+
- .. image:: external_api/account-security2.png
65+
:align: center
66+
67+
- .. image:: external_api/new-api-key.png
68+
:align: center
69+
70+
A description and a duration are needed to create a new api key. The description makes it possible
71+
to identify the key, and to determine later whether the key is still in use or should be removed.
72+
The duration determines the lifetime of the key after which the the key becomes invalid. It is
73+
recommended to set a short duration (typically 1 day) for interactive usage. It is not possible to
74+
create keys that last for more than 3 months, it means that long lasting keys must be rotated at
75+
least once every 3 months.
76+
77+
The :guilabel:`Generate Key` creates a 160 bits strong random key. Its value appears on screen, this
78+
is the only time and place the key is visible on screen. It must be copied, kept secret and stored
79+
somewhere secure. If it ever gets compromized or lost, then it must be removed.
80+
81+
Please refer to OWASP's `Secrets Management Cheat Sheet`_ for further guidance on the management of
82+
API keys.
83+
84+
.. _Secrets Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html#secrets-management-cheat-sheet
85+
86+
87+
Access Rights
88+
-------------
89+
90+
The JSON-2 API uses the standard :ref:`security <reference/security>` model of Odoo. All operations
91+
are validated against the access rights, record rules and field accesses of the user.
92+
93+
For **interfactive usage**, such as discovering the API or running one-time scripts, it is fine to
94+
use a **personal account**.
95+
96+
For **extended automated usage**, such as an integration with another software, it is recommended to
97+
create and use **dedicated bot users**.
98+
99+
Using dedicated bot users has several benefits:
100+
101+
* The minimum required permissions can be granted to the bot, limiting the impact may the API key
102+
gets compromised;
103+
* The password can be set empty to disable login/password authentication, limiting the likelihood
104+
the account gets compromized;
105+
* The :ref:`reference/fields/automatic/log_access` use the bot account. No user gets impersonalized.
106+
107+
108+
Database
109+
--------
110+
111+
Depending on the deploiement, the ``Host`` and/or ``X-Odoo-Database`` request headers might be
112+
required. The ``Host`` header is required on servers where Odoo is installed next to other web
113+
applications, so a web-server/reverse-proxy is able to route the request to the Odoo server. The
114+
``X-Odoo-Database`` header is required when a single Odoo server hosts multiple databases, and that
115+
:ref:`dbfilter` wasn't configured to use the ``Host`` header.
116+
117+
Most HTTP client libraries automatically set the ``Host`` header using the connection url.
118+
119+
120+
Transaction
121+
===========
122+
123+
.. note::
124+
125+
Under construction
126+
127+
128+
Example
15129
=======
16130

17-
POST a json object at the ``/json/2/<model>/<method>`` URL.
131+
The following example showcases how to call the ``search_read`` method of the
132+
:ref:`reference/orm/models/crud` on a fake database ``mycompany`` hosted on a fake website
133+
``https://mycompany.example.com``.
18134

135+
The comprehensive documentation listing the models, fields and methods available in this database
136+
would be available at the https://mycompany.example.com/doc page.
137+
138+
Request
139+
-------
19140

20141
.. tabs::
21142

22143
.. code-tab:: http
23144

24145
POST /json/2/res.partner/search_read HTTP/1.1
25-
Host: mycompany.odoo.com
146+
Host: mycompany.example.com
26147
X-Odoo-Database: mycompany
27-
Authorization: Bearer 6578616d706c65206a736f6e20617069206b6579
148+
Authorization: bearer 6578616d706c65206a736f6e20617069206b6579
28149
Content-Type: application/json; charset=utf-8
29150
User-Agent: mysoftware python-requests/2.25.1
30151

31152
{
32153
"ids": [],
33154
"context": {
34155
"lang": "en_US"
35-
}
156+
},
36157
"domain": [
37158
["name", "ilike", "%deco%"],
38159
["is_company", "=", true]
@@ -44,21 +165,22 @@ POST a json object at the ``/json/2/<model>/<method>`` URL.
44165

45166
import requests
46167

47-
HOST = "https://mycompany.odoo.com"
48-
DATABASE = "mycompany"
168+
BASE_URL = "https://mycompany.example.com/json/2"
49169
API_KEY = ... # get it from a secure location
170+
headers = {
171+
"Authorization": f"bearer {API_KEY}",
172+
"X-Odoo-Database": "mycompany",
173+
"User-Agent": "mysoftware " + requests.utils.default_user_agent(),
174+
}
50175

51176
response = requests.post(
52-
HOST + "/json/2/res.partner/search_read",
53-
headers={
54-
"Authorization": f"Bearer {API_KEY}",
55-
"X-Odoo-Database": DATABASE,
56-
},
177+
f"{BASE_URL}/res.partner/search_read",
178+
headers=headers,
57179
json={
58180
"ids": [],
59181
"context": {
60182
"lang": "en_US",
61-
}
183+
},
62184
"domain": [
63185
("name", "ilike", "%deco%"),
64186
("is_company", "=", True),
@@ -72,55 +194,52 @@ POST a json object at the ``/json/2/<model>/<method>`` URL.
72194
.. code-tab:: javascript
73195

74196
(async () => {
75-
const HOST = "https://mycompany.odoo.com";
76-
const DATABASE = "mycompany";
197+
const BASE_URL = "https://mycompany.example.com/json/2";
77198
const API_KEY = ; // get it from a secure location
199+
const headers = {
200+
"Content-Type": "application/json",
201+
"Authorization": "bearer " + API_KEY,
202+
"X-Odoo-Database": DATABASE,
203+
}
78204

79205
const request = {
80206
method: "POST",
81-
headers: {
82-
"Content-Type": "application/json",
83-
"Authorization": "Bearer " + API_KEY,
84-
"X-Odoo-Database": DATABASE,
85-
},
207+
headers: headers,
86208
body: {
209+
"ids": [],
210+
"context": {
211+
"lang": "en_US",
212+
},
87213
domain: [
88214
["name", "ilike", "%deco%"],
89215
["is_company", "=", true],
90216
],
91217
fields: ["name"],
92218
},
93219
};
94-
95-
const response = await fetch(HOST + "/json/2/res.partner/search_read", request);
220+
const response = await fetch(BASE_URL + "/res.partner/search_read", request);
221+
const data = await response.json();
96222
if (response.ok) {
97-
const data = await response.json();
98-
console.log(data)
223+
console.log(data);
99224
} else {
100-
// Handle errors
225+
// Handle error, data holds the error message as string
101226
}
102227
})();
103228

104-
The body must be a json-object containing the arguments for the model's method. Both ``ids`` and
105-
``context`` are special arguments: they are used to craft the environment and recordset on which the
106-
method is executed.
107-
108-
The headers ``Host``, ``Authorization`` with an API key and ``Content-Type`` are required. The
109-
``X-Odoo-Database`` header is only necessary when multiple databases are hosted behind a same
110-
``Host``. A ``User-Agent`` with the name of the software where the request comes from is
111-
recommended.
112229

113-
The available models and methods depend on the list of modules that are installed in the database.
114-
The exact list of what's available is accessible on the ``/doc`` page of every database.
230+
The above example would be equivalent to running::
115231

232+
with odoo.sql_db.db_connect('mycompany') as cr:
233+
env = odoo.api.Environment(cr, uid=..., context={'lang': 'en_US'})
234+
records = env['res.partner'].search_read(
235+
domain=[("name", "ilike", "%deco%"), ("is_company", "=", True)],
236+
fields=["name"],
237+
)
238+
return json.dumps(records)
116239

117-
Response
118-
========
119240

120-
Success
121-
-------
122-
123-
A **200 OK** status with the method's return value serialized as json in the body.
241+
Success response
242+
----------------
124243

125244
.. code:: http
126245
@@ -131,93 +250,20 @@ A **200 OK** status with the method's return value serialized as json in the bod
131250
{"id": 25, "name": "Deco Addict"}
132251
]
133252
134-
Error
135-
-----
136-
137-
A **4xx**/**5xx** status with the error message serialized as a json string in the body.
253+
Error response
254+
--------------
138255

139256
.. code:: http
140257
141258
HTTP/1.1 401 Unauthorized
142-
Date: Fri, 18 Jul 2025 08:33:35 GMT
143259
Content-Type: application/json; charset=utf-8
144260
145261
"Invalid apikey"
146262
147-
The complete traceback is available in the server log, at the same date as the error response.
148-
149-
150-
API Key
151-
=======
152-
153-
An API key must be set in the ``Authorization`` request header, as a bearer token.
154-
155-
Create a new API key for a user via :guilabel:`Preferences`, :guilabel:`Account Security`, and
156-
:guilabel:`New API Key`.
157-
158-
.. have the three images appear next to each other
159-
.. list-table::
160-
161-
* - .. image:: external_api/preferences2.png
162-
:align: center
163263
164-
- .. image:: external_api/account-security2.png
165-
:align: center
166-
167-
- .. image:: external_api/new-api-key.png
168-
:align: center
169-
170-
A description and a duration are needed to create a new api key. The description makes it possible
171-
to identify the key, and to determine later whether the key is still in use or should be removed.
172-
The duration determines the lifetime of the key after which the the key becomes invalid. It is
173-
recommended to set a short duration (typically 1 day) for interactive usage. It is not possible to
174-
create keys that last for more than 3 months, it means that long lasting keys must be rotated at
175-
least once every 3 months.
176-
177-
The :guilabel:`Generate Key` creates a 160 bits strong random key. Its value appears on screen, this
178-
is the only time and place the key is visible on screen. It must be copied, kept secret and stored
179-
somewhere secure. If it ever gets compromized or lost, then it must be removed.
180-
181-
Please refer to OWASP's `Secrets Management Cheat Sheet`_ for further guidance on the management of
182-
API keys.
183-
184-
.. _Secrets Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html#secrets-management-cheat-sheet
185-
186-
187-
Access Rights
188-
=============
189-
190-
The JSON-2 API uses the standard :ref:`security <reference/security>` model of Odoo. All operations
191-
are validated against the access rights, record rules and field accesses of the user.
192-
193-
For **interfactive usage**, such as discovering the API or running one-time scripts, it is fine to
194-
use a **personal account**.
195-
196-
For **extended automated usage**, such as an integration with another software, it is recommended to
197-
create and use **dedicated bot users**.
198-
199-
Using dedicated bot users has several benefits:
200-
201-
* The minimum required permissions can be granted to the bot, limiting the impact may the API key
202-
gets compromised;
203-
* The password can be set empty to disable login/password authentication, limiting the likelihood
204-
the account gets compromized;
205-
* The :ref:`reference/fields/automatic/log_access` use the bot account. No user gets impersonalized.
206-
207-
208-
Database
209-
========
210-
211-
Depending on the deploiement, the ``Host`` and/or ``X-Odoo-Database`` request headers might be
212-
required. The ``Host`` header is required on servers where Odoo is installed next to other web
213-
applications, so a web-server/reverse-proxy is able to route the request to the Odoo server. The
214-
``X-Odoo-Database`` header is required when a single Odoo server hosts multiple databases, and that
215-
:ref:`dbfilter` wasn't configured to use the ``Host`` header.
216-
217-
Most HTTP client libraries automatically set the ``Host`` header using the connection url.
218-
219-
220-
Transaction
221-
===========
264+
Migrating from XML-RPC / JSON-RPC
265+
=================================
222266

267+
.. note::
223268

269+
Under construction

0 commit comments

Comments
 (0)