Invoicing & freelance CRM
Tolteck
Quotes, invoices, clients and unpaid reminders in Tolteck.
13 endpoints
Obat publishes no public API and has no official MCP server (checked 14 Nov 2026). Cotlet runs a hosted Obat MCP server with 14 tools that ChatGPT and Claude use in your own Obat account. Quotes, invoices and reminders wait for your OK before they reach a client.
14 tools Read and write
Obat publishes no public API and no developer docs: its pricing page lists no API on any plan. Obat has no official MCP server, and no official ChatGPT or Claude connector was found. Its only outside links go to accounting: Pennylane and CSV, XLSX or FEC exports.
| What you need | Obat alone | Cotlet |
|---|---|---|
| Ask ChatGPT or Claude to do the work | No API or MCP server | Hosted MCP server |
| Quotes, deposits and final invoices | By hand, one document at a time | 14 tools, sends after your OK |
| Reminders on late invoices | One click per invoice, by hand | On request or every week |
| Run from n8n or a script | No public API | REST, same key |
Checked 14 Nov 2026. Sources: Obat: pricing and plans · Obat: accounting export · Pennylane Help: connect Obat to Pennylane · Obat Help: invoice reminders · Obat: AI voice quotes
Once, in a browser we host for you.
One address in its settings.
It drafts one per signed quote, you check the amounts.
Your agent works in your own signed-in Cloud Browser. Quotes, invoices and reminders reach a client only after your OK. Who can see your session
Sign in to Obat in a Cloud Browser. Open www.obat.fr/login in your Cotlet Cloud Browser and sign in with your own Obat account.
Add the Cotlet address. Enter https://cotlet.dev/mcp/v1 as the MCP server or connector URL in your agent.
Let the agent in. Chat apps open a Cotlet sign-in page. Editors, n8n and scripts send an API key made in the console.
Obat sits on the shared address https://cotlet.dev/mcp/v1 with every other app you turn on, so one connector covers them all. Turned on Obat after connecting? Refresh the connector and its 14 tools appear.
Settings > Apps & Connectors > Create
MCP server URL: https://cotlet.dev/mcp/v1/connect
Authentication: OAuth Settings > Connectors > Add custom connector
URL: https://cotlet.dev/mcp/v1/connect
Claude Code:
claude mcp add --transport http cotlet \
https://cotlet.dev/mcp/v1 \
--header "Authorization: Bearer $COTLET_API_KEY" // ~/.cursor/mcp.json
{
"mcpServers": {
"cotlet": {
"url": "https://cotlet.dev/mcp/v1",
"headers": { "Authorization": "Bearer ${env:COTLET_API_KEY}" }
}
}
} # ~/.codex/config.toml
[mcp_servers.cotlet]
url = "https://cotlet.dev/mcp/v1"
bearer_token_env_var = "COTLET_API_KEY" MCP Client Tool (inside an AI Agent)
Transport: HTTP Streamable
URL: https://cotlet.dev/mcp/v1
Auth: Bearer, <your key>
Tool: obat_read The quote, invoice and contact screens of Obat, one tool per job. Reads and drafts run at once; the 3 tools that email a client ask first.
Read quotes with their supply, labour and work lines, save a draft, then finalize and email it with or without e-signature.
list_quotes returns the newest quotes first, with the quote id, number (empty for a draft), client, job site, status and total excluding VAT. It reads the Quotes list of the account. Only a signed quote can be invoiced in Obat.
MCP callobat_read → list_quotes
REST endpointGET https://cotlet.dev/api/v1/obat/quotes
| Name | Type | Description |
|---|---|---|
| status string | string | Filter by status as the Quotes list shows it: draft, sent or signed. Omit for all. |
| client_id string | string | Only quotes of this client. |
| cursor string | string | Cursor from the previous page. |
{
"quotes": [
{
"quote_id": "qt_8f21c4",
"number": "DE-0412",
"client": "Martin",
"site": "Bathroom renovation",
"status": "signed",
"total_excl_vat": 1694
},
{
"quote_id": "qt_8f21c9",
"number": null,
"client": "Durand",
"site": "Roof repair",
"status": "draft",
"total_excl_vat": 2400
}
],
"next_cursor": null
} get_quote returns the lines in the order of the document with their kind (supply, labour or work item), quantity, unit price and VAT rate, then the totals. It also says whether e-signature was requested. Use it before send_quote to check the draft.
MCP callobat_read → get_quote
REST endpointGET https://cotlet.dev/api/v1/obat/quotes/{quote_id}
| Name | Type | Description |
|---|---|---|
| quote_id string required | string | Quote id from list_quotes. |
{
"quote_id": "quote_8c41d2"
} {
"quote_id": "qt_8f21c9",
"status": "draft",
"client": "Durand",
"site": "Roof repair",
"lines": [
{
"kind": "labour",
"label": "Roof repair labour",
"quantity": 16,
"unit": "h",
"unit_price_excl_vat": 50
},
{
"kind": "supply",
"label": "Tiles and fixings",
"quantity": 1,
"unit": "lot",
"unit_price_excl_vat": 1600
}
],
"total_excl_vat": 2400,
"e_signature_requested": false
} create_quote_draft saves the quote as a draft: it has no number and nobody is told. Obat gives the definitive number only when the quote is finalized, which send_quote does. Lines are supply, labour or work items, the three kinds Obat offers. The draft is returned with totals so you can check them before sending. A draft reaches nobody and you can delete it in Obat, so it does not wait for your OK.
MCP callobat_write → create_quote_draft
REST endpointPOST https://cotlet.dev/api/v1/obat/clients/{client_id}/quote-drafts
| Name | Type | Description |
|---|---|---|
| client_id string required | string | Client id from list_clients or create_client. |
| site_id string | string | Job site id from list_sites. |
| title string | string | Description shown on the quote. |
| lines array required | array | Lines, each with kind (supply, labour or work), label, quantity, unit, unit_price_excl_vat and vat_rate in percent. |
{
"client_id": "cl_5a90d1",
"site_id": "st_77c2e0",
"title": "Bathroom floor tiling",
"lines": [
{
"kind": "supply",
"label": "Stoneware tiles",
"quantity": 22,
"unit": "m2",
"unit_price_excl_vat": 32,
"vat_rate": 10
},
{
"kind": "labour",
"label": "Tile laying",
"quantity": 22,
"unit": "m2",
"unit_price_excl_vat": 45,
"vat_rate": 10
}
]
} {
"quote_id": "qt_8f21c4",
"status": "draft",
"number": null,
"client": "Martin",
"total_excl_vat": 1694,
"total_vat": 169.4,
"total_incl_vat": 1863.4
} send_quote finalizes the quote, so it gets its definitive number and can no longer be edited as a draft, then emails it to the client. With allow_e_signature the client gets a link and signs with a code sent to the mobile number; Obat uses Universign for this. It fails if the quote has no client or the client has no email. By default you confirm each call; you can switch that off for this tool.
MCP callobat_write → send_quote
REST endpointPOST https://cotlet.dev/api/v1/obat/quotes/{quote_id}
| Name | Type | Description |
|---|---|---|
| quote_id string required | string | Quote id from list_quotes or create_quote_draft. |
| allow_e_signature boolean | boolean | Let the client sign online. Needs the client mobile number. Defaults to false. |
| message string | string | Text of the email. Omit to keep the default. |
{
"quote_id": "quote_8c41d2"
} {
"quote_id": "qt_8f21c4",
"number": "DE-0413",
"status": "sent",
"e_signature_requested": true,
"sent_to": "martin@example.com"
} Deposit, progress and final invoices from a signed quote, sent once you have checked the draft.
list_invoices returns invoices with id, number, client, status, total excluding VAT, due date and how many reminders were sent (Obat allows up to three). Drafts are listed but have no number. Obat does not count drafts in its totals, and neither does get_receivables_summary.
MCP callobat_read → list_invoices
REST endpointGET https://cotlet.dev/api/v1/obat/invoices
| Name | Type | Description |
|---|---|---|
| status string | string | Filter by status: draft, sent, partially_paid, paid or overdue. These map to Brouillon, Envoyé, Payé partiellement, Payé and the En retard tab. Omit for all. |
| client_id string | string | Only invoices of this client. |
| cursor string | string | Cursor from the previous page. |
{
"invoices": [
{
"invoice_id": "inv_31a07e",
"number": "FA-0188",
"client": "Lefèvre",
"status": "overdue",
"total_excl_vat": 1800,
"due_date": "2026-10-28",
"reminders_sent": 0
},
{
"invoice_id": "inv_31a0b2",
"number": "FA-0191",
"client": "Bernard",
"status": "overdue",
"total_excl_vat": 950,
"due_date": "2026-11-02",
"reminders_sent": 2
}
],
"next_cursor": null
} get_invoice returns the invoice type (deposit, progress or final), its lines, totals, the quote it comes from and the payments recorded so far. It reads what the invoice screen shows.
MCP callobat_read → get_invoice
REST endpointGET https://cotlet.dev/api/v1/obat/invoices/{invoice_id}
| Name | Type | Description |
|---|---|---|
| invoice_id string required | string | Invoice id from list_invoices. |
{
"invoice_id": "invoice_8c41d2"
} {
"invoice_id": "inv_31a07e",
"number": "FA-0188",
"type": "deposit",
"from_quote": "DE-0412",
"client": "Lefèvre",
"status": "overdue",
"total_excl_vat": 1800,
"payments": []
} create_invoice_from_quote makes the invoice as a draft, with no number and nobody told, the same as the Facturer button on a quote. Obat only invoices a signed quote. In progress and final invoices Obat counts deposits already invoiced. Send the draft with send_invoice. The draft reaches nobody and you can delete it in Obat, so it does not wait for your OK.
MCP callobat_write → create_invoice_from_quote
REST endpointPOST https://cotlet.dev/api/v1/obat/quotes/{quote_id}/invoice-from-quotes
| Name | Type | Description |
|---|---|---|
| quote_id string required | string | Id of a signed quote. |
| invoice_type string required | string | deposit, progress or final. progress is the global progress invoice, not the line by line one. |
| percent number | number | Share of the quote to invoice, for deposit and progress. |
| amount_excl_vat number | number | Amount to invoice instead of a percent. |
{
"quote_id": "quote_8c41d2",
"invoice_type": "invoice type"
} {
"invoice_id": "inv_31a0c4",
"status": "draft",
"number": null,
"type": "deposit",
"from_quote": "DE-0412",
"total_excl_vat": 508.2
} send_invoice finalizes the draft, which gives it its definitive number and locks it, then emails it to the client. Obat allows deleting or cancelling a finalized invoice only under conditions, and a cancelled one needs a credit note, so check the draft with get_invoice first. By default you confirm each call; you can switch that off for this tool.
MCP callobat_write → send_invoice
REST endpointPOST https://cotlet.dev/api/v1/obat/invoices/{invoice_id}
| Name | Type | Description |
|---|---|---|
| invoice_id string required | string | Invoice id of a draft from list_invoices. |
| message string | string | Text of the email. Omit to keep the default. |
{
"invoice_id": "invoice_8c41d2"
} {
"invoice_id": "inv_31a0c4",
"number": "FA-0192",
"status": "sent",
"sent_to": "martin@example.com"
} The "Total reste à encaisser" figures and the numbered reminders of the "En retard" tab. No tool takes or moves money.
get_receivables_summary returns the total left to collect excluding VAT and the late part of it, as Obat shows on the home screen. Obat counts invoices with status Envoyé or Payé partiellement, late or not. Drafts and negative invoices are left out, and credit notes linked to invoices are not deducted.
MCP callobat_read → get_receivables_summary
REST endpointGET https://cotlet.dev/api/v1/obat/receivables-summary
No parameters.
{
"to_collect_excl_vat": 9650,
"of_which_late_excl_vat": 2750,
"invoices_counted": 6
} send_invoice_reminder does what the numbered reminder buttons in the En retard tab do: Obat builds an email, and this tool sends it. Obat allows up to three reminders per invoice, and the text comes from Settings under Envoi d'emails. It fails for an invoice that is not overdue. By default you confirm each call; you can switch that off for this tool.
MCP callobat_write → send_invoice_reminder
REST endpointPOST https://cotlet.dev/api/v1/obat/invoices/{invoice_id}/reminder
| Name | Type | Description |
|---|---|---|
| invoice_id string required | string | Id of an invoice with status overdue. |
| reminder_number number | number | Which reminder to send, 1 to 3 as Obat numbers them. Defaults to the next one. |
| message string | string | Replacement text. Omit to use the account reminder text. |
{
"invoice_id": "invoice_8c41d2"
} {
"invoice_id": "inv_31a07e",
"reminder_number": 1,
"status": "sent",
"sent_to": "lefevre@example.com"
} Find a client before quoting, or add the client and the job site address the quote should name.
list_clients returns each client with id, type (individual or professional), name, emails, phone numbers and addresses. Obat lets a client have several addresses, emails and phone numbers, and so does the result. Use it to find a client_id before drafting a quote.
MCP callobat_read → list_clients
REST endpointGET https://cotlet.dev/api/v1/obat/clients
| Name | Type | Description |
|---|---|---|
| search string | string | Part of a name to match. |
| cursor string | string | Cursor from the previous page. |
{
"clients": [
{
"client_id": "cl_5a90d1",
"type": "individual",
"name": "Martin",
"emails": [
"martin@example.com"
],
"phones": [
"+33 6 00 00 00 00"
]
}
],
"next_cursor": null
} list_sites returns the job sites of the Chantiers tab with id, name, client and address. A job site can have an address that differs from the client billing address.
MCP callobat_read → list_sites
REST endpointGET https://cotlet.dev/api/v1/obat/sites
| Name | Type | Description |
|---|---|---|
| client_id string | string | Only job sites of this client. |
| cursor string | string | Cursor from the previous page. |
{
"sites": [
{
"site_id": "st_77c2e0",
"name": "Bathroom renovation",
"client": "Martin",
"address": "12 rue des Lilas, Nantes"
}
],
"next_cursor": null
} create_client adds the client to the Contacts list, as the New client button in a quote does. It reaches nobody, so it does not wait for your OK; Cotlet has no delete tool, so remove a client by hand in Obat. Run list_clients first to avoid a duplicate.
MCP callobat_write → create_client
REST endpointPOST https://cotlet.dev/api/v1/obat/clients
| Name | Type | Description |
|---|---|---|
| name string required | string | Client name. |
| type string | string | individual or professional. Defaults to individual. |
| email string | string | Email address. |
| phone string | string | Mobile or landline number. Needed later for e-signature. |
| address string | string | Billing address on one line. |
{
"name": "Jane Doe"
} {
"client_id": "cl_5a90d1",
"name": "Martin",
"type": "individual"
} create_site adds a job site, as New job site does in a quote. It reaches nobody, so it does not wait for your OK; remove it by hand in Obat if you do not need it. A quote draft can then name this job site.
MCP callobat_write → create_site
REST endpointPOST https://cotlet.dev/api/v1/obat/clients/{client_id}/sites
| Name | Type | Description |
|---|---|---|
| client_id string required | string | Client id from list_clients. |
| name string required | string | Job site name. |
| address string | string | Address if it differs from the client billing address. |
{
"client_id": "client_8c41d2",
"name": "Jane Doe"
} {
"site_id": "st_77c2e0",
"name": "Bathroom renovation",
"client_id": "cl_5a90d1"
} Your signed-in Obat browser profile, AES-256-GCM encrypted, in Finland. Never your password.
The 14 Obat tools. The session cookie stays in the Cloud Browser.
The quotes, invoices, clients and job sites your account and plan show, and nothing more.
Your Obat password, email and subscription, the Compte Pro and bank connection, the Pennylane link and accountant access, e-invoicing settings, and deleting any document.
You sign in again yourself, in the same Cloud Browser.
Disable Obat for agents, reset the browser, or change your password.
You type your Obat password yourself; the agent only uses the session that sign-in leaves behind. Our site scores A+ on Qualys SSL Labs, securityheaders.com and Mozilla Observatory (live results).
The tools work through the pages you use in Obat, so an update to those screens does not stop your quotes and invoices. Cotlet watches the apps it serves and updates the Obat server when Obat changes.
New Obat features become available to your agent. It still sees only what your own account and plan can see.
Cotlet never sees or stores your password. If Obat signs you out, one click in the Cotlet console reopens the Cloud Browser so you can sign in again.
| Action | How to put it right |
|---|---|
| Client or job site added | Remove it by hand in Contacts or Chantiers |
| Quote or invoice draft | Delete the draft in Obat; it had no number and reached nobody |
| Quote sent | Already with your client: tell them, then send a corrected quote |
| Invoice sent | Numbered and locked: Obat cancels it with a credit note (avoir) |
| Reminder sent | Already with your client: follow up with them directly |
The 3 tools that email a client (send_quote, send_invoice, send_invoice_reminder) ask first: by default you confirm each call, and you can switch that off per tool. The other 4 write tools only save drafts, clients and job sites, which reach nobody, and the 7 read tools run at once.
{
"name": "create_quote_draft",
"arguments": {
"client_id": "cl_5a90d1",
"site_id": "st_77c2e0",
"title": "Bathroom floor tiling",
"lines": [
{
"kind": "supply",
"label": "Stoneware tiles",
"quantity": 22,
"unit": "m2",
"unit_price_excl_vat": 32,
"vat_rate": 10
},
{
"kind": "labour",
"label": "Tile laying",
"quantity": 22,
"unit": "m2",
"unit_price_excl_vat": 45,
"vat_rate": 10
}
]
}
} curl -X POST https://cotlet.dev/api/v1/obat/clients/cl_5a90d1/quote-drafts \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"st_77c2e0","title":"Bathroom floor tiling","lines":[{"kind":"supply","label":"Stoneware tiles","quantity":22,"unit":"m2","unit_price_excl_vat":32,"vat_rate":10},{"kind":"labour","label":"Tile laying","quantity":22,"unit":"m2","unit_price_excl_vat":45,"vat_rate":10}]}' {
"quote_id": "qt_8f21c4",
"status": "draft",
"number": null,
"client": "Martin",
"total_excl_vat": 1694,
"total_vat": 169.4,
"total_incl_vat": 1863.4
} The example drafts a 22 m² bathroom floor: €704 of stoneware tiles and €990 of laying at 10% VAT, €1,863.40 in total, saved with no number and sent to nobody. A cron job or n8n flow can make the same call over REST at /api/v1/obat with the same key and price, in JSON. Failed calls are free.
About $18 a monthfor an artisan sending about twelve quotes and twelve invoices a month, 3,120 credits. Your Obat plan stays as it is.
| Job | Calls | Credits |
|---|---|---|
| Morning check of quotes and invoices | 2 × 22 | 440 |
| Quote drafts with client and job site | 4 × 12 | 480 |
| Quotes sent for e-signature | 1 × 10 | 100 |
| Deposit invoices from signed quotes | 3 × 6 | 180 |
| Final invoices at the end of a job | 3 × 6 | 180 |
| Overdue invoice reminders | 2 × 8 | 160 |
| Monday cash to collect | 2 × 4 | 80 |
| Cloud Browser, 30 days | 1,500 | |
| Total | 162 calls | 3,120 |
The $29 pack covers a typical month for most owners.
Credit packs are one-time purchases, not a subscription. The month above is our own example, not measured customer usage.
| Credits | Price, one time | Calls at 10 credits | Per 1,000 credits |
|---|---|---|---|
| 5,000 | $29 | 500 | $5.80 |
| 15,000 | $79 | 1,500 | $5.27 |
| 32,000 | $149 | 3,200 | $4.66 |
| 60,000 | $249 | 6,000 | $4.15 |
Only successful calls use credits; failed calls and timeouts cost nothing. At a balance of 0 calls pause, never a surprise charge. Authenticate with the Authorization: Bearer header.
| Option | What it does | Where it stops |
|---|---|---|
| Obat AI voice quotes | A paid option (29 € excl. VAT a month on the pricing page) that drafts a priced quote from your voice, text, a photo or a PDF. | It drafts quotes inside Obat; sending, invoicing and reminders stay with you. |
| Zapier, Make, n8n | No Obat app on Zapier or n8n, and none found on Make. | Nothing to trigger or act on in Obat. |
| Official API | None published; no plan on the pricing page lists one. | Nothing to build on. |
| Pennylane link, CSV, XLSX, FEC exports | Send finalized documents, purchases and payments to your accounting. | Accounting only: no quotes, invoices or reminders. |
| By hand | Open each quote and invoice and click through. | Only while you are at the screen. |
Only Cotlet lets your agent do the daily Obat work on every screen you use, reading and writing, from ChatGPT, Claude or any MCP client, with no API key from Obat and on your current plan.
Take Group sp. z o.o. makes Cotlet. It is a software company registered in Poland, EU (VAT PL6342984273), working since 2019, founded by Bart Krawczyk (Co-founder, CTO) and Jake Slugocki (Co-founder, SEO, sales and marketing). Questions about the Obat tools go to contact@cotlet.dev.
Sign up free at https://cotlet.dev/signup?app=obat, turn on Obat under Integrations in the console and sign in at https://www.obat.fr/login in your Cloud Browser. Then connect your AI agent and ask it which invoices are late. The trial needs no card.
Yes, because the agent works in your own account and sees what your plan shows. Per the pricing page, purchasing, job-site profitability and time tracking start at the Croissance plan, and the planning for teams of 2 to 50 is there too. Quotes, invoices, clients and reminders are in every plan.
No. Obat connects finalized invoices to Pennylane on its own (Pennylane Essentiel plan or higher), and exports files for other accounting software. Cotlet works on the quote and invoice screens. It does not touch your accounting link or your accountant access.
The user whose quotes and invoices the agent should handle. Obat sells extra user licences for staff, and the agent sees only what the signed-in user can see.
Yes. Your clients read French, so ask for French line labels and email text, or write the prompt in French. The tools keep Obat's own words, such as Devis, Factures and En retard.
Only in how it is called. Both carry the same 14 tools, inputs, answers, API key and price. Agents use MCP; scripts and n8n HTTP steps use REST.
No. Cotlet is independent and not affiliated with Obat.
Free 7-day trial with 2,000 credits, no card needed.
May we use Google Analytics to see which pages help people? It sets cookies only if you accept. No ads, and we never sell data. Cookie policy