This workflow corresponds to n8n.io template #10599 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"nodes": [
{
"id": "752a1ab6-274c-4f09-9bf1-e2dba414aaf1",
"name": "Receive Company Request1",
"type": "n8n-nodes-base.webhook",
"position": [
-816,
3152
],
"parameters": {
"path": "/api/v1/get-customers",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "66762aac-2d62-4d59-9956-816476d0f92f",
"name": "Prepare Dynamic Filter1",
"type": "n8n-nodes-base.function",
"position": [
-576,
3152
],
"parameters": {
"functionCode": "// const query = $json[\"query\"] || {}\n// const filters = []\n// if (query.name) filters.push([\"name\", \"Like\", query.name])\n// if (query.country) filters.push([\"country_code\", \"=\", query.country])\n// const limit = query.limit ? parseInt(query.limit) : 25\n// const response_format = query.response_format || 'json'\n// return [{ json: { filters, limit, response_format } }]\n\nconst query = $json[\"query\"] || {};\n\n// Validate required 'name' parameter\nif (!query.name || query.name.trim() === \"\") {\n return [\n {\n json: {\n success: false,\n message: \"Missing required parameter: name\",\n },\n },\n ];\n}\n\nconst filters = [];\nfilters.push([\"name\", \"Like\", query.name]); // name is mandatory\n\nconst response_format = query.response_format || \"json\";\n\nreturn [\n {\n json: { filters, response_format },\n },\n];"
},
"typeVersion": 1
},
{
"id": "e727d97c-678b-41b8-8db4-d1615c73a116",
"name": "Prepare Output Data1",
"type": "n8n-nodes-base.function",
"position": [
0,
3152
],
"parameters": {
"functionCode": "if (items.length === 0 || Object.keys(items[0].json).length === 0) {\n return [{ json: { success: false, message: 'No matching company records found' } }]\n}\nconst data = items.map(item => ({ ...item.json, report_generated_on: new Date().toISOString() }))\nreturn data.map(d => ({ json: d }))"
},
"typeVersion": 1
},
{
"id": "9187426f-d4d0-4461-af73-3f31cdb0cc17",
"name": "Check If Excel Required1",
"type": "n8n-nodes-base.if",
"position": [
288,
3152
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $('Prepare Dynamic Filter1').item.json.response_format }}",
"value2": "excel"
}
]
}
},
"typeVersion": 1
},
{
"id": "ed6030ad-11f0-43f6-aee5-147ee0c055de",
"name": "Convert to Excel1",
"type": "n8n-nodes-base.convertToFile",
"position": [
896,
3104
],
"parameters": {
"options": {},
"operation": "xlsx"
},
"typeVersion": 1.1
},
{
"id": "0e6e1540-4c2e-45fe-a75a-6e511a95937b",
"name": "Respond with File1",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1216,
3104
],
"parameters": {
"options": {},
"respondWith": "binary"
},
"typeVersion": 1.4
},
{
"id": "d64e68cf-c80c-4633-bc4f-614d572ca762",
"name": "Respond with JSON1",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1216,
3504
],
"parameters": {
"options": {},
"respondWith": "allIncomingItems"
},
"typeVersion": 1.4
},
{
"id": "d2f28f28-a541-42d1-aaf8-94ab14723a53",
"name": "Overview Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1792,
2288
],
"parameters": {
"width": 900,
"height": 620,
"content": "## How it works\nThis workflow provides an API endpoint `/api/v1/get-customers` that retrieves customer contact records directly from your Odoo instance. It\u2019s designed for teams who need to query or export customer data on demand \u2014 either in JSON for integrations or Excel (.xlsx) for reporting.\n\nWhen a request is made, the workflow:\n1. Accepts query parameters (`name`, `response_format`).\n2. Validates the name input (required for search).\n3. Fetches all matching customers (non-companies) from Odoo using an `Like` filter for partial matches.\n4. Dynamically returns either a JSON response or an Excel file download depending on the `response_format` parameter.\n\nThis makes it ideal for quick data exports\n\n\n\n## Setup steps\n1. Open the Webhook node and note the endpoint `/api/v1/get-customers`.\n2. Configure your Odoo API credentials in the Odoo node.\n3. Optionally update the `fieldsList` in the Odoo node to include more contact fields (email, city, etc.).\n4. Test using a browser or Postman: \n - `/api/v1/get-customers?name=Demo&response_format=json` \n - `/api/v1/get-customers?name=Demo&response_format=excel`"
},
"typeVersion": 1
},
{
"id": "ad743706-da44-436c-a330-96f289469989",
"name": "Fetch Customer",
"type": "n8n-nodes-base.odoo",
"position": [
-320,
3152
],
"parameters": {
"options": {
"fieldsList": [
"display_name",
"name",
"email",
"phone",
"mobile",
"parent_id",
"country_code",
"country_id"
]
},
"resource": "custom",
"operation": "getAll",
"returnAll": true,
"filterRequest": {
"filter": [
{
"value": "={{ $json.filters[0][2] && $json.filters[0][2].toString().trim() !== '' ? $json.filters[0][2] : \"False\" }}",
"operator": "like",
"fieldName": "name"
}
]
},
"customResource": "res.partner"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "5d55b9d2-a30b-4efd-8a22-e4d80851163a",
"name": "Overview Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
2928
],
"parameters": {
"color": 7,
"width": 452,
"height": 380,
"content": "## Request & Validation\nReceives the API request and checks for the required \u201cname\u201d parameter.\nReturns a validation message if missing."
},
"typeVersion": 1
},
{
"id": "e8d5c637-2adc-4c45-ab56-81eabe9af5ee",
"name": "Overview Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
2928
],
"parameters": {
"color": 7,
"width": 276,
"height": 380,
"content": "## Search Records from Odoo\n- Queries `res.partner` \n**Contact Table** records in Odoo using \u201cLike\u201d for partial matches.\n- Customize the fields in the node options if needed.\n- **Note: Name search is case-sensitive.**"
},
"typeVersion": 1
},
{
"id": "5b009e21-3259-430b-aaf1-044e5c364eb8",
"name": "Overview Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
2928
],
"parameters": {
"color": 7,
"width": 276,
"height": 380,
"content": "## Prepare data and manage response json object."
},
"typeVersion": 1
},
{
"id": "af201ab6-7f0f-4806-bba1-7d9f718eeb75",
"name": "Overview Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
208,
2928
],
"parameters": {
"color": 7,
"width": 276,
"height": 380,
"content": "## Check response_format\nIf response_format=excel \u2192 returns a downloadable Excel file.\nOtherwise, returns JSON with company data."
},
"typeVersion": 1
},
{
"id": "1b71d124-7d74-421c-882d-c67b6e6f9c08",
"name": "Return all data for create binary file",
"type": "n8n-nodes-base.code",
"position": [
592,
3104
],
"parameters": {
"jsCode": "return $input.all()"
},
"typeVersion": 2
},
{
"id": "4dab4b62-287e-48ab-851d-8f8277d4eb10",
"name": "Overview Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
512,
2928
],
"parameters": {
"color": 7,
"width": 276,
"height": 380,
"content": "## Prepare Data for Binary file."
},
"typeVersion": 1
},
{
"id": "d7dccf04-2209-4638-a535-175b8207a70d",
"name": "Overview Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
816,
2928
],
"parameters": {
"color": 7,
"width": 276,
"height": 380,
"content": "## Create excel file"
},
"typeVersion": 1
},
{
"id": "278e9a77-f740-4adb-8a9b-465cc48b56e2",
"name": "Overview Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1120,
2928
],
"parameters": {
"color": 7,
"width": 276,
"height": 380,
"content": "## Response to web-hook with excel file."
},
"typeVersion": 1
},
{
"id": "e86f38f1-12de-4da2-99e2-f5e4cf863b27",
"name": "Overview Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1136,
3328
],
"parameters": {
"color": 7,
"width": 276,
"height": 380,
"content": "## Response to web-hook with json object."
},
"typeVersion": 1
}
],
"connections": {
"Fetch Customer": {
"main": [
[
{
"node": "Prepare Output Data1",
"type": "main",
"index": 0
}
]
]
},
"Convert to Excel1": {
"main": [
[
{
"node": "Respond with File1",
"type": "main",
"index": 0
}
]
]
},
"Prepare Output Data1": {
"main": [
[
{
"node": "Check If Excel Required1",
"type": "main",
"index": 0
}
]
]
},
"Prepare Dynamic Filter1": {
"main": [
[
{
"node": "Fetch Customer",
"type": "main",
"index": 0
}
]
]
},
"Check If Excel Required1": {
"main": [
[
{
"node": "Return all data for create binary file",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond with JSON1",
"type": "main",
"index": 0
}
]
]
},
"Receive Company Request1": {
"main": [
[
{
"node": "Prepare Dynamic Filter1",
"type": "main",
"index": 0
}
]
]
},
"Return all data for create binary file": {
"main": [
[
{
"node": "Convert to Excel1",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
odooApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Odoo Customers API – Export to JSON or Excel provides a simple way to fetch customer records from your Odoo database and get them back either as a structured JSON response or a downloadable Excel (.xlsx) file. Listens for HTTP requests on the endpoint . Checks for the required…
Source: https://n8n.io/workflows/10599/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Blotato-Api. Uses @blotato/n8n-nodes-blotato. Webhook trigger; 53 nodes.
Social Media Poster - Dual Trigger. Uses @blotato/n8n-nodes-blotato. Webhook trigger; 23 nodes.
Bridge the gap between Monday.com and Jira with this intelligent n8n automation template.
Community Node Disclaimer: This workflow uses KlickTipp community nodes.
Demo Workflow How To Use Workflowstaticdata. Uses noOp, httpRequest, scheduleTrigger, stickyNote. Webhook trigger; 9 nodes.