| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Contacts (contacts)
• Sales (sale_management) • Discuss (mail) • Invoicing (account) |
| Lines of code | 1914 |
| Technical Name |
odoo_rest_api_gateway |
| License | OPL-1 |
| Website | https://www.auraodoo.tech/ |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Contacts (contacts)
• Sales (sale_management) • Discuss (mail) • Invoicing (account) |
| Lines of code | 1914 |
| Technical Name |
odoo_rest_api_gateway |
| License | OPL-1 |
| Website | https://www.auraodoo.tech/ |
REST API Gateway Pro
Odoo 19 Production-Ready REST API with JWT, Rate Limiting & Analytics
Watch Demo
Module Overview
JWT Authentication
Secure token-based authentication with access and refresh tokens. Tokens expire automatically.
SecurityAPI Key Management
Per-application keys with scope-based permissions and rate limiting controls.
AuthorizationRate Limiting
Per-minute and per-hour throttling with automatic IP blocking on violations.
ProtectionComplete Workflow
API Request Flow
-
Client Request
Client sends HTTP request with JWT token or API key
-
Middleware Processing
Request passes through api_middleware.py for authentication and validation
-
Authorization Check
Verify scope permissions (products_read, products_write, etc.)
-
Rate Limit Check
Check per-minute and per-hour limits for the API key
-
IP Whitelist Validation
Verify request IP against allowed IPs if configured
-
Controller Processing
Route to appropriate controller (product, order, customer)
-
Business Logic Execution
Execute create, read, update, or delete operations
-
Response Formatting
Serialize data using field whitelist for security
-
Request Logging
Save request/response info to api.log model for audit trail
-
JSON Response
Return formatted JSON with success/error status
Authentication Methods
| Method | Header | Format | Scope |
|---|---|---|---|
| JWT Token | Authorization | Bearer <access_token> | All capabilities |
| API Key | X-API-Key | <api_key> | By configuration |
Create Operations
Create Product
Endpoint Details
Method: POST
Path: /api/v1/products
Scope Required: products_write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
String | Yes | Product name/title |
default_code |
String | No | Internal product code/SKU |
barcode |
String | No | Product barcode |
list_price |
Float | No | Selling price |
standard_price |
Float | No | Cost price |
categ_id |
Integer | No | Category ID |
type |
String | No | consu, product, service |
description_sale |
String | No | Product description |
Processing Steps
- Validate JSON body format
- Check required fields (name)
- Filter writable fields from request
- Create product.template record in database
- Serialize response using PRODUCT_FIELDS whitelist
- Log request to api.log
- Return JSON response with created product data
Response
{
"success": true,
"data": {
"id": 1,
"name": "Example Product",
"default_code": "PROD001",
"list_price": 99.99,
"categ_id": {"id": 1, "name": "Electronics"},
"active": true
},
"message": "Product created successfully"
}
Create Order
Endpoint Details
Method: POST
Path: /api/v1/orders
Scope Required: orders_write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
partner_id |
Integer | Yes | Customer ID (res.partner) |
order_lines |
Array | Yes | Array of order line objects |
warehouse_id |
Integer | No | Default warehouse used |
notes |
String | No | Order notes/comments |
Order Line Structure
"order_lines": [
{
"product_id": 1,
"product_qty": 5,
"price_unit": 99.99
}
]
Processing Steps
- Parse JSON request body
- Validate partner_id exists
- Validate order_lines array
- Validate each product exists
- Create sale.order record
- Create sale.order.line records for each line
- Calculate totals and tax
- Return order data with confirmation status
Create Customer
Endpoint Details
Method: POST
Path: /api/v1/customers
Scope Required: customers_write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
String | Yes | Customer name |
email |
String | No | Email address |
phone |
String | No | Phone number |
street |
String | No | Address |
country_id |
Integer | No | Country ID |
is_company |
Boolean | No | Mark as company |
Processing Steps
- Validate JSON body
- Check required name field
- Filter writable fields
- Create res.partner record
- Validate email format if provided
- Serialize response data
- Log to audit trail
- Return created customer record
Authentication System
JWT Token Flow
Token Generation
-
User Login
POST /api/v1/auth/login with email/password -
Credential Validation
Verify user exists and password matches -
Token Creation
Access token (1 hour) and refresh token (7 days) generated via PyJWT -
Payload Encoding
Include user ID, token type, iat, and exp claims -
Token Response
Return both tokens to client for storage
Token Validation on Request
- Extract token from Authorization header
- Decode JWT with secret key
- Verify token type (access vs refresh)
- Check expiration timestamp
- Extract user ID from payload
- Grant access if valid
Token Configuration
| Algorithm | HS256 |
| Access Token TTL | 3600 seconds (1 hour) |
| Refresh Token TTL | 604800 seconds (7 days) |
| Secret Source | Database UUID + odoo-rest-api prefix |
API Key Authentication
Key Lifecycle
-
Key Generation
Auto-generated 64-character URL-safe token on creation -
Key Hashing
SHA-256 hash stored in database for security -
Scope Assignment
Assign permissions (products_read, products_write, etc.) -
Rate Limiting
Configure per-minute and per-hour limits -
IP Whitelist
Optionally restrict to specific IP addresses -
Expiration Date
Optional expiration for temporary keys
Key Validation Process
- Extract API key from X-API-Key header
- Compute SHA-256 hash of provided key
- Search for matching key record
- Check key is active (not revoked)
- Validate expiration date
- Load associated user and scopes
- Grant or deny access based on scopes
Usage Examples
Example 1: Create Product with JWT
Request
curl -X POST http://localhost:8069/api/v1/products \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "Wireless Keyboard",
"default_code": "KB001",
"list_price": 79.99,
"categ_id": 2,
"description_sale": "Ergonomic wireless keyboard"
}'
Response
{
"success": true,
"data": {
"id": 5,
"name": "Wireless Keyboard",
"default_code": "KB001",
"list_price": 79.99,
"categ_id": {"id": 2, "name": "Peripherals"},
"active": true,
"qty_available": 0
},
"message": "Product created successfully"
}
Example 2: Create Order with API Key
Request
curl -X POST http://localhost:8069/api/v1/orders \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"partner_id": 3,
"order_lines": [
{
"product_id": 1,
"product_qty": 2,
"price_unit": 99.99
},
{
"product_id": 5,
"product_qty": 1,
"price_unit": 79.99
}
]
}'
Response
{
"success": true,
"data": {
"id": 10,
"partner_id": {"id": 3, "name": "John Doe"},
"amount_total": 259.97,
"state": "draft",
"order_lines": [
{
"id": 25,
"product_id": {"id": 1, "name": "Mouse"},
"qty": 2
}
]
},
"message": "Order created successfully"
}
Example 3: Create Customer
Request
curl -X POST http://localhost:8069/api/v1/customers \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0123",
"street": "123 Main St",
"country_id": 1,
"is_company": false
}'
Response
{
"success": true,
"data": {
"id": 8,
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0123",
"street": "123 Main St",
"country_id": {"id": 1, "name": "Belgium"},
"is_company": false,
"active": true
},
"message": "Customer created successfully"
}
Example 4: Error Response
Missing Required Field
{
"success": false,
"error": {
"code": 400,
"message": "Missing required field: name"
}
}
Invalid JSON
{
"success": false,
"error": {
"code": 400,
"message": "Invalid JSON body"
}
}
Rate Limit Exceeded
{
"success": false,
"error": {
"code": 429,
"message": "Rate limit exceeded. Max 60 requests per minute"
}
}
Security Features
Data Protection
- Field whitelist sanitization
- Company isolation
- User context isolation
- Many2one relation protection
Access Control
- Scope-based permissions
- IP whitelist filtering
- Rate limiting enforcement
- API key revocation
Support & Documentation
For more information, visit the Swagger documentation at:
/api/docs
Odoo Proprietary License v1.0 This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file). You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one). It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software. The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Please log in to comment on this module