Wego Affiliate API Integration: Developer Guide
Implement the Wego Affiliate API around OAuth client credentials, search creation, polling, offset merging, trip/fare/provider models, rate limits, handoff and commercial reconciliation.
- 2026-09-26 — Provider companion standard applied; OAuth, polling, rate-limit and commercial handoff boundaries clarified.
Wego Affiliate API uses an asynchronous token -> search session -> poll -> merge -> handoff lifecycle rather than a single synchronous search call.
OAuth token
|
v
POST /metasearch/flights/searches
|
v
search ID
|
v
GET /metasearch/flights/searches/{searchId}/results
|
v
offset-based polling
|
v
Trips + Fares + Providers
|
v
Wego handoff URLFor affiliate, distribution and provider responsibilities, see the Wego profile. This guide covers the affiliate implementation flow.
1. Authentication
Token endpoint:
POST https://affiliate-api.wego.com/apps/oauth/token
Content-Type: application/jsonRequest:
{
"client_id": "<client-id>",
"grant_type": "client_credentials",
"scope": "affiliate"
}Response:
{
"access_token": "<token>",
"token_type": "bearer",
"expires_in": 43199,
"scope": "affiliates",
"created_at": 1500000000
}API calls use:
Authorization: Bearer <access-token>Keep credentials and access tokens off the frontend.
2. Token manager
interface WegoToken {
value: string;
expiresAt: string;
}
interface WegoCredentials {
clientId: string;
secretRef?: string;
}Use shared caching and single-flight refresh behavior.
3. Flight search creation
POST https://affiliate-api.wego.com/metasearch/flights/searches
Authorization: Bearer <token>
Content-Type: application/jsonSimplified request:
{
"search": {
"adultsCount": 1,
"childrenCount": 0,
"infantsCount": 0,
"cabin": "economy",
"currencyCode": "USD",
"locale": "en",
"siteCode": "SG",
"deviceType": "DESKTOP",
"appType": "WEB_APP",
"legs": [
{
"departureCityCode": "SIN",
"arrivalCityCode": "LON",
"outboundDate": "2026-10-12"
}
]
}
}The key create-response value is the search ID.
4. Internal search model
Do not let Wego payloads become your product contract.
interface TravelSearchRequest {
vertical: "flight" | "hotel";
market: string;
locale: string;
currency: string;
flight?: {
legs: Array<{
origin: string;
destination: string;
departureDate: string;
}>;
adults: number;
children: number;
infants: number;
cabin: string;
};
hotel?: {
locationId: string;
checkIn: string;
checkOut: string;
rooms: Array<{
adults: number;
childAges: number[];
}>;
};
}5. Search-session state
interface WegoSearchSession {
internalSearchId: string;
providerSearchId: string;
vertical: "flight" | "hotel";
status: "created" | "polling" | "complete" | "failed";
requestHash: string;
offset: number;
stableCountPolls: number;
pollCount: number;
createdAt: string;
lastPolledAt?: string;
}A search ID is operational state, not a durable booking identity.
6. Poll flight results
GET https://affiliate-api.wego.com/metasearch/flights/searches/{searchId}/results
?offset=0
&locale=EN
¤cyCode=USD
Authorization: Bearer <token>The first result set can be partial.
7. Offset merging
Do not blindly append poll responses.
interface WegoFlightResultStore {
trips: Map<string, Trip>;
legs: Map<string, Leg>;
airports: Map<string, Airport>;
airlines: Map<string, Airline>;
providers: Map<string, Provider>;
fares: Map<string, Fare>;
}Merge by stable source IDs, deduplicate shared entities and rerank fares.
8. Polling strategy
Wego recommends increasing intervals:
poll 1 -> 500 ms
poll 2 -> 1 sec
poll 3 -> 2 sec
poll 4 -> 3 sec
poll 5 -> 4 secA documented stop heuristic is three consecutive polls returning the same count.
Keep that provider-specific policy inside the adapter.
9. Trip and Fare are different
interface FlightTrip {
id: string;
legIds: string[];
}
interface FlightFare {
id: string;
tripId: string;
providerId: string;
amount: number;
currency: string;
handoffUrl: string;
bookingFee?: number;
paymentFee?: number;
}One trip can have several provider/fare alternatives.
10. Shared entity dictionaries
The response references reusable entities rather than duplicating full data.
Trip
-> legIds
Leg
-> airport refs
-> airline refs
Fare
-> trip
-> provider
-> handoffResolve those references into your canonical model while preserving source IDs.
11. More fares endpoint
The primary search can return the best fare for a trip. More fares can be requested when the user shows intent:
GET https://affiliate-api.wego.com/metasearch/flights/trips/{tripId}
Authorization: Bearer <token>Avoid eagerly requesting every trip detail when the user may never open it.
12. Hotel search
Hotels use the same create/poll style and progressive rate collection.
interface HotelSearchResult {
hotelId: string;
name: string;
bestRate?: {
providerId: string;
amount: number;
currency: string;
handoffUrl: string;
};
observedAt: string;
}Hotel merge logic should also deduplicate amenities, brands, chains, districts and property types.
13. Handoff contract
Wego policy requires Wego deep links in search results. Do not reconstruct arbitrary provider URLs yourself.
interface AffiliateClick {
internalSearchId: string;
providerSearchId: string;
vertical: "flight" | "hotel";
resultId: string;
providerId: string;
handoffUrl: string;
clickedAt: string;
}Apply HTTPS and destination allowlisting.
14. Search-to-click policy
Wego expects real-user searches and monitors search-to-click behavior.
Therefore:
- avoid bot-generated search traffic,
- suppress duplicate queries,
- avoid wasteful prefetch searches,
- monitor search-to-click as a product KPI.
15. Rate limits
The documented response headers include:
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-ResetTrack:
wego_rate_limit_remaining
wego_search_429
wego_search_to_click
wego_polls_per_search16. Error taxonomy
WEGO_AUTH
WEGO_RATE_LIMIT
WEGO_BAD_REQUEST
WEGO_SEARCH_CREATE_FAILED
WEGO_SEARCH_EXPIRED
WEGO_POLL_FAILED
WEGO_PARSE
WEGO_EMPTY_RESULT
WEGO_HANDOFF_INVALID
WEGO_PROVIDER_RESULT_INVALIDDo not blindly retry 400/401. Use bounded backoff for eligible 429/5xx/network failures.
17. Cache policy
A search cache key should preserve:
vertical
+ market
+ locale
+ currency
+ dates
+ passengers/occupancy
+ cabin/locationUse short-lived cache for duplicate suppression; it is not booking truth.
18. Observability
Auth
- token success,
- token age,
- refresh failures.
Search
- create success,
- p50/p95 latency,
- first-result latency,
- poll count,
- stable-count completion,
- empty results.
Quota
- remaining quota,
- 429,
- search-to-click.
Handoff
- clicks,
- invalid links,
- landing success.
Commercial
- attributed bookings,
- commission state,
- cancellation-adjusted conversion.
19. Commercial reconciliation
search
-> Wego fare/rate
-> handoff click
-> provider booking
-> conversion/commission
-> cancellationinterface AffiliateConversion {
clickId?: string;
bookingId: string;
providerId: string;
bookingValue: number;
currency: string;
status: "pending" | "approved" | "cancelled";
}20. Test matrix
| Test | Expected |
|---|---|
| one-way | one-leg trip |
| round-trip | two legs |
| multi-city | more than two legs |
| multiple fares | same trip, different providers |
| create | search ID persisted |
| partial poll | UI renders |
| offset poll | no duplicates |
| same count x3 | polling stops |
| 429 | bounded backoff |
| token expiry | refresh |
| invalid handoff | blocked/alerted |
| hotel search | progressive rate merge |
21. Go-live checklist
- credentials server-side
- token cache/refresh implemented
- search mapper tested
- search ID lifecycle tracked
- offset merge idempotent
- polling backoff implemented
- stop rule implemented
- Trip/Fare model separated
- hotel rate model normalized
- rate-limit headers monitored
- search-to-click KPI monitored
- only valid Wego handoff URLs exposed
- redirect security applied
- client disconnect stops polling
- commercial reconciliation ownership defined
Summary
The correct model is:
user query
-> normalized request
-> Wego search
-> provider search ID
-> progressive poll
-> entity merge
-> canonical trip/hotel offers
-> Wego handoff
-> commercial reconciliationThis keeps async search orchestration, quota/commercial policy and downstream handoff in one measurable system.
Provider companion snapshot
| Area | Status |
|---|---|
| Access | Affiliate credentials / client ID required |
| Auth | OAuth client credentials / bearer token |
| Primary lifecycle | Search create → Search ID → result polling → merge → Wego deeplink |
| Pagination | Result offset/merge semantics; UI sorting/filtering/pagination can be client-side |
| Polling | Core search lifecycle; polling does not count toward search-request quota |
| Default search rate limit | Regular key: 500 searches/hour; test key: 50 searches/hour |
| Commercial quality | Search-to-click ratio should remain at least 5%; poor ratio can affect rate limits |
| Booking ownership | Downstream provider after Wego deeplink |
| Evidence | Official docs reviewed; no claim of an active affiliate-account test |
| Code | Illustrative |
Capability boundary
OAuth token → create search → Search ID → poll result offsets → merge Trips/Fares/Providers → Wego redirect/deeplink → downstream provider.
A search result is not a booking confirmation.
Rate-limit and polling contract
Wego public docs list 500 search requests/hour for a regular key and 50/hour for a test key. Polling does not count toward the search-request quota. Still avoid tight loops; use progress-aware backoff and a maximum duration.
Idempotency and ordering
Reprocessing the same search ID/offset must not duplicate trips or fares. Offsets should progress monotonically and older snapshots must not overwrite newer provider/fare state.
Commercial handoff and observability
Production affiliate traffic should represent real user searches and use Wego deeplinks. Track search-to-click ratio, quota/429 signals, poll count, time to first result, time to complete, empty results and deeplink success together.
Planning a similar integration?
We can review requirements, feed/API design and the production approach with you.