Tour Operators
How tour operators access partner hotel data, configure property mappings, and apply override facts for their own catalogue.
Overview
Tour operators (TOs) consume hotel data from their accommodation partners. The TO module provides:
- A view of all properties from connected partners
- Hotel and room mapping — mapping Ananas property and room names to the TO's internal codes
- Override facts — modifying specific fact fields for the TO's catalogue without changing the source data from the hotel
- API access for automated data consumption
Before any data is accessible, an accepted contract (status=A) must exist between the TO and the accommodation provider. See the Partners & Contracts module for contract setup.
Accessing Partner Data
TOs access partner data through two mechanisms:
| Method | How it works | Best for |
|---|---|---|
| Dashboard | Visual review of partner properties via the Ananas GDS web app | Manual review, one-off checks |
| API | Programmatic access via API tokens issued by the accommodation provider | Automated catalogue ingestion, integrations |
For API access, the accommodation provider issues an API token to the TO. The token is passed as a URL path segment — not as an Authorization header.
Token-based access
The token endpoints (/api/v1/facts/{token}/, /api/v1/photos/{token}/, /api/v1/stop-sale/{token}/) require no Authorization header. The token in the URL path identifies both the partner relationship and the scope of data returned.
Hotel Mapping (HotelMapping)
A HotelMapping record lets a TO assign their own internal codes to a partner hotel. This is essential for automated ingestion where the TO's back-office system uses its own identifiers.
HotelMapping
├── user → FK(User) — the TO user
├── hotel → FK(Property) — the partner's property
├── override_code → CharField(20) — TO's internal hotel code
├── local_id → CharField(50) — TO's local identifier
├── external_id → CharField(50) — external system ID (GDS, OTA, PMS)
├── supplying_name → CharField(50) — name used in the TO's system
├── event_free → CharField(20) — code for Free Sale events
├── event_open → CharField(20) — code for Open Sale events
├── event_stop → CharField(20) — code for Stop Sale events
├── event_request → CharField(20) — code for On Request events
└── event_block → CharField(20) — code for Blocked events
The event_* fields translate Ananas event codes (0–4) into the TO's own stop sale codes for their internal systems. For example, if the TO's PMS uses CLS to represent a closed room, set event_stop = "CLS".
| Ananas Code | Ananas Name | HotelMapping field |
|---|---|---|
0 | Free Sale | event_free |
1 | Open Sale | event_open |
2 | Stop Sale | event_stop |
3 | On Request | event_request |
4 | Blocked | event_block |
Room Mapping (RoomMapping)
Each room within a partner hotel can also carry a TO-specific mapping. RoomMapping extends HotelMapping with room-level overrides:
RoomMapping
├── room → FK(Room, nullable)
├── user → FK(User) — the TO user
├── hotel → FK(HotelMapping)
├── override_code → CharField(20) — TO's room code
├── name → CharField(500) — override display name
├── original_name → BooleanField — use the property's original room name?
├── event_free / event_open / event_stop / event_request / event_block
│ → CharField(20) — room-level event codes
├── linked → BooleanField — is this mapping active?
├── link_date → DateTimeField
└── unlink_date → DateTimeField
The get_event_code(event_code) instance method on RoomMapping translates an Ananas integer event code to the TO's own string code. If no room-level code is set, the method falls back to the parent HotelMapping value.
Linked vs. unlinked rooms
A RoomMapping with linked=False is inactive — it will not appear in API exports for that TO. Use link_date and unlink_date to audit when a room was connected or disconnected.
Override Facts (FactsOverride)
Tour operators can override specific fact fields for their own catalogue without modifying the source data from the hotel. Overrides are stored per TO user and property combination. When the TO fetches fact data via the API, override fields are merged on top of the hotel's base fact data.
FactsOverride
├── user → FK(User) — the TO
├── property → FK(Property) — the hotel
├── add_operator_logo → BooleanField — show TO logo on this property's facts?
├── enable_stopsale_api → BooleanField — expose stop sale via API?
├── set_stopsale_closed_request → BooleanField — treat stop sales as on-request?
├── location_environment → TextField — custom location description
├── around_hotel → TextField — custom "around the hotel" text
├── beach_characteristics → TextField
├── beach_information → TextField
├── distance_to_beach → DecimalField
├── distance_to_beach_unit → CharField
├── distance_to_airport → DecimalField
├── airport_distance_type → CharField
├── outdoor_characteristics → TextField
└── outdoor_equipment → TextField
Only fields explicitly set in a FactsOverride record replace the hotel's values. Fields left blank fall through to the source data. This means a hotel's fact sheet remains canonical — the TO overlay is applied at query time.
TO-Specific API Endpoints
TOs also use the standard partner contract endpoints documented in the Partners module. The following endpoints are additionally available:
Override facts management:
/api/partners/override-facts/
🔐 Auth required
List all override facts records for the authenticated TO.
/api/partners/override-facts/create/
🔐 Auth required
Create or update an override record for a property.
/api/partners/override-facts/get/{prop_id}/
🔐 Auth required
Get the override record for a specific property.
/api/partners/partners-properties/
🔐 Auth required
List all properties visible from the TO's partner connections.
/api/partners/check-facts/{prop_id}/
🔐 Auth required
Check fact access status for a given property under the current contract.
Data consumption (token-based, no auth header required):
/api/v1/facts/{token}/
Retrieve the full fact sheet for the property associated with this token. Override facts are merged into the response.
/api/v1/photos/{token}/
Retrieve the photo gallery for the property associated with this token.
/api/v1/stop-sale/{token}/
Retrieve the stop sale calendar for the property associated with this token. Room event codes are translated using RoomMapping.get_event_code() where a mapping exists.
TO Sub-User Access
TO sub-users use a different set of permission flags from accommodation sub-users. The flags relevant to TO operations are:
| Flag | Description |
|---|---|
edit_products |
Create and edit hotel and accommodation listings in the TO's catalogue |
view_content |
View partner fact sheets, room info, media, and the stop sale calendar |
accounting |
View invoices issued to this TO |
Different permission model
TO sub-users are governed by the same UserPermission model as accommodation sub-users, but the meaningful flags differ. Accommodation-side flags such as stop_sales, facts, and photos apply to the property manager's side; edit_products, view_content, and accounting apply to the TO side.
Property Visibility
The properties a TO can see depend on their active contract connections. Only properties belonging to partners with status=A (Accepted) contracts are returned by any TO-facing endpoint.
For TO sub-users with SubUserRegionAccess records, visibility is further filtered by country or region. A sub-user without any SubUserRegionAccess records sees all properties from accepted partners; one with records sees only the intersection of their region grants and accepted-contract properties.