Developer Docs

Everything you need to ship faster

Complete API reference, integration guides, and code samples for the MAPPIN partner gateway.

Introduction

Welcome to the MAPPIN API — the unified partner API gateway for global travel data. Aggregate countries, cities, and hotels from 6+ travel providers through one intelligent mapping layer. Built for speed, designed for scale.

New here? Jump to the Quickstart to make your first API call in under 5 minutes.

Quickstart

Get up and running with MAPPIN in three quick steps.

1. Create an account

Head to the registration page and sign up as a partner. It takes under a minute — no credit card required.

2. Get your API key

After signing in, navigate to API Keys in your partner dashboard. Copy your key — you'll need it for every API request.

Keep it secret. Treat your API key like a password. Never commit it to a public repo or expose it in client-side code.

3. Make your first request

Try fetching the list of countries:

bash
curl https://mappin.rpconnect.travel/api/countries/ \
  -H "X-API-Key: your_api_key_here"

You should get back a JSON response with all supported countries. That's it — you're integrated. 🎉


Authentication

All API requests must include your API key in the X-API-Key header. Requests without a valid key will be rejected with 401 Unauthorized.

http
GET /api/hotels/ HTTP/1.1
Host: mappin.rpconnect.travel
X-API-Key: your_api_key_here

cURL

bash
curl https://mappin.rpconnect.travel/api/hotels/ \
  -H "X-API-Key: your_api_key_here"

Python

python
import requests

headers = {"X-API-Key": "your_api_key_here"}
response = requests.get(
    "https://mappin.rpconnect.travel/api/hotels/",
    headers=headers
)
print(response.json())

JavaScript

javascript
const response = await fetch(
  "https://mappin.rpconnect.travel/api/hotels/",
  { headers: { "X-API-Key": "your_api_key_here" } }
);
const data = await response.json();
console.log(data);

How It Works

MAPPIN sits between your application and multiple travel data providers — including HotelBeds, Rezlive, Travellanda and Dida. Instead of integrating each provider separately, you talk to one unified API and we handle:

  • Provider aggregation — one request fans out to every provider mapped to that record
  • Data normalization — a consistent JSON schema no matter which provider the data came from
  • Canonical master records — duplicate cities and hotels are merged into one stable ID you can store forever
  • Confidence scores — every provider mapping carries a 0–1 score so you know how sure the match is
  • Content merging — hotel details combine the best description, images and amenities across providers
  • Fresh lists, cached details — list endpoints always read live; hotel details are cached for 15 minutes per partner

Provider slugs are lowercase — hotelbeds, rezlive, travellanda, dida. Use these exact values in ?provider= filters and provider-map calls. A wrong slug returns the full valid list.

Pagination

Every list endpoint returns the same envelope. Default page size is 50 — override with ?limit= (max 500) and walk pages with ?page=.

ParameterTypeDefaultNotes
pageinteger1Page number, starting at 1
limitinteger50Results per page, max 500
json
{
  "pagination": {
    "total_results": 195,
    "total_pages": 4,
    "current_page": 1,
    "page_size": 50,
    "next": "https://mappin.rpconnect.travel/api/countries/?page=2",
    "previous": null
  },
  "results": [ ... ]
}

Follow pagination.next — it's a ready-made URL for the next page. Stop when it's null.

Rate Limits & Quotas

MAPPIN enforces three types of limits to keep the platform fast for everyone:

Limit TypeDescriptionResponse When Exceeded
Daily QuotaMax requests per day (per plan)429 Daily quota exceeded
Monthly QuotaMax requests per calendar month429 Monthly quota exceeded
Burst LimitMax concurrent requests per second429 Burst limit exceeded
IP Abuse Guard>10 requests/sec from single IP → 5-min block429 IP blocked

Pro tip: Check your current usage anytime from the Analytics tab in your partner dashboard.

Error Handling

MAPPIN uses standard HTTP status codes. Errors always return a JSON body with an error field.

json
{
  "error": "Daily API quota exceeded"
}
StatusMeaningWhat to do
200SuccessNothing — you're good
400Bad requestCheck your query parameters
401Missing/invalid API keyVerify your X-API-Key header
403Partner disabledContact support
404Resource not foundCheck the ID in your URL
429Rate limit exceededWait & retry, or upgrade plan
500Server errorRetry with exponential backoff

Real examples

Missing parameter (400):

json
{
  "error": "Parameter 'city_id' or 'city' is required. Use 'city' to search for cities, 'city_id' to fetch hotels."
}

Unknown record (404):

json
{
  "error": "Hotel not found"
}

One quirk: the country-detail 404 uniquely returns {"success": false, "error": "..."}. Every other endpoint returns a bare {"error": ...}. Handle both shapes.


