Stop Sale & Allotment
Manage room availability with the stop sale calendar — set Free Sale, Open Sale, Stop Sale, On Request, and Blocked states per room per day.
Overview
The stop sale module manages availability status for individual room types by date. Each room type in a property can have one of five states per day:
| Code | Name | Color | Meaning |
|---|---|---|---|
0 |
Free Sale | Green | Room is freely available, no restrictions |
1 |
Open Sale | Blue | Room is open for reservations |
2 |
Stop Sale | Red | Room is closed — no new reservations |
3 |
On Request | Yellow | Available on request/approval only |
4 |
Blocked | Grey | Internally blocked, not available |
Data Models
Stopsale — links a user and property to a stop sale configuration:
Stopsale
├── user → FK(User)
├── property → FK(Property)
└── date_update → DateTimeField(auto_now)
Event — one record per room and date combination:
Event
├── room → FK(Room, related_name='events')
├── date → DateField
├── color → PositiveSmallIntegerField (0–4, see table above)
└── Meta: unique_together = ['room', 'date']
Source — named stop sale sources for categorization:
Source
├── user → FK(User)
└── name → CharField(50)
API Endpoints
Rooms list (calendar view):
/api/stop-sale/{hotel_id}/
🔐 Auth required
Get rooms with their events for a hotel.
/api/stop-sale/save/
🔐 Auth required
Save rooms configuration.
Events (individual day operations):
/api/stop-sale/event/create/
🔐 Auth required
Create an event (set a day's status).
/api/stop-sale/event/{pk}/update/
🔐 Auth required
Update an existing event.
/api/stop-sale/event/{pk}/delete/
🔐 Auth required
Delete an event (resets to no state).
Export & Distribution:
/api/stop-sale/pdf/{hotel_id}/
🔐 Auth required
Download the stop sale calendar as a PDF.
/api/stop-sale/pdf/{hotel_id}/send-mail/{mailing_list_id}/
🔐 Auth required
Email the calendar PDF to a mailing list.
Partner API (token-based, no auth required):
/api/stop-sale/StopSale-Export/{token}/
Export stop sale data for a partner token (legacy).
/api/v1/stop-sale/{token}/
Modern stop sale export (JSON). Preferred for new integrations.
Creating Stop Sale Events
Send a POST request to create a single event for a room on a given date. The color field is the integer code from the status table above.
POST /api/stop-sale/event/create/
{
"room": 42,
"date": "2026-06-15",
"color": 2
}
A successful request returns 201 Created with the event object. To set a range of dates, send multiple event creation requests — one per date.
Unique constraint
The Event model enforces unique_together = ['room', 'date']. Use the PUT /api/stop-sale/event/{pk}/update/ endpoint to change the status of an existing event rather than creating a duplicate.
Calendar View
The GET /api/stop-sale/{hotel_id}/ endpoint returns all rooms for a hotel together with their event data. The response structure is:
{
"rooms": [
{
"id": 1,
"name": "Standard Room",
"events": [
{"date": "2026-06-15", "color": 2},
{"date": "2026-06-16", "color": 2}
]
}
]
}
Allotment
The allotment concept in Ananas GDS represents the negotiated stop sale deadline defined in a partner contract. The ss_deadline field in a Contract object specifies how many days in advance a stop sale must be applied. The to_special_allotment field controls whether allotment is:
- S (Special stop-sale allotment) — Room-specific allotment. Different room types can carry independent stop sale deadlines.
- G (General accommodations stop-sale) — Property-wide allotment. A single deadline applies to the entire property.
See the Partners & Contracts documentation for the full contract model including allotment fields.
Propagation to Tour Operators
Stop sale events are propagated to tour operators in two ways:
- API pull — TOs call
GET /api/v1/stop-sale/{token}/to fetch current events on demand. This is the preferred integration method for automated systems. - PDF export — The calendar PDF can be generated and emailed to mailing list contacts via the
POST /api/stop-sale/pdf/{hotel_id}/send-mail/{mailing_list_id}/endpoint.
Token-based partner access
The /api/v1/stop-sale/{token}/ endpoint does not require an Authorization header. The API token embedded in the URL path identifies the partner and controls which property data is returned.
Sub-User Access
Sub-users require the stop_sales permission flag on their UserPermission object to access stop sale endpoints. Managers always have access.
if not user.is_manager():
perms = UserPermission.objects.filter(user=user).first()
if not perms or not perms.stop_sales:
return Response({'message': 'Not permitted.'}, status=403)