ODXProxy

Actions and Methods

The 9 actions ODXProxy allows through to Odoo's execute_kw (v1), and the named kwargs each Odoo method takes on JSON-2 (v2).

What you can call depends on the API version. v1 has a fixed allowlist of nine actions with positional arguments; v2 calls any public model method with named arguments. Both reach the same Odoo methods — only the shape differs, so don't mix the two.

v1: the 9 allowed actions

The action field must be one of these 9 values. Anything else is rejected with HTTP 400 and JSON-RPC code -32001.

ActionMeaning
search_countCount records matching a domain.
searchReturn record IDs matching a domain.
readRead fields for given IDs.
fields_getDescribe a model's fields.
search_readCombined search + read.
createCreate record(s).
writeUpdate record(s) by ID.
unlinkDelete record(s) by ID.
call_methodInvoke an arbitrary model method named by fn_name.

The action is passed straight through as the Odoo method name in execute_kw, except for call_method, where fn_name is used instead.

The model and fields are arbitrary — they are named in the request body and forwarded as-is. The proxy never hardcodes or mirrors your Odoo schema, so a model or field you add in Odoo is reachable immediately, with no proxy redeploy, config change, or schema regeneration. That holds on v2 too.

call_method requires a non-empty fn_name. Omitting it returns HTTP 400 with JSON-RPC code -32002. Any model method outside this allowlist must be invoked through call_method.

params and keyword per action

params is the positional-argument list of execute_kw, so for the search-style actions the domain is its first element — hence the doubled brackets. keyword carries kwargs such as fields, limit, offset, order, and context.

Actionparamskeywordresult
search_count[domain]{context}integer
search[domain]{limit, offset, order}array of ids
read[ids, fields] (fields optional){context}array of records
fields_get[]{attributes}object keyed by field name
search_read[domain]{fields, limit, offset, order}array of records
create[vals]{context}the new id
write[ids, vals]{context}true
unlink[ids]{context}true
call_methodthe method's positional args, e.g. [ids]the method's kwargswhatever the method returns
{ "action": "search_read", "model_id": "res.partner",
  "params": [[["is_company", "=", true]]],
  "keyword": { "fields": ["name", "email"], "limit": 50, "order": "name asc" } }

{ "action": "write", "model_id": "res.partner",
  "params": [[42], { "name": "Acme LLC" }] }

{ "action": "call_method", "model_id": "sale.order", "fn_name": "action_confirm",
  "params": [[42]] }

v2: methods and their kwargs

On v2 (POST /v2/odoo/execute, Odoo 19+), method names the Odoo method directly and kwargs carries every argument by name. There is no allowlist, no fn_name, and no positional params. Odoo checks each key against the method's Python signature, so the keys below must be spelled exactly as shown.

Operationmethodkwargsresult
search + readsearch_readdomain, fields, offset, limit, orderarray of records
searchsearchdomain, offset, limit, orderarray of ids
countsearch_countdomain, limitinteger
readreadids, fields, loadarray of records
schemafields_getallfields, attributesobject keyed by field name
createcreatevals_list — always an arrayarray of ids, always
updatewriteids, valstrue
deleteunlinkidstrue
anything elsethe method's nameids (record methods only) + the method's named argswhatever the method returns; a recordset becomes an array of ids

Any call can also carry context (lang, tz, allowed_company_ids, …).

{ "model_id": "res.partner", "method": "search_read",
  "kwargs": { "domain": [["is_company", "=", true]], "fields": ["name", "email"], "limit": 50 } }

{ "model_id": "res.partner", "method": "create",
  "kwargs": { "vals_list": [{ "name": "Acme Inc" }] } }

{ "model_id": "sale.order", "method": "action_confirm",
  "kwargs": { "ids": [42] } }

{ "model_id": "res.partner", "method": "name_search",
  "kwargs": { "name": "Acm", "limit": 5 } }

The rules that matter:

  • Keys are Odoo's Python names, verbatim. vals_list, not valsList; allfields, not allFields. Field names inside vals, domain, and context are sent exactly as Odoo writes them too.
  • The domain is the list itself — "domain": [["is_company", "=", true]]. An empty domain is [].
  • Leave out what you don't set. Odoo's own defaults then apply; null means Python None, which is not the same thing.
  • ids only for record methods. Sending ids to an @api.model method (search, search_read, search_count, fields_get, create, name_search, …) fails with error code 422, as does an unknown or misspelled key.
  • model_id and method may contain only A-Z a-z 0-9 _ . and can't start with .; anything else is rejected with HTTP 400 / -32007 before Odoo is contacted. Odoo refuses private (_-prefixed) methods with code 403.

Finding a method's parameter names

For methods beyond the table above, the parameter names are in the method's Python definition. On Odoo 19+, /doc/<model> in the web UI lists every public method of a model with its parameters.

Relational fields (both versions)

For one2many and many2many fields, Odoo uses command tuples inside the values dict — [[6, 0, [ids]]] to replace, [[4, id]] to link, [[0, 0, {vals}]] to create and link. They pass through create and write unchanged on both versions. Check the field's type with fields_get first.

On this page