Countries

Access the master list of countries, each with its provider mappings and live city count.

GET /api/countries/

List countries. Results are paginated (see Pagination) and sorted by name.

ParameterTypeRequiredDescription
searchstringNoMatch against name, ISO code, or numeric ID — ?search=india, ?search=IN, ?search=247
pageintegerNoPage number (default 1)
limitintegerNoPage size, max 500 (default 50)
bash
curl "https://mappin.rpconnect.travel/api/countries/?search=united&limit=2" \
  -H "X-API-Key: your_api_key_here"
json
{
  "pagination": {
    "total_results": 2,
    "total_pages": 1,
    "current_page": 1,
    "page_size": 2,
    "next": null,
    "previous": null
  },
  "results": [
    {
      "id": 1,
      "name": "United Arab Emirates",
      "code": "AE",
      "status": "Active",
      "city_count": 42,
      "provider_count": 2,
      "providers": [
        {
          "provider": "hotelbeds",
          "provider_country_id": "AE",
          "provider_country_name": "United Arab Emirates",
          "provider_country_code": "AE",
          "confidence": 1.0
        },
        {
          "provider": "rezlive",
          "provider_country_id": "AE",
          "provider_country_name": "UAE",
          "provider_country_code": "AE",
          "confidence": 0.98
        }
      ]
    }
  ]
}

GET /api/countries/<identifier>/

Country detail. The identifier is flexible — use whichever you have:

  • Numeric ID — /api/countries/1/
  • ISO code (case-insensitive) — /api/countries/us/
  • Full name — /api/countries/Japan/ (URL-encode spaces)
bash
curl https://mappin.rpconnect.travel/api/countries/GB/ \
  -H "X-API-Key: your_api_key_here"
json
{
  "id": 247,
  "name": "United Kingdom",
  "code": "GB",
  "status": "Active",
  "city_count": 1284,
  "total_providers": 3,
  "providers": [
    {
      "provider": "hotelbeds",
      "provider_country_id": "GB",
      "provider_country_name": "United Kingdom",
      "provider_country_code": "GB",
      "confidence": 1.0
    }
  ]
}

Unknown identifier returns 404 with {"success": false, "error": "Country with ID or code 'XX' not found."} — note the extra success flag, unique to this endpoint.

Cities

Search the master city list and fetch city details with provider mappings and live hotel counts.

GET /api/cities/

List cities. Results are paginated and sorted by name.

ParameterTypeRequiredDescription
searchstringNoMatch against city name — or numeric ID (?search=london, ?search=123)
countrystringNoFilter by country code, name, or numeric ID (?country=GB, ?country=247)
country_idintegerNoSame as numeric ?country= — filter by country ID
pageintegerNoPage number (default 1)
limitintegerNoPage size, max 500 (default 50)
bash
curl "https://mappin.rpconnect.travel/api/cities/?country=AE&limit=2" \
  -H "X-API-Key: your_api_key_here"
json
{
  "pagination": {
    "total_results": 42,
    "total_pages": 21,
    "current_page": 1,
    "page_size": 2,
    "next": "https://mappin.rpconnect.travel/api/cities/?country=AE&limit=2&page=2",
    "previous": null
  },
  "results": [
    {
      "id": 2041,
      "name": "Dubai",
      "country": { "id": 1, "name": "United Arab Emirates", "code": "AE" },
      "status": "Active",
      "hotel_count": 1284,
      "provider_count": 3,
      "providers": [
        {
          "provider": "hotelbeds",
          "provider_city_id": "DXB",
          "provider_city_name": "Dubai",
          "provider_country_id": "AE",
          "confidence": 1.0
        }
      ]
    }
  ]
}

GET /api/cities/<city_id>/

City detail by numeric master ID only (unlike countries, codes and names are not accepted here).

bash
curl https://mappin.rpconnect.travel/api/cities/2041/ \
  -H "X-API-Key: your_api_key_here"
json
{
  "id": 2041,
  "name": "Dubai",
  "country": { "id": 1, "name": "United Arab Emirates", "code": "AE" },
  "status": "Active",
  "hotel_count": 1284,
  "total_providers": 3,
  "providers": [
    {
      "provider": "hotelbeds",
      "provider_city_id": "DXB",
      "provider_city_name": "Dubai",
      "provider_country_id": "AE",
      "confidence": 1.0
    }
  ]
}

Unknown ID returns 404 with {"error": "City with ID '999' not found"}.

City Master

One dual-purpose endpoint that takes you from a city name to its hotels in two calls — no IDs to look up first.

