Partners & Contracts
Connect with tour operators and travel agents via contract-based partnerships. Control what data partners can access and modify.
Overview
Partnership in Ananas GDS is formal and contract-based. An accommodation provider and a tour operator establish a contract that defines:
- The relationship type (Full Partnership, Non-Contracted Affiliate, Customer Contract)
- What the TO is allowed to do (edit facts, add their logo, select photos, add own photos)
- Stop sale behaviour (allotment type, sync enabled, deadline)
- On-request availability settings
Contracts are bilateral — both parties must accept the terms before data sharing begins. A contract with status=A (Accepted) is the only active state.
Contract Model
Contract
├── user → FK(User) — accommodation provider
├── partner → FK(User) — tour operator / travel agent
├── contract_terms → CharField(1): F=Full | N=Non-Contracted | C=Customer
├── to_edit_facts → Y/N/O — can TO edit facts?
├── to_add_its_logo → Y/N/O — can TO add their logo?
├── to_select_photos → Y/N/O — can TO select preferred photos?
├── to_add_own_photos → Y/N/O — can TO upload their own photos?
├── to_special_allotment → S/G — special or general allotment
├── to_sync_ss → BooleanField — sync stop sales to this partner?
├── ss_deadline → PositiveSmallIntegerField — advance notice in days
├── to_allow_on_request → BooleanField — allow on-request bookings?
├── notice_period → PositiveSmallIntegerField — cancellation notice days
├── comments → TextField — free-form notes
├── status → P/C/R/X/A (see lifecycle below)
├── changes_requested → BooleanField — amendment pending
└── Meta: unique_together = ('user', 'partner')
Y/N/O values
Permission fields use three-state values: Y = Yes (allowed), N = No (not allowed), O = Only with approval by e-mail.
Contract Terms
| Code | Name | Description |
|---|---|---|
F |
Full Partnership | Standard full data sharing agreement |
N |
Non-Contracted Affiliate | Affiliate with limited data access |
C |
Customer Contract | Custom commercial arrangement |
Contract Lifecycle
[Proposed] → P (Pending) → A (Accepted) ✓
→ R (Rejected)
→ C (Changed) → negotiation → A or R
A (Accepted) → X (Cancelled)
| Code | Name | Description |
|---|---|---|
P |
Pending | New contract awaiting acceptance by the other party |
C |
Changed | Amendment proposed by one party, awaiting review |
R |
Rejected | Contract rejected by the receiving party |
X |
Cancelled | Previously accepted contract cancelled |
A |
Accepted | Active contract — data sharing is live |
Contract Amendments (ContractVersions)
When changes are requested on an active contract, a ContractVersions record captures the proposed diff alongside a snapshot of the contract at the time of the request. Either party can accept or reject the amendment.
ContractVersions
├── contract → FK(Contract)
├── user → FK(User) — who requested the change
├── requested_changes → JSONField — diff of proposed changes
├── base_snapshot → JSONField — snapshot of contract at request time
├── is_reviewed → BooleanField
└── is_accepted → BooleanField
Accept or reject an amendment via:
/api/partners/contract/contractVersion/{version_id}/
🔐 Auth required
API Endpoints
/api/partners/contracts/
🔐 Auth required
List all contracts for the authenticated user.
/api/partners/my-contracts/
🔐 Auth required
List contracts (alternate endpoint).
/api/partners/contract/create/
🔐 Auth required
Create a new contract. Sets initial status to P (Pending).
/api/partners/contract/edit/{id}/
🔐 Auth required
Update contract terms. Creates a ContractVersions record if the contract is already accepted.
/api/partners/contract/delete/{id}/
🔐 Auth required
Cancel a contract. Sets status to X.
/api/partners/contract/view/{id}/
🔐 Auth required
View full contract details including permission matrix.
/api/partners/
🔐 Auth required
List all available partners on the platform.
/api/partners/my-partners/
🔐 Auth required
List connected partners with contract details.
/api/partners/partners-properties/
🔐 Auth required
List all properties visible from partner connections.
/api/partners/check-facts/{prop_id}/
🔐 Auth required
Check whether fact data is accessible for a given property under current contract terms.
Override Facts
Tour operators with accepted contracts can override specific fact fields for their own catalogue without modifying the source hotel data. Override facts are managed through the partners app:
/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 for a property.
/api/partners/override-facts/get/{prop_id}/
🔐 Auth required
Get the override record for a specific property. See the Tour Operators module for the full FactsOverride model documentation.
Contract Permission Matrix
The ContractPermissionMatrix model stores granular permission data tied to a contract. It extends the coarse Y/N/O flags on the Contract model with arbitrary JSON-defined permission flags.
ContractPermissionMatrix
├── contract → OneToOne(Contract)
├── permissions → JSONField — granular permission flags
└── updated_at → DateTimeField
Example permissions payload:
{
"facts": {"edit": "Y"},
"exports": {"allowed": true},
"photos": {"select": "Y", "add_own": "N"}
}
Sub-User Access
Sub-users require the partner_connections permission flag on their UserPermission object to access partner and contract endpoints. Managers always have access.
if not user.is_manager():
perms = UserPermission.objects.filter(user=user).first()
if not perms or not perms.partner_connections:
return Response({'message': 'Not permitted.'}, status=403)