npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

odoo-json-rpc-client

v1.0.0

Published

A fully typed TypeScript JSON-RPC client for Odoo's External API

Readme

odoo-json-rpc-client

A fully typed TypeScript JSON-RPC client for Odoo's External API.

npm version License: MIT Test Coverage

Features

  • Full TypeScript support with precise type definitions
  • 🔒 Type-safe CRUD operations (search, read, create, write, unlink)
  • 🚀 Promise-based API for modern async/await syntax
  • 🔧 Flexible configuration with custom timeouts, debug mode, and HTTP agents
  • 📦 Zero dependencies (axios as peer dependency)
  • 100% test coverage
  • 🌐 Compatible with Node.js and potentially Expo Go (with limitations)

Installation

npm install odoo-json-rpc-client axios

or with yarn:

yarn add odoo-json-rpc-client axios

or with pnpm:

pnpm add odoo-json-rpc-client axios

Quick Start

import { OdooClient } from 'odoo-json-rpc-client';

const client = new OdooClient({
  url: 'https://your-odoo-instance.com',
  db: 'your-database',
  login: 'your-username',
  password: 'your-password',
});

// Authenticate
const uid = await client.authenticate();
if (!uid) throw new Error('Authentication failed');

// Get server version
const version = await client.version();
console.log('Odoo version:', version.server_version);

// Search for company partners
const partnerIds = await client.search('res.partner', [
  ['is_company', '=', true]
], { limit: 10 });

// Read partner data with type safety
interface Partner {
  id: number;
  name: string;
  email: string;
}

const partners = await client.read<Partner>(
  'res.partner',
  partnerIds,
  ['id', 'name', 'email']
);
console.log('Partners:', partners);

Configuration

Basic Configuration

const client = new OdooClient({
  url: 'https://your-odoo-instance.com',
  db: 'your-database',
  login: 'your-username',
  password: 'your-password',
});

Advanced Configuration

import https from 'https';

const client = new OdooClient({
  url: 'https://your-odoo-instance.com',
  db: 'your-database',
  login: 'your-username',
  password: 'your-password',
  options: {
    // Enable debug logging (logs all requests/responses)
    debug: true,
    
    // Set custom timeout (default: 3000ms)
    timeoutMs: 5000,
    
    // Use custom HTTPS agent (Node.js only)
    // Useful for self-signed certificates, proxies, or keep-alive
    agent: new https.Agent({
      rejectUnauthorized: false, // Accept self-signed certificates
      keepAlive: true,
    }),
  },
});

API Reference

Authentication

authenticate(reqId?: number): Promise<number | false>

Authenticates the user and retrieves the user ID (uid).

const uid = await client.authenticate();
if (uid) {
  console.log('Authenticated as user', uid);
} else {
  console.log('Authentication failed');
}

isAuthenticated(): boolean

Check if the client is authenticated.

if (client.isAuthenticated()) {
  console.log('User ID:', client.getUid());
}

getUid(): number | false

Returns the current user ID or false if not authenticated.

Server Information

version(reqId?: number): Promise<OdooVersionInfo>

Retrieves Odoo server version information. No authentication required.

const version = await client.version();
console.log('Server version:', version.server_version);
console.log('Protocol version:', version.protocol_version);

Generic Method Execution

executeKw<T>(model: string, method: string, args: any[], kwargs?: Record<string, any>, reqId?: number): Promise<T>

Execute any Odoo model method with full type safety.

// Custom method call with type safety
const result = await client.executeKw<number>(
  'res.partner',
  'name_search',
  ['Acme'],
  { limit: 5 }
);

CRUD Operations

search(model: string, domain: any[], kwargs?: Record<string, any>, reqId?: number): Promise<number[]>

Search for record IDs matching the domain criteria.

const ids = await client.search('res.partner', [
  ['is_company', '=', true],
  ['country_id.code', '=', 'US']
], {
  limit: 100,
  offset: 0,
  order: 'name ASC'
});

searchCount(model: string, domain: any[], kwargs?: Record<string, any>, reqId?: number): Promise<number>

Count records matching the domain criteria.

const count = await client.searchCount('res.partner', [
  ['is_company', '=', true]
]);
console.log('Total companies:', count);

read<T>(model: string, ids: number[], fields?: string[], kwargs?: Record<string, any>, reqId?: number): Promise<T[]>

