Odoo actions
Reference for the Odoo actions: the connection type, each action and what it does, its inputs and outputs, and the live catalog call.
The Odoo block reads and creates customer invoices, timesheets and sales orders through Odoo's JSON-2 external API, and runs Odoo's own timesheet invoicing. For the plain-language overview, see Odoo.
When to use it
Use an Odoo step to bill hours: log or read timesheets, create and confirm a sales order, then create the invoice from the order so Odoo's own rules decide which hours are billable. You can also list, read and create customer invoices directly.
Connection
| Item | Value |
|---|---|
| Block type | odoo |
| Connection | API key. In Integrations, Odoo asks for Odoo Domain (for example mycompany.odoo.com) and the API key |
| Account pin | config.connection, the stored connection id. The step loads the domain and key from that connection and ignores any inline domain or apiKey |
| Without a connection | The executor reads config.domain and config.apiKey from the step |
The domain must be a public host name. The executor refuses IP addresses, localhost and URLs with embedded credentials. Each call times out after 30 seconds.
Actions
The action id is odoo.<action>. All eleven are in the Studio Action list.
| Action | What it does | Required config | Returns |
|---|---|---|---|
listInvoices | Search customer invoices and credit notes | None | { records } |
getInvoice | Read one invoice | recordId | Odoo's read result (an array) |
createInvoice | Create a customer invoice | values | { id } |
listTimesheets | Search timesheet lines | None | { records } |
getTimesheet | Read one timesheet line | recordId | Odoo's read result |
createTimesheet | Log a timesheet line | values | { id } |
listSalesOrders | Search sales orders | None | { records } |
getSalesOrder | Read one sales order | recordId | Odoo's read result |
createSalesOrder | Create a draft sales order (quotation) | values | { id } |
confirmSalesOrder | Confirm a quotation into a sales order | recordId | { id, name, state, invoiceStatus } |
createInvoiceFromSalesOrder | Create the invoice for what the order has delivered | recordId | { invoiceIds, invoiceStatus } |
Fields
| Field | Type | Used by | Meaning |
|---|---|---|---|
recordId | string | Get, confirm and invoice-from-order actions | Odoo record id, a positive integer |
values | JSON object | Create actions | Odoo field values, for example {"partner_id": 12} |
orderLines | JSON array | createSalesOrder | Plain order-line objects such as [{"product_id": 73, "product_uom_qty": 5}]; the executor wraps them in Odoo's create commands |
filter | JSON array | List actions | An Odoo search domain, for example [["invoice_status","=","to invoice"]] |
fields | JSON array | List and get actions | Fields to return; each model has a default set |
limit | string | List actions | Maximum records, default 50, capped at 200 |
Behaviour worth knowing
listInvoicesalways adds a filter for customer invoices and credit notes, so vendor bills and journal entries never appear in its results, whateverfiltersays.createInvoicesets the move type to customer invoice.createInvoiceFromSalesOrderuses Odoo's "invoice delivered quantities" wizard. The new invoice is a draft; nothing is posted or sent. Hours already invoiced on an order line are not invoiced again. If there is nothing to invoice, Odoo returns an error and the step fails.- Sales order actions need the Odoo Sales app; timesheet invoicing also needs Odoo's timesheet-based invoicing.
Output
Create actions return { id }, so a later step reads {{steps.<id>.id}}. List actions return { records }. createInvoiceFromSalesOrder returns the ids of the invoices it created in {{steps.<id>.invoiceIds}}.
Example
{
"id": "invoice_hours",
"type": "action",
"name": "Invoice delivered hours",
"action": "odoo.createInvoiceFromSalesOrder",
"config": {
"operation": "createInvoiceFromSalesOrder",
"connection": "<odoo-connection-id>",
"recordId": "{{steps.confirm_order.id}}"
}
}Live catalog
GET /api/v1/blocks/odoo returns the fields and the eleven actions. Curated examples are at GET /api/v1/blocks/odoo/actions/<action>/examples. See Block and action discovery.
Errors and limits
Selected Odoo connection was not found or is not active. Reconnect Odoo from the Integrations page.Odoo API key is required.: no connection was selected and no inlineapiKeywas set.recordId must be a positive integer, got: …Odoo API error (<status>): <body>: Odoo rejected the call; the body carries Odoo's message.
NetSuite actions
Reference for the NetSuite actions: the connection type, each action and what it does, its inputs and outputs, and the live catalog call.
PandaDoc actions
Reference for the PandaDoc actions: the API key and MCP connections, every action id, the fields each one takes, outputs and a complete example.
Loopfour