{"openapi":"3.1.0","info":{"title":"Odoo (BYOK) API","version":"0.1.0","description":"Odoo (BYOK) lets an AI assistant read your own Odoo data through the Odoo API with a key you supply (Odoo API key (Preferences, Account Security, New API Key)). Read-only: 7 tools (list_records, search_records, find_by_name, read_record, count_records, count_matching_records, describe_fields). The BYOK key travels with each request, is used for that one call only and is never stored, logged or...\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://byok-odoo.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"agent@connectorbay.com","url":"https://connectorbay.com/byok-odoo/docs"},"termsOfService":"https://connectorbay.com/byok-odoo/terms"},"servers":[{"url":"https://byok-odoo.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/byok-odoo/docs"},"security":[{"upstreamKey":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."},"upstreamKey":{"type":"apiKey","in":"header","name":"X-Upstream-Key","description":"Your own key for the service this connector wraps (bring your own key). Used for that one call only; never stored, logged or cached."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/list_records":{"post":{"operationId":"list_records","summary":"List records of one model with up to six fields you name (display_name by default), sorted and paged. Needs Odoo 19 and ","description":"List records of one model with up to six fields you name (display_name by default), sorted and paged. Needs Odoo 19 and a plan with external API access. Use for \"List my 20 most recently changed Odoo contacts\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"database":{"description":"Your Odoo Online database subdomain: the part before .odoo.com, for example 'mycompany' for mycompany.odoo.com.","maxLength":200,"pattern":"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$","title":"Database","type":"string"},"model":{"description":"Technical model name to read, for example 'res.partner' (contacts), 'sale.order' (sales orders) or 'account.move' (invoices and bills).","enum":["res.partner","product.template","product.product","product.category","sale.order","sale.order.line","purchase.order","account.move","account.payment","crm.lead","project.project","project.task","stock.picking","stock.quant","res.company"],"title":"Model","type":"string"},"field_1":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":"display_name","description":"Name of a field to return; display_name, create_date and write_date exist on every model.","title":"Field 1"},"field_2":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 2"},"field_3":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 3"},"field_4":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 4"},"field_5":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 5"},"field_6":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 6"},"order":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":"id desc","description":"Sort expression such as 'write_date desc' or 'name asc'.","title":"Order"},"limit":{"anyOf":[{"maximum":200,"minimum":1,"type":"integer"},{"type":"null"}],"default":20,"description":"How many records to return (1 to 200).","title":"Limit"},"offset":{"anyOf":[{"maximum":1000000,"minimum":0,"type":"integer"},{"type":"null"}],"default":0,"description":"How many records to skip, for paging.","title":"Offset"}},"required":["database","model"],"title":"list_recordsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/search_records":{"post":{"operationId":"search_records","summary":"List records of one model that match a single condition (field, operator, value), with up to six fields you name. Use fo","description":"List records of one model that match a single condition (field, operator, value), with up to six fields you name. Use for \"Find Odoo contacts whose name contains 'deco'\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"database":{"description":"Your Odoo Online database subdomain: the part before .odoo.com, for example 'mycompany' for mycompany.odoo.com.","maxLength":200,"pattern":"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$","title":"Database","type":"string"},"model":{"description":"Technical model name to read, for example 'res.partner' (contacts), 'sale.order' (sales orders) or 'account.move' (invoices and bills).","enum":["res.partner","product.template","product.product","product.category","sale.order","sale.order.line","purchase.order","account.move","account.payment","crm.lead","project.project","project.task","stock.picking","stock.quant","res.company"],"title":"Model","type":"string"},"filter_field":{"description":"Field to filter on, for example 'name' or 'write_date'.","maxLength":100,"title":"Filter Field","type":"string"},"filter_operator":{"description":"Comparison operator: =, !=, >, >=, <, <=, like, ilike (case-insensitive contains, use % as wildcard).","enum":["=","!=",">",">=","<","<=","like","ilike","in","not in"],"title":"Filter Operator","type":"string"},"filter_value":{"description":"Value to compare with (text, number or date such as 2026-01-01).","maxLength":200,"title":"Filter Value","type":"string"},"field_1":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":"display_name","description":"Name of a field to return; display_name, create_date and write_date exist on every model.","title":"Field 1"},"field_2":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 2"},"field_3":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 3"},"field_4":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 4"},"field_5":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 5"},"field_6":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 6"},"order":{"anyOf":[{"maxLength":100,"type":"string"},{"type":"null"}],"default":"id desc","description":"Sort expression such as 'write_date desc' or 'name asc'.","title":"Order"},"limit":{"anyOf":[{"maximum":200,"minimum":1,"type":"integer"},{"type":"null"}],"default":20,"description":"How many records to return (1 to 200).","title":"Limit"},"offset":{"anyOf":[{"maximum":1000000,"minimum":0,"type":"integer"},{"type":"null"}],"default":0,"description":"How many records to skip, for paging.","title":"Offset"}},"required":["database","model","filter_field","filter_operator","filter_value"],"title":"search_recordsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/find_by_name":{"post":{"operationId":"find_by_name","summary":"Find records of one model whose display name matches a text (case-insensitive contains). Returns pairs of [id, display n","description":"Find records of one model whose display name matches a text (case-insensitive contains). Returns pairs of [id, display name]. Use for \"What is the Odoo ID of the contact called Deco Addict\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"database":{"description":"Your Odoo Online database subdomain: the part before .odoo.com, for example 'mycompany' for mycompany.odoo.com.","maxLength":200,"pattern":"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$","title":"Database","type":"string"},"model":{"description":"Technical model name to read, for example 'res.partner' (contacts), 'sale.order' (sales orders) or 'account.move' (invoices and bills).","enum":["res.partner","product.template","product.product","product.category","sale.order","sale.order.line","purchase.order","account.move","account.payment","crm.lead","project.project","project.task","stock.picking","stock.quant","res.company"],"title":"Model","type":"string"},"name":{"description":"Text to look for in the display name.","maxLength":100,"title":"Name","type":"string"},"limit":{"anyOf":[{"maximum":100,"minimum":1,"type":"integer"},{"type":"null"}],"default":10,"description":"How many matches to return (1 to 100).","title":"Limit"}},"required":["database","model","name"],"title":"find_by_nameArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/read_record":{"post":{"operationId":"read_record","summary":"Read one record of a model by its ID with up to six fields you name. Use for \"Show fields name and email of Odoo contact","description":"Read one record of a model by its ID with up to six fields you name. Use for \"Show fields name and email of Odoo contact 25\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"database":{"description":"Your Odoo Online database subdomain: the part before .odoo.com, for example 'mycompany' for mycompany.odoo.com.","maxLength":200,"pattern":"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$","title":"Database","type":"string"},"model":{"description":"Technical model name to read, for example 'res.partner' (contacts), 'sale.order' (sales orders) or 'account.move' (invoices and bills).","enum":["res.partner","product.template","product.product","product.category","sale.order","sale.order.line","purchase.order","account.move","account.payment","crm.lead","project.project","project.task","stock.picking","stock.quant","res.company"],"title":"Model","type":"string"},"record_id":{"description":"Record ID.","minimum":1,"title":"Record Id","type":"integer"},"field_1":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":"display_name","description":"Name of a field to return; display_name, create_date and write_date exist on every model.","title":"Field 1"},"field_2":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 2"},"field_3":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 3"},"field_4":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 4"},"field_5":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 5"},"field_6":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Name of a field to return, for example 'name' or 'write_date'.","title":"Field 6"}},"required":["database","model","record_id"],"title":"read_recordArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/count_records":{"post":{"operationId":"count_records","summary":"Count all records of one model. Use for \"How many Odoo contacts are there\".","description":"Count all records of one model. Use for \"How many Odoo contacts are there\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"database":{"description":"Your Odoo Online database subdomain: the part before .odoo.com, for example 'mycompany' for mycompany.odoo.com.","maxLength":200,"pattern":"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$","title":"Database","type":"string"},"model":{"description":"Technical model name to read, for example 'res.partner' (contacts), 'sale.order' (sales orders) or 'account.move' (invoices and bills).","enum":["res.partner","product.template","product.product","product.category","sale.order","sale.order.line","purchase.order","account.move","account.payment","crm.lead","project.project","project.task","stock.picking","stock.quant","res.company"],"title":"Model","type":"string"}},"required":["database","model"],"title":"count_recordsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/count_matching_records":{"post":{"operationId":"count_matching_records","summary":"Count the records of one model that match a single condition (field, operator, value). Use for \"How many Odoo sales orde","description":"Count the records of one model that match a single condition (field, operator, value). Use for \"How many Odoo sales orders were changed since 2026-01-01\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"database":{"description":"Your Odoo Online database subdomain: the part before .odoo.com, for example 'mycompany' for mycompany.odoo.com.","maxLength":200,"pattern":"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$","title":"Database","type":"string"},"model":{"description":"Technical model name to read, for example 'res.partner' (contacts), 'sale.order' (sales orders) or 'account.move' (invoices and bills).","enum":["res.partner","product.template","product.product","product.category","sale.order","sale.order.line","purchase.order","account.move","account.payment","crm.lead","project.project","project.task","stock.picking","stock.quant","res.company"],"title":"Model","type":"string"},"filter_field":{"description":"Field to filter on, for example 'name' or 'write_date'.","maxLength":100,"title":"Filter Field","type":"string"},"filter_operator":{"description":"Comparison operator: =, !=, >, >=, <, <=, like, ilike (case-insensitive contains, use % as wildcard).","enum":["=","!=",">",">=","<","<=","like","ilike","in","not in"],"title":"Filter Operator","type":"string"},"filter_value":{"description":"Value to compare with (text, number or date such as 2026-01-01).","maxLength":200,"title":"Filter Value","type":"string"}},"required":["database","model","filter_field","filter_operator","filter_value"],"title":"count_matching_recordsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/describe_fields":{"post":{"operationId":"describe_fields","summary":"Describe the fields of one model: label, type, related model and selection values. Optionally restrict to named fields. ","description":"Describe the fields of one model: label, type, related model and selection values. Optionally restrict to named fields. Use for \"Which fields does the Odoo sales order model have\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"database":{"description":"Your Odoo Online database subdomain: the part before .odoo.com, for example 'mycompany' for mycompany.odoo.com.","maxLength":200,"pattern":"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$","title":"Database","type":"string"},"model":{"description":"Technical model name to read, for example 'res.partner' (contacts), 'sale.order' (sales orders) or 'account.move' (invoices and bills).","enum":["res.partner","product.template","product.product","product.category","sale.order","sale.order.line","purchase.order","account.move","account.payment","crm.lead","project.project","project.task","stock.picking","stock.quant","res.company"],"title":"Model","type":"string"},"field_name":{"anyOf":[{"maxLength":200,"type":"string"},{"type":"null"}],"default":null,"description":"Only describe this field; leave empty for all fields.","title":"Field Name"}},"required":["database","model"],"title":"describe_fieldsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}