Skip to content

Odoo '405 Method Not Allowed' and API Endpoint Errors Fix

DeployMonkey Team · March 24, 2026 9 min read

405 Method Not Allowed in Odoo API

When calling Odoo API endpoints, you may encounter:

HTTP/1.1 405 Method Not Allowed
Allow: POST

{"error": {"code": 404, "message": "404: Not Found"}}

TypeError: my_endpoint() got an unexpected keyword argument 'jsonrpc'

werkzeug.exceptions.MethodNotAllowed: 405 Method Not Allowed

Understanding Odoo Route Types

Odoo has two route types with different requirements:

Propertytype='json'type='http'
HTTP MethodPOST onlyGET or POST
Content-Typeapplication/jsonform or multipart
Request bodyJSON-RPC formatForm data or query params
ResponseJSON-RPC wrappedRaw HTML or JSON

Fix 1: Wrong HTTP Method for JSON Routes

# Odoo JSON routes ONLY accept POST
# Wrong:
curl -X GET https://odoo.example.com/api/data
# Returns: 405 Method Not Allowed

# Right:
curl -X POST https://odoo.example.com/api/data \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "params": {}}'

Fix 2: Missing JSON-RPC Wrapper

# Wrong — raw JSON without JSON-RPC envelope
curl -X POST https://odoo.example.com/api/data \
  -H "Content-Type: application/json" \
  -d '{"name": "test"}'
# Returns: TypeError or empty response

# Right — JSON-RPC envelope
curl -X POST https://odoo.example.com/api/data \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "call", "params": {"name": "test"}}'

# Note: for type='json' routes, your method parameters
# go inside the "params" object

Fix 3: Specifying HTTP Methods on Routes

# Default: type='json' only accepts POST
# To allow specific methods on type='http':
@http.route('/api/items', type='http', auth='public', methods=['GET'])
def list_items(self, **kwargs):
    return json.dumps({'items': []})

@http.route('/api/items', type='http', auth='public', methods=['POST'])
def create_item(self, **kwargs):
    return json.dumps({'status': 'created'})

# Wrong — trying to use methods parameter with type='json'
# type='json' ignores the methods parameter and always uses POST
@http.route('/api/data', type='json', auth='public', methods=['GET'])  # GET won't work
def get_data(self, **kwargs):
    pass

Fix 4: Route Not Found (404 vs 405)

# If you get 404 instead of 405, the route does not exist at all

# Check if the module defining the route is installed
# Settings > Apps > search for module name

# Verify the route is registered
# In odoo shell:
from odoo.http import root
for rule in root.routing_map.iter_rules():
    if 'api' in rule.rule:
        print(f"{rule.rule} -> {rule.methods}")

# Common issues:
# - Module not installed
# - Controller file not imported in __init__.py
# - Typo in route path

Fix 5: CSRF Token Issues

# For type='http' with auth='user', Odoo requires CSRF token
# Error: Session expired or invalid CSRF token

# Option 1: Disable CSRF for API endpoints
@http.route('/api/data', type='http', auth='public', csrf=False)
def get_data(self, **kwargs):
    pass

# Option 2: Include CSRF token in request
# Get token from session first, then include as parameter
curl -X POST https://odoo.example.com/api/data \
  -b "session_id=abc123" \
  -d "csrf_token=xyz789&name=test"

# type='json' routes are CSRF-exempt by default

Fix 6: Authentication Method Mismatch

# auth='user' requires a valid session (logged in via web)
# auth='public' allows anonymous access
# auth='none' bypasses authentication entirely

# For API endpoints called by external systems:
@http.route('/api/data', type='json', auth='public')
def get_data(self, **kwargs):
    # Validate API key or JWT manually
    api_key = request.httprequest.headers.get('Authorization')
    if not api_key:
        return {'error': 'Unauthorized'}
    # ... validate and proceed

# For internal endpoints:
@http.route('/api/internal', type='json', auth='user')
def internal_data(self, **kwargs):
    # request.env.user is available
    return {'user': request.env.user.name}

Debugging API Routes

# Test with curl and verbose output
curl -v -X POST https://odoo.example.com/api/endpoint \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "params": {}}'

# Check response headers for clues:
# Allow: POST  → you used the wrong method
# 404          → route doesn't exist
# 500          → route exists but code crashed

Prevention

DeployMonkey's AI agent validates API endpoint configurations and tests request formats during development. Route mismatches and authentication issues are caught before deployment.