The fastest name → hotels path: search ?city=Dubai to get a city_id, then fetch ?city_id=2041 for its hotels. The search response even includes this hint.

GET /api/city/?city=<name>

Search cities by name. Tries an exact match first, then falls back to partial matching.

ParameterTypeRequiredDescription
citystringYes*City name (?city=London). *Required unless city_id is given
countrystringNoNarrow by country code (?city=Paris&country=FR). If it matches nothing, it's ignored and unfiltered results return
page / limitintegerNoStandard pagination
bash
curl "https://mappin.rpconnect.travel/api/city/?city=Dubai" \
  -H "X-API-Key: your_api_key_here"
json
{
  "pagination": {
    "total_results": 1,
    "total_pages": 1,
    "current_page": 1,
    "page_size": 50,
    "next": null,
    "previous": null
  },
  "results": [
    {
      "city_id": 2041,
      "city_name": "Dubai",
      "country_name": "United Arab Emirates",
      "country_code": "AE"
    }
  ],
  "hint": "Use city_id from results to fetch hotels: /api/city/?city_id="
}

GET /api/city/?city_id=<id>

List active hotels in a city, each with its provider mappings — plus a metadata block echoing the city.

ParameterTypeRequiredDescription
city_idintegerYes*Master city ID. *Required unless city is given
providerstringNoOnly hotels mapped to this provider slug (?provider=hotelbeds)
page / limitintegerNoStandard pagination
bash
curl "https://mappin.rpconnect.travel/api/city/?city_id=2041&limit=1" \
  -H "X-API-Key: your_api_key_here"
json
{
  "pagination": {
    "total_results": 1284,
    "total_pages": 1284,
    "current_page": 1,
    "page_size": 1,
    "next": "https://mappin.rpconnect.travel/api/city/?city_id=2041&limit=1&page=2",
    "previous": null
  },
  "results": [
    {
      "master_id": 12847,
      "name": "Burj Al Arab",
      "coordinates": { "lat": 25.1412, "lng": 55.1853 },
      "mappings": [
        {
          "provider": "hotelbeds",
          "provider_code": "12847",
          "provider_hotel_id": "12847",
          "provider_hotel_name": "Burj Al Arab Jumeirah",
          "confidence": 0.99
        }
      ]
    }
  ],
  "metadata": {
    "city_id": 2041,
    "city_name": "Dubai",
    "country_name": "United Arab Emirates",
    "country_code": "AE",
    "selected_provider": null
  }
}

Calling with neither parameter returns 400; an unknown name or ID returns 404.

Hotels

The core of MAPPIN — search the master hotel list, then drill into rich merged details per property.

GET /api/hotels/

List hotels. Results are paginated and sorted by name.

ParameterTypeRequiredDescription
searchstringNoMatch against hotel name — or numeric master ID (?search=hilton, ?search=12847)
city_idintegerNoMaster city ID. Must be numeric — anything else is ignored
country / country_code / country_idstringNoThree aliases, same filter: code, name, or numeric ID (?country=GB, ?country_id=247)
providerstringNoOnly hotels mapped to this provider slug
page / limitintegerNoStandard pagination
bash
curl "https://mappin.rpconnect.travel/api/hotels/?city_id=2041&limit=1" \
  -H "X-API-Key: your_api_key_here"
json
{
  "pagination": {
    "total_results": 1284,
    "total_pages": 1284,
    "current_page": 1,
    "page_size": 1,
    "next": "https://mappin.rpconnect.travel/api/hotels/?city_id=2041&limit=1&page=2",
    "previous": null
  },
  "results": [
    {
      "id": 12847,
      "name": "Burj Al Arab",
      "city": { "id": 2041, "name": "Dubai" },
      "country": { "id": 1, "name": "United Arab Emirates", "code": "AE" },
      "coordinates": { "lat": 25.1412, "lng": 55.1853 },
      "status": "Active",
      "provider_count": 3,
      "providers": [
        {
          "provider": "hotelbeds",
          "provider_code": "12847",
          "provider_hotel_id": "12847",
          "provider_hotel_name": "Burj Al Arab Jumeirah",
          "confidence": 0.99
        }
      ]
    }
  ]
}

GET /api/hotels/<hotel_id>/

Full detail for one hotel by numeric master ID — merged description, address, rating, images and amenities, plus every provider mapping. Arrays below are truncated for brevity.

bash
curl https://mappin.rpconnect.travel/api/hotels/12847/ \
  -H "X-API-Key: your_api_key_here"
