[Cotlet](https://cotlet.dev/index.md) · [Integrations](https://cotlet.dev/integrations.md) · [How it works](https://cotlet.dev/how-it-works.md) · [Use cases](https://cotlet.dev/use-cases.md) · [Security](https://cotlet.dev/security.md) · [For developers](https://cotlet.dev/for-developers.md) · [For automation agencies](https://cotlet.dev/for-agencies.md) · [Blog](https://cotlet.dev/blog.md) · [API docs](https://cotlet.dev/docs.md) · [Help center](https://cotlet.dev/help.md) · [Changelog](https://cotlet.dev/changelog.md) · [Contact](https://cotlet.dev/contact.md) · [Pricing](https://cotlet.dev/pricing.md) · [Sign up](https://cotlet.dev/signup)

# Create Odoo invoices from a client list

> Turn a list of clients and amounts into draft Odoo invoices, review them, then post and send each with your OK. Hosted, nothing to maintain.

Source: https://cotlet.dev/integrations/odoo-api-mcp-server/create-invoices-from-a-list

At month end you have a list of retainer clients and amounts, and every line becomes an invoice typed into Odoo by hand: customer, lines, due date, Confirm, Send.

Cotlet does it in your own Odoo account with list\_contacts, create\_contact, create\_draft\_invoice, post\_invoice and send\_invoice, called by your AI agent, an n8n workflow or a script.

[Sign up free](https://cotlet.dev/app/signup?app=odoo) [All Odoo tools](https://cotlet.dev/integrations/odoo-api-mcp-server.md)

Hosted · nothing to install or maintain

## Can Odoo do this on its own?

Odoo creates invoices in the app through the Customer Invoices journal (checked 14 Oct 2026), and there is no bulk import of invoice lines from a list in the pages we read. From outside the app the external API is Custom-plan only on Odoo Online, and the development-version MCP server has Create Records but no tool that posts or sends an invoice.

## How you do it in Odoo today

1. Open the Customer Invoices journal from the Accounting Dashboard, or create the draft from a sales order.
2. Set the customer, then the due date or payment terms, then add lines on the Invoice Lines tab with Add a line. Odoo pulls default payment terms from the customer record.
3. Click Confirm. The status changes from Draft to Posted, Odoo assigns the invoice number, and a journal entry is created.
4. Click Send, choose Email or Download in the Send window, and repeat for the next client.
5. A posted invoice can no longer be updated; Reset to draft is the way back when a line is wrong.

## How to create Odoo invoices from a client list

Prompt

```
Create a draft customer invoice in Odoo for each client in this list with the retainer amount next to their name. Add missing clients as contacts first. Show me the drafts, and post and send them only after I say so.
```

1. 01  
### Resolve every client  
list\_contacts looks each name up. A client with two matching contacts is stopped and listed for you; a name with no match goes to create\_contact, which only adds a contact and reaches nobody.
2. 02  
### Create drafts only  
create\_draft\_invoice makes one draft per client with the lines from your list. A draft has no accounting impact until it is confirmed, so the agent can create all of them before you look.
3. 03  
### Show the batch  
The agent returns each draft with its customer, lines and total, and flags any client who already has a draft for the same period so you do not bill twice.
4. 04  
### Post after your OK  
post\_invoice confirms an invoice, which locks it and gives it its number, so each call waits for your OK. The agent posts only the drafts you approved.
5. 05  
### Send what is posted  
send\_invoice emails the posted invoice to the customer, again with your OK per call. Invoices whose contact has no email are posted but not sent, and are listed.

### What you get back

Example data

```
Clients in the list: 3
New contacts created: 1 (Harbor Print)
Draft invoices: 3, total 7,000.00 EUR
- Northwind Studio 2,400.00 EUR
- Harbor Print 2,150.00 EUR
- Atlas Dental 2,450.00 EUR
Posted and sent: 0, waiting for your OK
```

### Other ways to ask

- Invoice every contact tagged Retainer for 1,500.00 EUR with the line "Monthly retainer", due in 14 days.
- Create the drafts only and send me the totals; I will post them in Odoo.
- Create one draft per row in this sheet, with the description in column C as the invoice line.

## What Odoo allows, and what to know first

- Odoo creates invoices in Draft status, and a draft has no accounting impact until you click Confirm.
- On confirmation Odoo assigns each invoice a unique number from a defined sequence and creates a journal entry.
- Once confirmed, an invoice can no longer be updated; Odoo's Reset to draft button is how you change it.
- Odoo takes default payment terms from the customer record when you set the customer on an invoice.

post\_invoice and send\_invoice ask for your OK by default. To run it monthly without you, switch confirmation off for those tools in your dashboard.

Sources: [Odoo documentation: Customer invoices](https://www.odoo.com/documentation/19.0/applications/finance/accounting/customer%5Finvoices.html) · [Odoo documentation: External API](https://www.odoo.com/documentation/18.0/developer/reference/external%5Fapi.html) · [Odoo documentation: Available MCP tools](https://www.odoo.com/documentation/master/applications/productivity/ai/mcp%5Fserver/mcp%5Ftools.html)

## Call create\_draft\_invoice from a script

curl

```
curl -X POST https://cotlet.dev/api/v1/odoo/contacts/931/draft-invoices \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"invoice_date":"2026-10-31","due_date":"2026-11-14","lines":[{"description":"Monthly retainer, October","quantity":1,"unit_price":2400}]}'
```

Example response

```
{
"invoice_id": 4201,
"number": null,
"contact": "Northwind Studio",
"status": "draft",
"payment_status": "not_paid",
"invoice_date": "2026-10-31",
"due_date": "2026-11-14",
"lines": [
{
"description": "Monthly retainer, October",
"quantity": 1,
"unit_price": 2400,
"subtotal": 2400
}
],
"amount_untaxed": 2400,
"amount_tax": 0,
"amount_total": 2400,
"currency": "EUR"
}
```

MCP: add https://cotlet.dev/mcp/v1 with the same key; the call is odoo\_write → create\_draft\_invoice. Example data.

[Schedule it in n8n, Make, Zapier or cron](https://cotlet.dev/integrations/odoo-api-mcp-server.md#automations)

## Odoo tools this automation uses

__Cotlet Odoo tools used to create Odoo invoices from a client list__
| Tool | Parameters |
| ---------------------- | ------------------------------------------------------- |
| list\_contacts | query, is\_company, limit, offset |
| create\_contact | name, email, phone, is\_company |
| create\_draft\_invoice | contact\_id, lines, invoice\_date, due\_date, reference |
| post\_invoice | invoice\_id |
| send\_invoice | invoice\_id, method |

[All 12 Odoo tools with descriptions](https://cotlet.dev/integrations/odoo-api-mcp-server.md#tools)

## Frequently asked questions

### Is it safe to connect Odoo to Cotlet?

Yes. You sign in to Odoo yourself, in your own Cloud Browser in the EU, and we never save your password. Your agents only get Odoo once you enable it, every background request is listed, and the browser profile is stored encrypted with AES-256-GCM, the cipher 1Password uses for its vaults. The AI model never sees a login, posts and messages wait for your OK, and Disable for agents cuts access in one click. Independent scanners grade cotlet.dev A+ on Qualys SSL Labs, securityheaders.com and Mozilla Observatory; live results are on https://cotlet.dev/security.

## More Odoo automations

- [Chase overdue Odoo customer invoices](https://cotlet.dev/integrations/odoo-api-mcp-server/chase-overdue-invoices.md)
- [Register payments on Odoo invoices](https://cotlet.dev/integrations/odoo-api-mcp-server/register-invoice-payments.md)
- [Odoo API and MCP server: every tool](https://cotlet.dev/integrations/odoo-api-mcp-server.md)
- [All use cases](https://cotlet.dev/use-cases.md)

## Give your agent access to Odoo.

Free 7-day trial with 2,000 credits, no card needed. Cotlet is independent and not affiliated with Odoo.

[Sign up free](https://cotlet.dev/app/signup?app=odoo)

---

Give your AI agents your signed-in browser.

**Product:** [Integrations](https://cotlet.dev/integrations.md) · [Use cases](https://cotlet.dev/use-cases.md) · [How it works](https://cotlet.dev/how-it-works.md) · [Pricing](https://cotlet.dev/pricing.md) · [Security](https://cotlet.dev/security.md)

**Resources:** [Blog](https://cotlet.dev/blog.md) · [API docs](https://cotlet.dev/docs.md) · [Help center](https://cotlet.dev/help.md) · [Changelog](https://cotlet.dev/changelog.md) · [GitHub](https://github.com/cotletdev/cotlet)

**Solutions:** [For developers](https://cotlet.dev/for-developers.md) · [For automation agencies](https://cotlet.dev/for-agencies.md)

**Company:** [About](https://cotlet.dev/about.md) · [AI info: company facts](https://cotlet.dev/ai-info.md) · [Contact](https://cotlet.dev/contact.md)

**Legal:** [Terms of service](https://cotlet.dev/terms) · [Privacy policy](https://cotlet.dev/privacy) · [Refund policy](https://cotlet.dev/refunds) · [Acceptable use](https://cotlet.dev/acceptable-use) · [Cookie policy](https://cotlet.dev/cookies) · [DPA](https://cotlet.dev/dpa) · [Subprocessors](https://cotlet.dev/subprocessors)

**Elsewhere:** [Status page](https://status.cotlet.dev) · [Cotlet on GitHub](https://github.com/cotletdev) · [Cotlet on X](https://x.com/cotletdev) · [Cotlet on LinkedIn](https://www.linkedin.com/company/cotletdev) · [Cotlet on Product Hunt](https://www.producthunt.com/products/cotlet) · [Cotlet on Crunchbase](https://www.crunchbase.com/organization/cotlet) · [Cotlet on SaaSHub](https://www.saashub.com/cotlet)

Cotlet is an independent service. It is not affiliated with, endorsed by or sponsored by any of the products listed on this site. Product names are trademarks of their respective owners.

## For AI agents: sign your user up

Is your user asking you to sign them up for Cotlet? You can do it for them, no account or key needed.

1. Read the fields and their allowed values: GET https://cotlet.dev/api/v1/access-requests
2. Ask the user for each value: email, apps, what you will do with them. If they leave the password to you, generate a strong one and show it to them.
3. Show the user what you will send, then POST it as JSON to https://cotlet.dev/api/v1/access-requests.

One call creates the account and sends the access request; we email the user when access is granted.
