ODXProxy Clients
Help the user build applications against an Odoo ERP through ODXProxy, and
understand the target Odoo instance's data structure first so the code matches
reality.
Mental model (read this first)
ODXProxy is a Rust reverse proxy exposing one JSON-RPC 2.0 API in front of
any number of Odoo instances. Apps call the proxy; the proxy calls Odoo's
execute_kw. Two facts drive almost every mistake:
- Two separate keys. The proxy key goes in the
x-api-key HTTP header
(client → proxy). The Odoo user key goes in the request body as
odoo_instance.api_key (proxy → Odoo). They are never the same value.
- HTTP 200 can still be an error. Odoo logic/permission failures come back
inside a populated
error object on a 200 response. Always inspect error
before reading result.
Endpoint: POST /api/odoo/execute. Only 9 actions are allowed through:
search_count, search, read, fields_get, search_read, create,
write, unlink, call_method (arbitrary method — needs fn_name).
Minimal request body:
{
"id": "req-1",
"action": "search_read",
"model_id": "res.partner",
"params": [[["is_company", "=", true]]],
"keyword": { "fields": ["id", "name", "email"], "limit": 20 },
"odoo_instance": { "url": "https://erp.example.com", "db": "prod", "user_id": 2, "api_key": "<odoo user key>" }
}
params = positional args to execute_kw; keyword = kwargs (fields,
limit, offset, order, context, ...). Full field/type details, all
actions, and the error catalog live in references/ — load them as needed
rather than guessing.
Workflow
1. Discover the target Odoo model with fields_get — before serializing into
the native language. Do not assume field names; Odoo models are heavily
customized per instance. Always call fields_get on the model first to get
its real schema (field names, type, required, relation, selection),
then map that schema into your target language's native types
(structs/classes/DTOs/models). Writing the native data model before introspecting
is the most common source of bugs.
- Every official SDK exposes
fields_get first-class — as a method in most, as
OdxAction.FieldsGet in .NET. Use it when working inside a chosen SDK;
call_method is not needed for this, fields_get is one of the 9
actions.
- No SDK yet (or just exploring)?
scripts/odx.py is a zero-dependency CLI over
/api/odoo/execute for running fields_get and search_read against the
live instance.
- Then sample a few real records with
search_read to confirm value shapes
(e.g. many2one as [id, "name"], which selection values actually occur).
- Full recipe — classify fields, follow relations, map the model graph:
references/odoo-introspection.md.
If you have no live instance, say so and design against documented Odoo core
models, flagging every field the user must confirm.
2. Pick the client path. Either an official SDK or a hand-rolled client:
- Official SDKs share one intent: hold proxy URL +
x-api-key once, bind an
Odoo instance, call one method per action, catch typed exceptions — but the
actual APIs have drifted per language, so read the real source before
writing code. Notable exceptions: the com.terrakernel Kotlin client is
low-level (build the request yourself), and the .NET client has no
per-action methods at all — one ExecuteAsync plus an OdxAction enum,
with params/keyword passed as raw JSON bytes. Language specifics:
references/sdks.md.
- Custom client: implement the envelope and the 200-with-error check yourself.
Contract is in
references/api-reference.md.
3. Build, mapping each user operation to one allowed action. If an operation
needs an Odoo method outside the 8 CRUD actions (e.g. action_confirm), use
call_method with fn_name. Details + per-action param shapes:
references/actions.md.
4. Handle errors by code, not by HTTP status alone. Map the JSON-RPC error
codes to user-facing behavior (retry on timeout, surface Odoo validation
messages, fail fast on auth/license). Catalog: references/errors.md.
Reference index
| File |
Use when |
references/api-reference.md |
Full endpoint + envelope contract; building a custom client |
references/actions.md |
Exact params/keyword shape for each of the 9 actions |
references/errors.md |
Mapping error codes to handling logic |
references/sdks.md |
Choosing/using an official SDK; local reference repo paths |
references/odoo-introspection.md |
Discovering the target Odoo's data model |
scripts/odx.py |
Running live calls against a proxy for introspection/testing |
Local reference repos
The official SDK sources live on GitHub under https://github.com/terrakernel
(per-language repo URLs are in references/sdks.md). Published SDKs: Python,
Java (Kotlin), PHP, Kotlin, Swift, JavaScript/TS, and .NET/C# (NuGet
TerraKernel.OdxClient). Dart exists but is not published yet — don't
recommend it. Before relying on exact symbol
names, read the real source of the SDK the user is on — browse/clone its repo, or
read a local checkout if you have one — because this skill's summaries can drift
from the code.
1---2name: odxproxy-clients3description: Use when building an application, integration, or bot that talks to an Odoo ERP through ODXProxy — the Rust JSON-RPC proxy at odxproxy.io. Covers the 9 allowed actions (search_read, search, read, fields_get, create, write, unlink, search_count, call_method), the request/response envelope, error handling, the official SDKs (Python, Java, PHP, Kotlin, Swift, JavaScript, .NET/C# via NuGet TerraKernel.OdxClient, Dart), and how to introspect a target Odoo instance's data model (fields_get / relations) before writing code. Trigger on: ODXProxy, odxproxy, Odoo via proxy, execute_kw over JSON-RPC, "for_instance", OdxClient/OdxAction/TerraKernel.OdxClient, x-api-key + Odoo api_key, building an Odoo client/app.4---56# ODXProxy Clients78Help the user build applications against an Odoo ERP **through ODXProxy**, and9understand the target Odoo instance's data structure first so the code matches10reality.1112## Mental model (read this first)1314ODXProxy is a Rust reverse proxy exposing **one JSON-RPC 2.0 API** in front of15any number of Odoo instances. Apps call the proxy; the proxy calls Odoo's16`execute_kw`. Two facts drive almost every mistake:17181. **Two separate keys.** The proxy key goes in the `x-api-key` HTTP header19 (client → proxy). The Odoo user key goes in the request body as20 `odoo_instance.api_key` (proxy → Odoo). They are never the same value.212. **HTTP 200 can still be an error.** Odoo logic/permission failures come back22 inside a populated `error` object on a 200 response. Always inspect `error`23 before reading `result`.2425Endpoint: `POST /api/odoo/execute`. Only **9 actions** are allowed through:26`search_count`, `search`, `read`, `fields_get`, `search_read`, `create`,27`write`, `unlink`, `call_method` (arbitrary method — needs `fn_name`).2829Minimal request body:3031```json32{33 "id": "req-1",34 "action": "search_read",35 "model_id": "res.partner",36 "params": [[["is_company", "=", true]]],37 "keyword": { "fields": ["id", "name", "email"], "limit": 20 },38 "odoo_instance": { "url": "https://erp.example.com", "db": "prod", "user_id": 2, "api_key": "<odoo user key>" }39}40```4142`params` = positional args to `execute_kw`; `keyword` = kwargs (`fields`,43`limit`, `offset`, `order`, `context`, ...). Full field/type details, all44actions, and the error catalog live in `references/` — load them as needed45rather than guessing.4647## Workflow4849**1. Discover the target Odoo model with `fields_get` — before serializing into50the native language.** Do not assume field names; Odoo models are heavily51customized per instance. **Always call `fields_get` on the model first** to get52its real schema (field names, `type`, `required`, `relation`, `selection`),53*then* map that schema into your target language's native types54(structs/classes/DTOs/models). Writing the native data model before introspecting55is the most common source of bugs.5657- Every official SDK exposes `fields_get` first-class — as a method in most, as58 `OdxAction.FieldsGet` in .NET. Use it when working inside a chosen SDK;59 `call_method` is **not** needed for this, `fields_get` is one of the 960 actions.61- No SDK yet (or just exploring)? `scripts/odx.py` is a zero-dependency CLI over62 `/api/odoo/execute` for running `fields_get` and `search_read` against the63 live instance.64- Then sample a few real records with `search_read` to confirm value shapes65 (e.g. many2one as `[id, "name"]`, which selection values actually occur).66- Full recipe — classify fields, follow relations, map the model graph:67 `references/odoo-introspection.md`.6869If you have no live instance, say so and design against documented Odoo core70models, flagging every field the user must confirm.7172**2. Pick the client path.** Either an official SDK or a hand-rolled client:7374- Official SDKs share one *intent*: hold proxy URL + `x-api-key` once, bind an75 Odoo instance, call one method per action, catch typed exceptions — but the76 actual APIs have **drifted** per language, so read the real source before77 writing code. Notable exceptions: the `com.terrakernel` Kotlin client is78 low-level (build the request yourself), and the .NET client has **no79 per-action methods at all** — one `ExecuteAsync` plus an `OdxAction` enum,80 with `params`/`keyword` passed as raw JSON bytes. Language specifics:81 `references/sdks.md`.82- Custom client: implement the envelope and the 200-with-error check yourself.83 Contract is in `references/api-reference.md`.8485**3. Build, mapping each user operation to one allowed action.** If an operation86needs an Odoo method outside the 8 CRUD actions (e.g. `action_confirm`), use87`call_method` with `fn_name`. Details + per-action param shapes:88`references/actions.md`.8990**4. Handle errors by code, not by HTTP status alone.** Map the JSON-RPC error91codes to user-facing behavior (retry on timeout, surface Odoo validation92messages, fail fast on auth/license). Catalog: `references/errors.md`.9394## Reference index9596| File | Use when |97|------|----------|98| `references/api-reference.md` | Full endpoint + envelope contract; building a custom client |99| `references/actions.md` | Exact `params`/`keyword` shape for each of the 9 actions |100| `references/errors.md` | Mapping error codes to handling logic |101| `references/sdks.md` | Choosing/using an official SDK; local reference repo paths |102| `references/odoo-introspection.md` | Discovering the target Odoo's data model |103| `scripts/odx.py` | Running live calls against a proxy for introspection/testing |104105## Local reference repos106107The official SDK sources live on GitHub under **https://github.com/terrakernel**108(per-language repo URLs are in `references/sdks.md`). Published SDKs: Python,109Java (Kotlin), PHP, Kotlin, Swift, JavaScript/TS, and .NET/C# (NuGet110`TerraKernel.OdxClient`). Dart exists but is **not published yet** — don't111recommend it. Before relying on exact symbol112names, read the real source of the SDK the user is on — browse/clone its repo, or113read a local checkout if you have one — because this skill's summaries can drift114from the code.