Read records by IDs with optional field selection.

interface Partner {
  id: number;
  name: string;
  email: string;
  phone: string;
}

const partners = await client.read<Partner>(
  'res.partner',
  [1, 2, 3],
  ['id', 'name', 'email', 'phone']
);

searchRead<T>(model: string, domain: any[], fields?: string[], kwargs?: Record<string, any>, reqId?: number): Promise<T[]>

Combined search and read in a single call.

const partners = await client.searchRead<Partner>(
  'res.partner',
  [['is_company', '=', true]],
  ['id', 'name', 'email'],
  { limit: 50 }
);

create(model: string, values: Record<string, any>, kwargs?: Record<string, any>, reqId?: number): Promise<number>

Create a new record and return its ID.

const partnerId = await client.create('res.partner', {
  name: 'New Company',
  email: '[email protected]',
  is_company: true,
});
console.log('Created partner ID:', partnerId);

write(model: string, ids: number[], values: Record<string, any>, kwargs?: Record<string, any>, reqId?: number): Promise<true>

Update existing records. Returns true on success.

const success = await client.write('res.partner', [1, 2], {
  phone: '+1234567890',
});
console.log('Update successful:', success);

unlink(model: string, ids: number[], kwargs?: Record<string, any>, reqId?: number): Promise<true>

Delete records. Returns true on success.

const success = await client.unlink('res.partner', [123, 124]);
console.log('Delete successful:', success);

Model Introspection

fieldsGet(model: string, attributes?: string[], kwargs?: Record<string, any>, reqId?: number): Promise<any>

Get field definitions for a model.

const fields = await client.fieldsGet('res.partner', ['string', 'type', 'required']);
console.log('Partner fields:', fields);

Static Methods

OdooClient.getNextReqId(): number

Get the next request ID for manual request tracking.

const reqId = OdooClient.getNextReqId();
const version = await client.version(reqId);

Error Handling

The client provides custom error classes for better error handling:

import {
  OdooClient,
  OdooError,
  InvalidJsonRpcVersionError,
  MismatchedRequestIdError,
} from 'odoo-json-rpc-client';

try {
  const partners = await client.search('res.partner', []);
} catch (error) {
  if (error instanceof OdooError) {
    console.error('Odoo error:', error.message);
    console.error('Error code:', error.code);
    console.error('Error data:', error.data);
  } else if (error instanceof InvalidJsonRpcVersionError) {
    console.error('Invalid JSON-RPC version:', error.receivedVersion);
  } else if (error instanceof MismatchedRequestIdError) {
    console.error('Request ID mismatch:', error.expectedId, error.receivedId);
  } else {
    console.error('Unknown error:', error);
  }
}

TypeScript Support

This library is written in TypeScript and provides full type definitions. You can leverage TypeScript's type system for better IDE support and type safety:

// Define your model interface
interface SaleOrder {
  id: number;
  name: string;
  partner_id: [number, string];
  amount_total: number;
  state: 'draft' | 'sent' | 'sale' | 'done' | 'cancel';
}

// Use it with type safety
const orders = await client.searchRead<SaleOrder>(
  'sale.order',
  [['state', '=', 'sale']],
  ['id', 'name', 'partner_id', 'amount_total', 'state']
);

// TypeScript will enforce the type
orders.forEach(order => {
  console.log(order.name); // OK
  console.log(order.invalid); // TypeScript error
});

Examples

Check the examples folder for more usage examples:

Platform Compatibility

Node.js ✅

Fully supported with all features including custom HTTP/HTTPS agents.

Browsers ⚠️

Should work in browsers, but the agent option is not supported (Node.js only).

React Native / Expo Go ⚠️

Compatible with basic functionality. The agent option is not supported in React Native/Expo environments.

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build the project
npm run build

# Watch mode for development
npm run dev

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

References

⚠️ Important: Odoo has announced that JSON-RPC support will be removed starting from Odoo 20. For new integrations, it is recommended to use the new REST or GraphQL APIs provided by Odoo. See the Odoo External API Documentation for more details.

Support

If you encounter any issues or have questions, please:

  1. Check the examples folder
  2. Review the API documentation
  3. Open an issue on GitHub

Author

Copyright (c) 2025 Robin Lamotte

Changelog

See CHANGELOG.md for version history and updates.