PHPackages                             codebar-ag/laravel-odoo - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. codebar-ag/laravel-odoo

ActiveLibrary[API Development](/categories/api)

codebar-ag/laravel-odoo
=======================

A simple way to interact with the Odoo API in Laravel

v1.10(3w ago)0537↓50%MITPHPPHP ^8.4CI passing

Since Jun 11Pushed 3w agoCompare

[ Source](https://github.com/codebar-ag/laravel-odoo)[ Packagist](https://packagist.org/packages/codebar-ag/laravel-odoo)[ Docs](https://github.com/codebar-ag/laravel-odoo)[ GitHub Sponsors](https://github.com/codebar-ag)[ RSS](/packages/codebar-ag-laravel-odoo/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (7)Dependencies (25)Versions (15)Used By (0)

[![](https://camo.githubusercontent.com/75e45896d35e2e0ab9a6b98d4388f34e42ac11516c3210de66e3b9946a8c62a3/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4c61726176656c2532304f646f6f2e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d636f64656261722d61672532466c61726176656c2d6f646f6f267061747465726e3d63697263756974426f617264267374796c653d7374796c655f31266465736372697074696f6e3d412b73696d706c652b7761792b746f2b696e7465726163742b776974682b7468652b4f646f6f2b4150492b696e2b4c61726176656c266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313735707826696d616765733d736572766572)](https://camo.githubusercontent.com/75e45896d35e2e0ab9a6b98d4388f34e42ac11516c3210de66e3b9946a8c62a3/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4c61726176656c2532304f646f6f2e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d636f64656261722d61672532466c61726176656c2d6f646f6f267061747465726e3d63697263756974426f617264267374796c653d7374796c655f31266465736372697074696f6e3d412b73696d706c652b7761792b746f2b696e7465726163742b776974682b7468652b4f646f6f2b4150492b696e2b4c61726176656c266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313735707826696d616765733d736572766572)

[![Latest Version on Packagist](https://camo.githubusercontent.com/750dc6184f02da80cbc102502d112776eae60dc61f5249348522cd732baf7863/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f636f64656261722d61672f6c61726176656c2d6f646f6f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codebar-ag/laravel-odoo)[![Total Downloads](https://camo.githubusercontent.com/ec1d386510a70b4b6c0822d6fb3a1f85d3bd97d6b0297262a1b12a5b4398112e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f636f64656261722d61672f6c61726176656c2d6f646f6f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codebar-ag/laravel-odoo)[![GitHub-Tests](https://github.com/codebar-ag/laravel-odoo/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/codebar-ag/laravel-odoo/actions/workflows/run-tests.yml)[![GitHub Code Style](https://github.com/codebar-ag/laravel-odoo/actions/workflows/fix-php-code-style-issues.yml/badge.svg?branch=main)](https://github.com/codebar-ag/laravel-odoo/actions/workflows/fix-php-code-style-issues.yml)[![PHPStan](https://github.com/codebar-ag/laravel-odoo/actions/workflows/phpstan.yml/badge.svg)](https://github.com/codebar-ag/laravel-odoo/actions/workflows/phpstan.yml)[![Dependency Review](https://github.com/codebar-ag/laravel-odoo/actions/workflows/dependency-review.yml/badge.svg)](https://github.com/codebar-ag/laravel-odoo/actions/workflows/dependency-review.yml)

This package was developed to give you a quick start to communicate with the Odoo external API from Laravel. It wraps the most common endpoints — sessions, users, employees, projects, tasks and timesheets — behind a clean, typed connector built on [Saloon](https://docs.saloon.dev).

⚠️ This package is not designed as a replacement of the official Odoo external API. See the [Odoo documentation](https://www.odoo.com/documentation) if you need further functionality. ⚠️

📑 Table of Contents
-------------------

[](#-table-of-contents)

- [What is Odoo?](#-what-is-odoo)
- [Requirements](#-requirements)
- [Installation](#%EF%B8%8F-installation)
- [Configuration](#-configuration)
    - [Environment Variables](#environment-variables)
- [Basic Usage](#-basic-usage)
- [API Reference](#-api-reference)
    - [Session](#session)
    - [User](#user)
    - [Employees](#employees)
    - [Fields](#fields)
    - [Permissions](#permissions)
    - [Projects](#projects)
    - [Tasks](#tasks)
    - [Timesheets](#timesheets)
    - [Bank Accounts](#bank-accounts)
    - [Sync All](#sync-all)
- [DTOs](#-dtos)
- [Testing](#-testing)
- [Changelog](#-changelog)
- [Contributing](#%EF%B8%8F-contributing)
- [Security Vulnerabilities](#-security-vulnerabilities)
- [Credits](#-credits)
- [License](#-license)

💡 What is Odoo?
---------------

[](#-what-is-odoo)

Odoo is an open-source suite of business applications covering CRM, sales, project management, timesheets, accounting, inventory and more. It exposes an external API that lets you read and write records across all of these modules. This package provides a typed, Laravel-friendly client for the most common Odoo endpoints used in day-to-day integrations.

🛠 Requirements
--------------

[](#-requirements)

PackagePHPLaravelv1.0.0^8.4^13.0⚙️ Installation
---------------

[](#️-installation)

You can install the package via composer:

```
composer require codebar-ag/laravel-odoo
```

🔧 Configuration
---------------

[](#-configuration)

Optionally publish the config file to adjust defaults:

```
php artisan vendor:publish --provider="CodebarAg\Odoo\OdooServiceProvider" --tag="laravel-odoo-config"
```

You can generate an API key in your Odoo user profile under **Preferences → API Keys**.

### Environment Variables

[](#environment-variables)

Add the following variables to your `.env` file:

```
LARAVEL_ODOO_URL=https://your-odoo-instance.com
LARAVEL_ODOO_API_KEY=your-api-key
LARAVEL_ODOO_DB=your-database
LARAVEL_ODOO_TIMEOUT=15        # optional — request timeout in seconds (default 15, 0 = no timeout)
LARAVEL_ODOO_MAX_REDIRECTS=5   # optional — max HTTP redirects to follow (default 5)
```

🚀 Basic Usage
-------------

[](#-basic-usage)

Create an `OdooConnector` instance with your Odoo URL, API key, and optionally a database name:

```
use CodebarAg\Odoo\OdooConnector;

$connector = new OdooConnector(
    baseUrl: 'https://your-odoo-instance.com',
    apiKey: 'your-api-key',
    db: 'your-database',   // optional
    maxRedirects: 5,       // optional — max HTTP redirects to follow (default 5)
    timeout: 15.0,         // optional — request timeout in seconds (default 15, 0 = no timeout)
);
```

Each method returns a typed response object with dedicated methods for accessing the data.

### Using the Facade

[](#using-the-facade)

If you set the environment variables above (or publish and edit the config file), the package binds a pre-configured `OdooConnector` in the container, so you can resolve it or use the `Odoo` facade instead of constructing it by hand:

```
use CodebarAg\Odoo\Facades\Odoo;

$response = Odoo::health();
$response->isHealthy(); // bool
```

The facade reads `url`, `api_key`, `db`, `timeout`, and `max_redirects` from `config/laravel-odoo.php` (configurable via their respective `LARAVEL_ODOO_*` env vars). Direct instantiation with `new OdooConnector(...)` remains fully supported — for example when you need to talk to more than one Odoo instance.

📖 API Reference
---------------

[](#-api-reference)

### Session

[](#session)

```
// Check if the Odoo instance is reachable
$response = $connector->health();
$response->isHealthy(); // bool

// Get the Odoo server version
$response = $connector->version();
$response->serverVersion(); // ?string  e.g. "17"
$response->serie();         // ?string  e.g. "17.0"

// List all available databases
$response = $connector->databases();
$response->databases(); // array
```

### User

[](#user)

```
// Get the currently authenticated user
$response = $connector->getUser(
    fields: ['name', 'email'], // optional — omit to get the default field set
    domain: [],                // optional
    limit: 1,                  // optional, default 1
);
$user = $response->dto(); // ?UserDto  (id, name, lang)

// Get a user by their Odoo ID
$response = $connector->getUserById(
    uid: 1,
    fields: ['name', 'email'], // optional
);

// Get the authenticated user's context (timezone, language)
$response = $connector->getUserContext();
```

### Employees

[](#employees)

```
// Get an employee by their Odoo user ID
$response = $connector->getEmployeeByUserId(
    userId: 1,
    fields: ['name', 'job_title'], // optional — omit to get all fields
    limit: 1,                      // optional, default 1
);
$response->dto(); // ?EmployeeDto
```

### Fields

[](#fields)

```
// Get fields for a specific model
$response = $connector->getFields(
    model: 'account.move',
    attributes: ['string', 'type'], // optional — field meta-attributes to return
);
$response->fields(); // array

// Get all fields across all models
$response = $connector->getAllFields();
$response->fields(); // array
```

### Permissions

[](#permissions)

```
// Check permissions for a model and operation
$response = $connector->getPermissions(
    model: 'project.project',
    operation: 'read', // read, write, create, unlink
);
$response->allowed(); // bool
```

### Projects

[](#projects)

```
$response = $connector->getProjects(
    fields: ['name', 'date_start', 'date'], // optional
    domain: [['active', '=', true]],        // optional Odoo domain filter
    limit: 100,                              // optional, default 100
);

/** @var array $projects */
$projects = $response->projects();

use CodebarAg\Odoo\Dto\Projects\CreateProjectDto;
use CodebarAg\Odoo\Dto\Projects\UpdateProjectDto;

// Create a project
$response = $connector->createProject(new CreateProjectDto(
    name: 'Website Relaunch',
    partnerId: 7,         // optional, linked contact
    userId: 2,            // optional, project manager
    allocatedHours: 40.0, // optional
    tagIds: [1, 2],       // optional many-to-many tags
    extraValues: [],      // optional, custom/studio fields
));
$id = $response->id(); // ?int

// Update a project (only provided fields are written)
$response = $connector->updateProject(new UpdateProjectDto(
    id: 42,
    name: 'Website Relaunch 2.0',
));
$response->ok(); // bool

// Delete a project
$response = $connector->deleteProject(id: 42);
$response->ok(); // bool
```

### Tasks

[](#tasks)

```
// Get all tasks
$response = $connector->getAllTasks(
    fields: ['name', 'project_id', 'stage_id'], // optional
    domain: [['active', '=', true]],             // optional
    limit: 100,                                   // optional, default 100
);

/** @var array $tasks */
$tasks = $response->tasks();

// Get tasks for a specific project
$response = $connector->getTasksByProject(
    projectId: 42,
    fields: ['name', 'stage_id', 'date_deadline'], // optional
    limit: 100,                                     // optional, default 100
    operator: '=',                                  // optional domain operator, default '='
);

/** @var array $tasks */
$tasks = $response->tasks();

use CodebarAg\Odoo\Dto\Tasks\CreateTaskDto;
use CodebarAg\Odoo\Dto\Tasks\UpdateTaskDto;

// Create a task
$response = $connector->createTask(new CreateTaskDto(
    name: 'Design homepage',
    projectId: 42,        // optional
    userIds: [5, 6],      // optional assignees (many-to-many)
    stageId: 1,           // optional
    dateDeadline: '2026-07-01',
    priority: '1',        // optional
    extraValues: [],      // optional, custom/studio fields
));
$id = $response->id(); // ?int

// Update a task (only provided fields are written)
$response = $connector->updateTask(new UpdateTaskDto(
    id: 42,
    name: 'Design homepage v2',
    stageId: 2,
));
$response->ok(); // bool

// Delete a task
$response = $connector->deleteTask(id: 42);
$response->ok(); // bool
```

### Timesheets

[](#timesheets)

```
use CodebarAg\Odoo\Dto\Timesheets\CreateTimesheetDto;
use CodebarAg\Odoo\Dto\Timesheets\UpdateTimesheetDto;

// Get timesheet entries
$response = $connector->getTimesheetEntries(
    fields: ['name', 'project_id', 'task_id', 'unit_amount', 'date'], // optional
    domain: [['employee_id', '=', 5]],                                 // optional
    limit: 100,                                                         // optional
);

/** @var array $entries */
$entries = $response->entries();

// Get timesheet entries from the last N days
$response = $connector->getTimesheetEntriesLastDays(
    days: 7,
    fields: ['name', 'date', 'unit_amount'], // optional
    operator: '>=',                          // optional domain operator, default '>='
);
$entries = $response->entries(); // array

// Read a single timesheet entry
$response = $connector->readTimesheet(id: 123);
$entry = $response->dto(); // ?TimesheetEntryDto

// Create a timesheet entry
$response = $connector->createTimesheet(new CreateTimesheetDto(
    name: 'Fixed bug #456',
    projectId: 1,
    taskId: 10,
    date: '2024-06-11',
    unitAmount: 1.5,
    employeeId: 5,   // optional
    extraValues: [], // optional — extra Odoo fields (e.g. custom Studio fields)
));
$newId = $response->id(); // ?int

// Update a timesheet entry
$response = $connector->updateTimesheet(new UpdateTimesheetDto(
    id: 123,
    values: ['name' => 'Updated description', 'unit_amount' => 2.0],
));
$response->ok(); // bool

// Delete a timesheet entry
$response = $connector->deleteTimesheet(id: 123);
$response->ok(); // bool
```

### Bank Accounts

[](#bank-accounts)

CRUD and search operations for the `res.partner.bank` model.

> **Odoo 19.0 vs 19.3:** Odoo renamed the bank-account fields in 19.3 (`acc_number` → `account_number`, `acc_holder_name` → `holder_name`, and the `bank_id` / `currency_id`relations were dropped). The connector detects the server version once (cached) and transparently uses the right field names for reads and writes, so the API below is the same on both. Read DTOs always expose the classic property names (`accNumber`, `accHolderName`, …). To skip the version lookup, force it with `$connector->withBankAccountSchema(modern: true)`.

```
use CodebarAg\Odoo\Dto\BankAccounts\CreateBankAccountDto;
use CodebarAg\Odoo\Dto\BankAccounts\UpdateBankAccountDto;

// Search + read fields in one call (search_read)
$response = $connector->getBankAccounts(
    fields: ['id', 'acc_number', 'partner_id', 'bank_id'], // optional (version-aware default)
    domain: [['partner_id', '=', 7]],                      // optional
    limit: 100,                                            // optional
);

/** @var array $bankAccounts */
$bankAccounts = $response->bankAccounts();

// Search only for matching IDs (search)
$response = $connector->searchBankAccounts(domain: [['partner_id', '=', 7]]);
$ids = $response->ids(); // array

// Read a record by ID (read)
$response = $connector->readBankAccount(id: 5);
$bankAccounts = $response->bankAccounts(); // array

// Count matching records (search_count)
$response = $connector->searchCountBankAccounts(domain: [['partner_id', '=', 7]]);
$count = $response->count(); // ?int

// Create a bank account (create)
$response = $connector->createBankAccount(new CreateBankAccountDto(
    accNumber: 'CH9300762011623852957',
    partnerId: 7,
    accHolderName: 'Jane Doe', // optional
    bankName: 'UBS',           // optional
    bankBic: 'UBSWCHZH80A',    // optional
    bankId: 3,                 // optional — Odoo 19.0 only (ignored on 19.3)
    currencyId: 1,             // optional — Odoo 19.0 only (ignored on 19.3)
    allowOutPayment: true,     // optional
    sequence: 10,              // optional
    extraValues: [],           // optional — extra Odoo fields (e.g. custom Studio fields)
));
$newId = $response->id(); // ?int

// Update a bank account (write)
$response = $connector->updateBankAccount(new UpdateBankAccountDto(
    id: 5,
    accHolderName: 'John Doe',
));
$response->ok(); // bool

// Delete a bank account (unlink)
$response = $connector->deleteBankAccount(id: 5);
$response->ok(); // bool
```

### Sync All

[](#sync-all)

Fetch projects, all tasks, and all timesheet entries in one call:

```
$results = $connector->syncAll();

$projects   = $results['projects']->projects();     // array
$tasks      = $results['tasks']->tasks();           // array
$timesheets = $results['timesheets']->entries();    // array
```

📦 DTOs
------

[](#-dtos)

Read DTOs are built on [spatie/laravel-data](https://spatie.be/docs/laravel-data). Odoo's relation tuples (`[id, name]`) are flattened onto paired properties (e.g. `projectId` / `projectName`) and its `false`-means-empty sentinel is normalised to `null`. Each DTO keeps a `fromArray()` factory for backwards compatibility and is also a full laravel-data `Data` object (`from()`, `collect()`, …).

DTODescription`ProjectDto`Represents an Odoo project`TaskDto`Represents an Odoo task`TimesheetEntryDto`Represents a timesheet entry (read)`CreateTimesheetDto`Payload for creating a timesheet entry`UpdateTimesheetDto`Payload for updating a timesheet entry`EmployeeDto`Represents an Odoo employee`UserDto`Represents the authenticated Odoo user`FieldDto`Represents a field definition on an Odoo model🧪 Testing
---------

[](#-testing)

```
composer test
```

For live integration tests against a real Odoo instance, copy `phpunit.xml.dist` to `phpunit.xml`, fill in the `LARAVEL_ODOO_URL`, `LARAVEL_ODOO_API_KEY` and `LARAVEL_ODOO_DB` env values, then run:

```
composer test:live
```

📝 Changelog
-----------

[](#-changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

✏️ Contributing
---------------

[](#️-contributing)

Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.

🧑‍💻 Security Vulnerabilities
----------------------------

[](#‍-security-vulnerabilities)

Please review [our security policy](.github/SECURITY.md) on how to report security vulnerabilities.

🙏 Credits
---------

[](#-credits)

- [Sebastian Bürgin-Fix](https://github.com/StanBarrows)
- [Tobias Brogle](https://github.com/Astro2006)
- [All Contributors](../../contributors)
- [Skeleton Repository from Spatie](https://github.com/spatie/package-skeleton-laravel)
- [Laravel Package Training from Spatie](https://spatie.be/videos/laravel-package-training)

🎭 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

48

—

FairBetter than 94% of packages

Maintenance94

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 91.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

12

Last Release

26d ago

Major Versions

v0.1.0 → v1.0.02026-06-11

### Community

Maintainers

![](https://www.gravatar.com/avatar/fd1bbe54b79d041b513a286058b6fa0c479343f82147da3e63eefdf29c2fa6cb?d=identicon)[codebar](/maintainers/codebar)

---

Top Contributors

[![Astro2006](https://avatars.githubusercontent.com/u/135111039?v=4)](https://github.com/Astro2006 "Astro2006 (43 commits)")[![StanBarrows](https://avatars.githubusercontent.com/u/10268813?v=4)](https://github.com/StanBarrows "StanBarrows (3 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

laravelodoocodebar-aglaravel-odoo

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/codebar-ag-laravel-odoo/health.svg)

```
[![Health](https://phpackages.com/badges/codebar-ag-laravel-odoo/health.svg)](https://phpackages.com/packages/codebar-ag-laravel-odoo)
```

###  Alternatives

[codebar-ag/laravel-docuware

DocuWare integration with Laravel

1123.7k](/packages/codebar-ag-laravel-docuware)[codebar-ag/laravel-zammad

Zammad integration with Laravel

107.1k](/packages/codebar-ag-laravel-zammad)[njoguamos/laravel-plausible

A laravel package for interacting with plausible analytics api.

209.6k](/packages/njoguamos-laravel-plausible)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
