External API v1 Documentation¶
This documentation describes the external API v1 compliant with Odoo 18 standards, using native Odoo API Key authentication.
Introduction¶
The API v1 is a complete rewrite of the AirDoo API compliant with Odoo 18 standards. It uses native Odoo API Key authentication (auth='api_key') and follows modern RESTful conventions.
Key Features¶
- Native Odoo authentication: Uses Odoo's built-in API Key system
- Standard JSON format: Structured responses with uniform metadata
- Idempotency: Idempotency key support to prevent duplicates
- Price validation: Automatic verification of calculated amounts
- Stripe integration: Secure payment flow with webhooks
- Secure Next.js architecture: Mandatory Route Handler to protect API keys
- Semantic versioning: Version 1.0.0
Base URL¶
https://your-odoo-instance.com/api/v1/airdoo/
Authentication¶
Authentication Method¶
The API v1 uses native Odoo API Key authentication via HTTP header:
Authorization: Bearer your_api_token
How to Get the API Key¶
- In Odoo:
AirDoo → Configuration → Settings - API Settings section: Click "Generate API Key"
- Use the technical user: The
airdoo_api_useris automatically created with the module
API User Configuration¶
The technical user is defined in data/airdoo_api_user_data.xml without a plaintext password. The password is randomly generated at installation via a post_init_hook.
Important: The password is automatically generated at installation. To retrieve the API key:
1. Go to Settings → Users & Companies → Users
2. Find "AirDoo API System User"
3. Click "Generate API Key" in the "Preferences" tab
HTTP Header Example¶
POST /api/v1/airdoo/availability HTTP/1.1
Host: your-odoo-instance.com
Authorization: Bearer your_api_token
Content-Type: application/json
Accept: application/json
Available Endpoints¶
1. POST /api/v1/airdoo/availability — Check Availability¶
Checks availability for a period and calculates the price.
Request¶
{
"accommodation_id": 1,
"checkin": "2026-06-15",
"checkout": "2026-06-20",
"guest_count": 2,
"extras": {
"breakfast": true,
"linen": false,
"late_checkin": true
}
}
Response (Success)¶
{
"success": true,
"data": {
"available": true,
"nights": 5,
"pricing": {
"base_price": 750.00,
"avg_price_per_night": 150.00,
"cleaning_fee": 80.00,
"tax": 45.65,
"extras": {
"breakfast": 75.00,
"late_checkin": 30.00
},
"discounts": {
"weekly": 0.10
},
"total": 980.65
},
"restrictions": {
"min_stay": 2,
"max_stay": 30,
"max_guests": 6,
"checkin_time": "15:00",
"checkout_time": "10:00"
},
"message": "Available"
},
"metadata": {
"api_version": "1.0",
"timestamp": "2026-02-28T12:00:00Z",
"endpoint": "v1"
}
}
Response (Not Available)¶
{
"success": true,
"data": {
"available": false,
"message": "Dates not available (conflict with booking CHALET2026-123)",
"nights": 0,
"pricing": null,
"restrictions": null
}
}
2. POST /api/v1/airdoo/bookings — Create a Booking¶
Creates a direct booking.
Request¶
{
"accommodation_id": 1,
"partner_data": {
"title": "Mr.",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com",
"phone": "+44712345678",
"address": {
"street": "123 Example Street",
"city": "London",
"zip": "SW1A 1AA",
"country": "United Kingdom"
}
},
"booking_data": {
"checkin_date": "2026-06-15",
"checkout_date": "2026-06-20",
"adults_count": 2,
"children_count": 1,
"babies_count": 0,
"guest_notes": "Wedding anniversary",
"payment_method": "stripe",
"payment_token": "tok_visa_123456",
"total_amount": 980.65
},
"extras": {
"breakfast": true,
"linen": false,
"late_checkin": true
}
}
Response (Success)¶
{
"success": true,
"data": {
"booking_id": 123,
"confirmation_code": "CHALET2026-123",
"partner_id": 456,
"invoice_url": "https://odoo/invoice/789",
"next_steps": [
"Confirmation email sent",
"Payment processed",
"Calendar updated"
]
},
"metadata": {
"api_version": "1.0",
"timestamp": "2026-02-28T12:00:00Z",
"endpoint": "v1"
}
}
3. GET /api/v1/airdoo/bookings/<booking_id> — Retrieve a Booking¶
Retrieves the details of an existing booking.
Response¶
{
"success": true,
"data": {
"id": 123,
"confirmation_code": "CHALET2026-123",
"accommodation_name": "The Mountain Chalet",
"checkin_date": "2026-06-15",
"checkout_date": "2026-06-20",
"nights": 5,
"guest_count": 3,
"composition": {
"adults": 2,
"children": 1,
"babies": 0
},
"total_amount": 980.65,
"status": "confirmed",
"partner": {
"id": 456,
"name": "John Smith",
"email": "john.smith@email.com",
"phone": "+44712345678"
}
}
}
4. GET /api/v1/airdoo/test — Test the API¶
Test endpoint to verify the API is working.
Response¶
{
"success": true,
"data": {
"status": "ok",
"message": "API v1 functional",
"timestamp": "2026-02-28T12:00:00Z",
"user": "airdoo_api_user",
"login": "airdoo_api_user"
}
}
Data Structures¶
PartnerData¶
interface PartnerData {
title?: string; // "Mr.", "Mrs.", "Ms."
first_name: string; // First name
last_name: string; // Last name
email: string; // Email (required)
phone?: string; // Phone
address?: {
street?: string;
city?: string;
zip?: string;
country?: string;
};
}
BookingData¶
interface BookingData {
checkin_date: string; // Format: "YYYY-MM-DD"
checkout_date: string; // Format: "YYYY-MM-DD"
adults_count: number;
children_count: number;
babies_count: number;
guest_notes?: string; // Notes for the host
payment_method: string; // "stripe", "bank_transfer", "cash"
payment_token: string; // Payment token
total_amount: number; // Total amount
}
Pricing¶
interface Pricing {
base_price: number;
avg_price_per_night: number;
cleaning_fee: number;
tax: number;
extras: Record<string, number>;
discounts: Record<string, number>;
total: number;
}
Usage Examples¶
cURL Example¶
# Test the API
curl -X GET \
-H "Authorization: Bearer your_api_token" \
https://your-odoo-instance.com/api/v1/airdoo/test
# Check availability
curl -X POST \
-H "Authorization: Bearer your_api_token" \
-H "Content-Type: application/json" \
-d '{
"accommodation_id": 1,
"checkin": "2026-06-15",
"checkout": "2026-06-20",
"guest_count": 2
}' \
https://your-odoo-instance.com/api/v1/airdoo/availability
Python Example¶
import requests
class AirDooV1API:
def __init__(self, base_url, api_key):
self.base_url = base_url.rstrip('/')
self.headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
def test(self):
response = requests.get(
f"{self.base_url}/api/v1/airdoo/test",
headers=self.headers
)
return response.json()
def check_availability(self, accommodation_id, checkin, checkout, guest_count=2):
response = requests.post(
f"{self.base_url}/api/v1/airdoo/availability",
headers=self.headers,
json={
'accommodation_id': accommodation_id,
'checkin': checkin,
'checkout': checkout,
'guest_count': guest_count,
}
)
return response.json()
# Usage
api = AirDooV1API(
base_url='https://your-odoo-instance.com',
api_key='your_api_key'
)
print(api.test())
Error Handling¶
Standard Error Format¶
{
"error": {
"code": 400,
"message": "Error description",
"details": {
"field": "checkin",
"reason": "Invalid date format"
}
}
}
Common Error Codes¶
| Code | Description | Likely Cause |
|---|---|---|
| 400 | Bad Request | Invalid or missing parameters |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Unauthorized access |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Data conflict (dates already booked) |
| 500 | Internal Server Error | Server error |
Migration from Old API¶
Endpoint Comparison¶
| Old API | New API v1 | Changes |
|---|---|---|
/airdoo/api/availability |
/api/v1/airdoo/availability |
Same functionality, new format |
/airdoo/api/create_booking |
/api/v1/airdoo/bookings |
RESTful naming |
| N/A | /api/v1/airdoo/bookings/<id> |
New GET endpoint |
| N/A | /api/v1/airdoo/test |
New test endpoint |
Key Changes¶
- Authentication: Bearer Token instead of the old system
- Response format: Standardized structure with
success,data,metadata - Versioning: All endpoints under
/api/v1/
Migration Example¶
Old code:
const response = await fetch('/airdoo/api/create_booking', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'call',
params: { accommodation_id: 1 }
})
});
New code:
const response = await fetch('/api/v1/airdoo/bookings', {
method: 'POST',
headers: {
'Authorization': 'Bearer your_api_token',
'Content-Type': 'application/json'
},
body: JSON.stringify({ accommodation_id: 1 })
});
Troubleshooting¶
Common Issues¶
- Error 401: Check API key in headers
- Error 404: Check URL and accommodation ID
- Error 500: Check Odoo logs for details
Test with cURL¶
curl -v -H "Authorization: Bearer your_token" http://localhost:8069/api/v1/airdoo/test
Support¶
- Email: support@kalpana.com.br
← Back: API Overview | Next: Calendar API
Version: 1.0.0 Last updated: 2026-02-28