json
{
  "id": 12847,
  "master_id": 12847,
  "name": "Burj Al Arab",
  "status": "Active",
  "city": { "id": 2041, "name": "Dubai" },
  "country": { "id": 1, "name": "United Arab Emirates", "code": "AE" },
  "coordinates": { "lat": 25.1412, "lng": 55.1853 },
  "total_providers": 3,
  "providers": [
    {
      "provider": "hotelbeds",
      "provider_code": "12847",
      "provider_hotel_id": "12847",
      "provider_hotel_name": "Burj Al Arab Jumeirah",
      "confidence": 0.99
    }
  ],
  "description": "Iconic sail-shaped luxury hotel on its own island off the Dubai coast...",
  "address": "Jumeirah St, Umm Suqeim 3, Dubai",
  "phone": "+97143017777",
  "star_rating": 5,
  "images": [
    "https://photos.hotelbeds.com/giata/00/001234/001234a_hb_a_001.jpg"
  ],
  "amenities": ["Free WiFi", "Outdoor pool", "Spa", "Airport shuttle"],
  "source_provider": "hotelbeds",
  "providers_available": ["hotelbeds", "rezlive", "travellanda"],
  "providers_used": ["hotelbeds", "rezlive"]
}

How content is picked: the richest provider record wins (description length, images ×2, amenities ×1.5, plus rating and address) and becomes source_provider; missing fields are then filled in from the others (providers_used). provider_code is the supplier-side code — pass it back to that provider's own booking APIs.

Cached 15 minutes per partner. Brand-new mappings can take up to 15 minutes to appear in this endpoint; list endpoints always read live.

Unknown ID returns 404 with {"error": "Hotel not found"}.

Provider Mapping

Reverse lookup: hand over any supplier's hotel ID and get back the canonical master record — plus every other provider's ID for the same hotel, so you can translate IDs across suppliers (e.g. hotelbeds → dida) without extra calls. Hotels only.

GET /api/provider-map/

Single lookup via query params.

ParameterTypeRequiredDescription
providerstringYesLowercase provider slug (hotelbeds, rezlive, …)
hotel_idstringYesThat provider's hotel ID or code
bash
curl "https://mappin.rpconnect.travel/api/provider-map/?provider=hotelbeds&hotel_id=12847" \
  -H "X-API-Key: your_api_key_here"
json
{
  "mapped": true,
  "query": { "provider": "hotelbeds", "provider_hotel_id": "12847" },
  "master": {
    "master_id": 12847,
    "name": "Burj Al Arab",
    "city": { "id": 2041, "name": "Dubai" },
    "country": { "id": 1, "name": "United Arab Emirates", "code": "AE" },
    "coordinates": { "lat": 25.1412, "lng": 55.1853 },
    "status": "Active"
  },
  "match": {
    "provider": "hotelbeds",
    "provider_code": "12847",
    "provider_hotel_id": "12847",
    "provider_hotel_name": "Burj Al Arab Jumeirah",
    "confidence": 0.99,
    "lookup": "exact"
  },
  "siblings": [
    {
      "provider": "dida",
      "provider_code": "DUB12847",
      "provider_hotel_id": "DUB12847",
      "provider_hotel_name": "Burj Al Arab",
      "confidence": 0.95
    }
  ],
  "total_providers": 2,
  "hint": "Full details: GET /api/hotels/12847/"
}

POST /api/provider-map/

Same lookup as JSON — single or batch. Batch accepts up to 100 IDs and uses exact matching only (no code fallbacks, for speed).

bash
curl -X POST https://mappin.rpconnect.travel/api/provider-map/ \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"provider": "hotelbeds", "hotel_ids": ["12847", "99999"]}' 
json
{
  "provider": "hotelbeds",
  "total": 2,
  "found": 1,
  "not_found": 1,
  "results": [
    {
      "mapped": true,
      "query": { "provider": "hotelbeds", "provider_hotel_id": "12847" },
      "master": { "master_id": 12847, "name": "Burj Al Arab" },
      "match": { "provider": "hotelbeds", "lookup": "exact" },
      "siblings": [ ... ],
      "total_providers": 2
    },
    {
      "mapped": false,
      "query": { "provider": "hotelbeds", "provider_hotel_id": "99999" }
    }
  ]
}

Smart matching: single lookups try an exact match first, then provider-specific code fallbacks (hotelbeds code → id, dida id ↔ hotel_id). The lookup field tells you which one hit.

No match still returns HTTP 200 — check the mapped flag, not the status code. Real errors: unknown provider (400 + the valid_providers list), empty hotel_ids (400), over 100 IDs (400).


API Playground

Test any endpoint interactively without writing a single line of code. Log in to your dashboard and click API Playground in the sidebar.

Open Playground

Get Help

Stuck? We're here to help.

Our team typically responds within 2 hours during business hours (IST).

Was this documentation helpful?