Developer Documentation

Integrate global visa requirements and passport mobility data into your application.

What's new

v1.7.0 — Structured currency & fee parsing. New currencies + exchange_rates tables (USD-base, lazy-refreshed from exchangerate-api.com on 24h staleness). All fee strings parsed into fee_amount, fee_amount_max, fee_currency columns on both visa_info and visa_info_types (98%+ extraction rate). Responses now include a fee.structured object with numeric amounts, USD equivalent, range support, and conversion to any currency via ?currency=XXX. New /currencies.php endpoint lists supported codes + current rates. Requires migration_currency.sql + backfill_currency.php.

v1.6.0 — Regional & grouping metadata. New countries + country_groups tables with 249 countries (continent + UN M.49 subregion) and 20 travel-relevant blocs (Schengen, GCC, ASEAN, SAARC, EU, NATO, BRICS+, US VWP, ETIAS, etc.). /visa-details now embeds region + groups on both passport and destination. /country-profile, /countries-list, and /visiting-countries support new continent, subregion, and group filter params. New /groups.php endpoint lists all blocs with members. Requires migration_regions_groups.sql.

v1.5.2 — Structured photo specifications: /visa-details now returns a parsed passport_requirements.photo object with width_mm, height_mm, background_color, biometric, digital_accepted, max_age_months, country_spec, and notes. Free-text photo_specifications remains for backward compat. Optional SQL migration available to persist the parsed fields as queryable columns.

v1.5.1 — Optional visa_types filter parameter on /visa-details: narrow the visa_types[] array to specific categories (e.g. ?visa_types=Business,Work). Response meta now includes visa_types_available listing every category present for the destination, so clients can self-discover what to request.

v1.5.0 — Structured visa types: each /visa-details response now includes a visa_types[] array exposing Tourist, Business, Transit, Student, Work, and other categories with their own fees, validity, application workflow, and approval signals. New endpoint /passport-compare.php for side-by-side comparison of 2-10 passports.

v1.4.0 — New endpoint /passport-strength.php: aggregate mobility metrics, rank vs other passports, fee statistics, and lists of visa-free / visa-on-arrival destinations.

v1.3.0 — 15 structured fields on /visa-details (entry type, application center, appointment, urgent processing, interview, approval rate, extension, overstay penalty, transit visa, data confidence, verification date). Migration: validity_max_staystay.*, timestampsmeta.*.


GET/country-profile.php

Country Profile UPDATED v1.6.0

Returns a summary of visa requirements for all visiting countries from the perspective of the given passport. v1.6.0 adds region/group filtering and embeds region + groups on passport and each destination.

Parameters

ParamTypeDescription
passport_country_iso2StringRequired. 2-letter ISO 3166-1 alpha-2 (e.g. BD).
continent NEW v1.6.0StringOptional. Filter destinations by continent: AfricaAmericasAsiaEuropeOceaniaAntarctica
subregion NEW v1.6.0StringOptional. Filter by UN M.49 subregion. E.g. "Southern Asia", "Western Europe", "Eastern Africa". Get the full list via /countries-list.php?type=subregions.
group NEW v1.6.0StringOptional. Filter by country-group code(s), comma-separated. E.g. schengen, gcc,asean, us_vwp. Run /groups.php to discover valid codes.
currency NEW v1.7.0StringOptional. ISO 4217 code to convert all destination fees to. E.g. ?currency=GBP.

Example Requests

# All destinations
GET /country-profile.php?passport_country_iso2=BD

# Only European destinations
GET /country-profile.php?passport_country_iso2=BD&continent=Europe

# Only Schengen destinations (single visa enters 29 states)
GET /country-profile.php?passport_country_iso2=BD&group=schengen

# Multiple groups — destinations in GCC OR ASEAN
GET /country-profile.php?passport_country_iso2=BD&group=gcc,asean
GET/visa-details.php

Visa Details UPDATED v1.7.0

Returns the complete visa profile for a passport-destination pair. Includes embassy contacts, structured requirement flags, application workflow, fees, stay rules, data quality signals, a visa_types[] array exposing each visa category, and (as of v1.5.2) a structured passport_requirements.photo object with parsed dimensions, background, biometric/digital flags, and country-specific notes.

Parameters

ParamTypeDescription
passport_country_iso2StringRequired. Origin passport (e.g., BD).
visiting_country_iso2StringRequired. Destination country (e.g., AE).
visa_types v1.5.1 String Optional. Comma-separated list of visa categories to return in the visa_types[] array. Case-insensitive. Filters only the visa_types[] array — legacy top-level blocks (overview, application, fees, stay) always reflect the Tourist primary record for backward compatibility.

Allowed values: TouristBusinessTransitStudentWorkFamilyMedicalConferenceJournalistDiplomaticCreweVisaVoAVisa-FreeOther
currency NEW v1.7.0StringOptional. ISO 4217 currency code (e.g. EUR, GBP, JPY, USD). When supplied, all fees include amount_in_requested with the converted amount. See /currencies.php for valid codes.

Example Requests

# All visa types (default)
GET /visa-details.php?passport_country_iso2=BD&visiting_country_iso2=AE

# Filter to a single visa type
GET /visa-details.php?passport_country_iso2=BD&visiting_country_iso2=US&visa_types=Business

# Filter to multiple
GET /visa-details.php?passport_country_iso2=BD&visiting_country_iso2=US&visa_types=Business,Student,Work

Self-discovery via response meta

The response meta always includes visa_types_available — an alphabetical list of every visa category present for the destination. Use this to populate filter chips/dropdowns without trial and error.

When the visa_types filter is applied, meta.visa_types_filter echoes the normalized values that were actually used (after deduplication and canonical casing).

Response shape (full)
{
  "success": true,
  "meta": {
    "generated_at": "2026-05-16T01:55:00+00:00",
    "visa_type_count": 1,
    "visa_types_available": ["Business", "Tourist", "Transit"],   // NEW v1.5.1 — always present
    "visa_types_filter": ["Business"]                             // NEW v1.5.1 — only when filter applied
  },
  "data": {
    "id": 99,
    "passport": { "country": "Bangladesh", "iso2": "BD", "currency_code": "BDT" },
    "destination": { "country": "United Arab Emirates", "iso2": "AE" },

    "overview": {
      "visa_fees_summary": "...",
      "visa_types": "...",                       // free-text legacy summary
      "govt_portal_url": "https://...",
      "entry_type": "Single",
      "approval_rate_estimate": "Medium",
      "transit_visa_required": "Conditional"
    },

    "embassy": {
      "address": "...", "map_url": "https://...",
      "phone": "+880 2 ...", "email": "..."
    },

    "passport_requirements": {
      "passport_validity": "6+ months from entry",
      "photo_specifications": "35x45mm, white bg",                // raw, kept for compat
      "photo": {                                                  // NEW v1.5.2 — structured
        "raw": "35x45mm, white bg",
        "required": "Yes",
        "width_mm": 35, "height_mm": 45,
        "alt_dimensions": null,
        "background_color": "White",
        "biometric": false,
        "digital_accepted": false,
        "digital_only": false,
        "max_age_months": null,
        "country_spec": null
      },
      "required_documents": "..."
    },
    "requirements": { ... },

    "application": {                             // ← Primary (Tourist) cache for compat
      "method": "Embassy via VFS Dhaka",
      "center_type": "VFS Global",
      "processing_time": "15 working days",
      "appointment": { "required": "Yes", "booking_url": "..." },
      "interview": { "required": "Conditional" },
      "urgent_processing": { "available": "No", "details": null }
    },

    "fees": { ... },                             // ← Primary (Tourist) cache
    "stay": { ... },                             // ← Primary (Tourist) cache
    "rejection_reasons": "...",

    "visa_types": [                              // NEW v1.5 — structured array
      {
        "visa_type": "Tourist",
        "visa_subtype": null,
        "is_primary": true,
        "entry_type": "Single",
        "validity": null,
        "max_stay": "Validity: 60 days from issue. Max Stay: 30 days...",
        "extension_possible": "Conditional",
        "fee": {
          "local_currency": "AED 350",
          "usd": "USD 95",
          "passport_currency": "BDT 11,615",
          "service_fee_note": "VFS service fee: USD 25-40 on top of visa fee"
        },
        "application": {
          "method": "Embassy via VFS Dhaka",
          "center_type": "VFS Global",
          "processing_time": "15 working days",
          "appointment": { "required": "Yes", "booking_url": "..." },
          "interview": { "required": "Conditional" },
          "urgent_processing": { "available": "No", "details": null }
        },
        "minimum_bank_balance_usd": "USD 100/day",
        "approval_rate_estimate": "Medium",
        "summary": "Tourist visa for leisure visits...",
        "notes": null,
        "meta": { "data_confidence": "High", "last_verified_at": "2026-05-15", ... }
      }
      /* additional types (Business, Transit, Student, etc.) appended here */
    ],

    "meta": {
      "data_confidence": "High",
      "last_verified_at": "2026-05-15",
      "created_at": "2026-05-13 02:57:48",
      "updated_at": "2026-05-15 00:18:11"
    }
  }
}

visa_types[] field reference NEW v1.5.0

Each element in the array represents one visa category for the passport-destination pair. The element marked is_primary=true (usually Tourist) duplicates the top-level application / fees / stay blocks for backward compatibility.

FieldTypeDescription
visa_type enum TouristBusinessTransitStudentWorkFamilyMedicalConferenceJournalistDiplomaticCreweVisaVoAVisa-FreeOther
visa_subtype string nullable Specific category, e.g., "Schengen Type C", "B1/B2", "ETA", "90-day Multi-Entry".
is_primary boolean True for the most-common/default visa type per pair (usually Tourist). The legacy top-level application / fees / stay blocks reflect the primary type.
fee.local_currency / fee.usd / fee.passport_currency string Type-specific fees. Different visa types (Tourist vs Business) often have very different fees.
application.* object Type-specific application workflow (method, processing time, appointment, interview, urgent processing).
summary / notes string Type-specific summary and gotchas (e.g., sponsor letter for Business, course acceptance for Student).

passport_requirements.photo field reference NEW v1.5.2

The photo object is parsed from the free-text photo_specifications string. The raw value is preserved under passport_requirements.photo_specifications for backward compatibility; the parsed object is the recommended way to consume photo requirements going forward.

FieldTypeDescription
rawstringThe original free-text value (same as photo_specifications).
requiredenumYesNoNo for visa-free, on-arrival, citizen, EASE, etc.
width_mm / height_mmfloat nullablePhoto dimensions normalized to millimeters. Source values in cm or inches are auto-converted (e.g., 2x2 inch → 50.8 × 50.8 mm, 4x5cm → 40 × 50 mm). May be null for underspecified entries like "Color, white bg".
alt_dimensionsstring nullableAlternative acceptable dimensions when the source lists two (e.g., "30x40mm or 50x50mm, white bg""50x50mm").
background_colorenumWhiteOff-whiteLight blue or null.
biometricbooleantrue when the source says "biometric" — typically Schengen, UK, etc.
digital_acceptedbooleantrue when digital uploads (eVisa/ETA) are accepted.
digital_onlybooleantrue when only digital is supported (e.g. "Digital (for ETA)", standalone "Digital"). Implies digital_accepted = true.
max_age_monthsint nullablePhoto must be newer than N months. Parsed from "last 6 months" / "not older than 6 months".
country_specstring nullableCountry/format spec label captured from parentheticals: "US spec", "Japan spec", "Indian spec", "ICAO standard", "Chinese spec", etc.
notesstring[]Conditional notes — "Hijab required for women", "No glasses", "ICAO standard", "Natural color", "Recent photo required", etc. Omitted from response if empty.

Parsing notes

"Passport size" / "Passport-style" without explicit dimensions defaults to 35 × 45 mm (the BD/global standard) with a corresponding note added.

The parser is forgiving — even when only background or color info is available, the structured object is still returned with the fields that could be extracted. Dimensions remain null in those cases.

Original free-text remains under passport_requirements.photo_specifications. The two fields will always be consistent — photo.raw equals photo_specifications.

Field reference — added in v1.3.0

FieldTypeDescription
overview.entry_typeenumSingleDoubleMultipleVisa-FreeVoAN/A
overview.approval_rate_estimateenumHighMediumLowUnknown
overview.transit_visa_requiredenumYesNoConditionalN/A
application.center_typeenumEmbassyVFS GlobalBLS InternationalTLScontactDirect OnlineVoAVisa-FreeMixedOther
application.appointment.requiredenumYesNoConditionalN/A
application.interview.requiredenumYesNoConditionalN/A
application.urgent_processing.availableenumYesNoN/A
fees.minimum_bank_balance_usdstring nullableFunds proof requirement, normalized to USD.
fees.service_fee_notestring nullableAdditional service-center fee beyond visa fee (typ. USD 20-40 for VFS/BLS/TLS).
stay.extension_possibleenumYesNoConditionalN/A
stay.overstay_penaltytext nullablePenalty for overstaying (per-day fines, bans, etc).
meta.data_confidenceenumHighMediumLow
meta.last_verified_atdate nullableISO date when a human last confirmed this row.

Filter behavior v1.5.1

ScenarioBehavior
visa_types omittedReturns all visa categories present for the destination.
visa_types=BusinessReturns only Business rows in the visa_types[] array.
visa_types=Business,StudentReturns rows matching either category. Order: is_primary DESC, visa_type ASC, visa_subtype ASC.
Case variations (business, BUSINESS)Normalized to canonical casing. Echoed in meta.visa_types_filter.
Duplicates (Business,business)Deduplicated.
Empty (visa_types=) or commas onlyTreated as no filter — all types returned.
Filter matches nothingNot a 404. Returns 200 with empty visa_types[].
Invalid value (e.g. Bogus)Returns 400 INVALID_VISA_TYPE.
Legacy top-level fieldsAlways reflect Tourist primary record — never affected by the filter.
GET/passport-strength.php

Passport Strength

Returns an aggregate mobility profile for a passport: how many destinations are visa-free vs require advance application, fee statistics across all destinations, application workflow distribution, approval-rate counts, data-quality counts, and the passport's rank versus all other supported passports.

Parameters

ParamTypeDescription
passport_country_iso2StringRequired. 2-letter ISO 3166-1 alpha-2 code (e.g., BD).

Example Request

GET /passport-strength.php?passport_country_iso2=BD
Response shape
{
  "data": {
    "passport": { "country": "Bangladesh", "iso2": "BD", "currency_code": "BDT" },
    "total_destinations": 203,
    "score": {
      "mobility_score": 27,
      "rank": 7,
      "rank_of_total": 10,
      "rank_method": "visa_free + visa_on_arrival count"
    },
    "mobility": {
      "visa_free": 18, "visa_on_arrival": 9,
      "no_advance_visa": 27, "visa_required": 175,
      "own_country": 1,
      "visa_free_percentage": 8.9,
      "open_access_percentage": 13.3
    },
    "entry_type_breakdown": { "Single": 138, "Multiple": 37, ... },
    "approval_rate_distribution": { "High": 26, "Medium": 167, "Low": 10, "Unknown": 0 },
    "application_workflow": {
      "centers": { "Embassy": 53, "VFS Global": 44, ... },
      "appointment_required_count": 93,
      "interview_required_count": 1,
      "urgent_processing_available_count": 2,
      "extension_possible_count": 25,
      "transit_visa_required_count": 3
    },
    "fees": {
      "average_usd": 87.5, "median_usd": 75,
      "min_usd": 0, "max_usd": 300,
      "free_count": 27, "sample_size": 202
    },
    "data_quality": { "high_confidence": 53, "medium_confidence": 136, "low_confidence": 14 },
    "visa_free_destinations": [ {"iso2": "BS", "country": "Bahamas"}, ... ],
    "visa_on_arrival_destinations": [ {"iso2": "BJ", "country": "Benin"}, ... ]
  }
}
GET/passport-compare.php

Passport Compare NEW v1.5.0

Compares 2-10 passports side-by-side. Returns per-metric value maps, a winners block highlighting the best passport per metric (with tie support), and set operations on destinations: common visa-free destinations across ALL compared passports, and destinations unique to each.

Parameters

ParamTypeDescription
codesStringRequired. Comma-separated 2-letter ISO codes, 2-10 passports (e.g., BD,IN,PK). Duplicates are deduped.

Example Request

GET /passport-compare.php?codes=BD,IN,PK
Response shape
{
  "meta": {
    "generated_at": "...",
    "compared_count": 3,
    "rank_method": "visa_free + visa_on_arrival count"
  },
  "data": {
    "compared_passports": [
      { "country": "Bangladesh", "iso2": "BD", "currency_code": "BDT",
        "mobility_score": 27, "global_rank": 7, "rank_of_total": 10 },
      { "country": "India", "iso2": "IN", "currency_code": "INR",
        "mobility_score": 53, "global_rank": 3, "rank_of_total": 10 },
      { "country": "Pakistan", "iso2": "PK", "currency_code": "PKR",
        "mobility_score": 8, "global_rank": 10, "rank_of_total": 10 }
    ],

    "comparison": {
      "mobility_score":              { "BD": 27, "IN": 53, "PK": 8 },
      "visa_free":                   { "BD": 18, "IN": 27, "PK": 6 },
      "visa_on_arrival":             { "BD": 9,  "IN": 26, "PK": 2 },
      "no_advance_visa":             { "BD": 27, "IN": 53, "PK": 8 },
      "average_fee_usd":             { "BD": 87.5, "IN": 75.2, "PK": 102.4 },
      "high_approval_destinations":  { "BD": 26, "IN": 58, "PK": 35 },
      "low_approval_destinations":   { "BD": 10, "IN": 12, "PK": 47 },
      "appointment_required_count":  { "BD": 93, "IN": 89, "PK": 106 }
      /* ... more metrics */
    },

    "winners": {
      "highest_mobility_score":           ["IN"],
      "most_visa_free":                   ["IN"],
      "cheapest_average_fee":             ["IN"],
      "fewest_low_approval_destinations": ["BD"]
      /* always arrays — supports ties */
    },

    "visa_free_destinations": {
      "common_to_all": [
        { "iso2": "BB", "country": "Barbados" }
      ],
      "unique_per_passport": {
        "BD": [ { "iso2": "BS", "country": "Bahamas" } ],
        "IN": [ { "iso2": "TT", "country": "Trinidad and Tobago" } ],
        "PK": []
      }
    },

    "per_passport_detail": {
      "BD": { /* full strength aggregation */ },
      "IN": { /* ... */ },
      "PK": { /* ... */ }
    }
  }
}

Notes

Winners are arrays. When multiple passports tie on a metric (e.g., both have zero interviews required), all tied codes appear in the array. Client code can safely treat as a list of length 1+.

Rank stays global. The global_rank on each compared passport is its position across all 10 supported passports — not the position within the subset you're comparing. So comparing BD vs PK still shows BD=7 and PK=10.

GET/countries-list.php

Countries List

Fetches the distinct list of countries supported by the system. Useful for populating dropdowns.

Parameters

ParamTypeDescription
typeStringOptional. One of: all (default), passport, visiting.

Example Request

GET /countries-list.php?type=all
GET/visiting-countries.php

Visiting Countries List

Returns countries available for visiting. If a passport code is provided, the list is filtered to only countries reachable by that passport — useful for cascading dropdowns.

Parameters

ParamTypeDescription
passport_country_iso2StringOptional. Returns only countries reachable by this passport.

Example Request

GET /visiting-countries.php?passport_country_iso2=BD

Enum Field Reference

Quick reference for the structured ENUM values used across the API.

EnumValuesNotes
visa_typeTouristBusinessTransitStudentWorkFamilyMedicalConferenceJournalistDiplomaticCreweVisaVoAVisa-FreeOtherCategories within visa_types[].
entry_typeSingleDoubleMultipleVisa-FreeVoAN/AVoA = Visa on Arrival. N/A for own-country.
application_center_typeEmbassyVFS GlobalBLS InternationalTLScontactDirect OnlineVoAVisa-FreeMixedOtherMixed = multiple application channels.
appointment_required / interview_required / extension_possible / transit_visa_requiredYesNoConditionalN/AConditional = depends on visa category or applicant profile.
urgent_processing_availableYesNoN/AN/A for visa-free.
approval_rate_estimateHighMediumLowUnknownDerived from documented rejection patterns. Not a guarantee.
requirements.*.statusYesNoConditionalRecommendedMandatoryN/AGranular requirement status.
data_confidenceHighMediumLowInternal trust signal.

Error Responses

All errors follow a consistent shape. Inspect error.code programmatically.

{
  "success": false,
  "error": {
    "code": "INVALID_ISO2",
    "message": "Invalid passport_country_iso2: must be a 2-letter ISO 3166-1 alpha-2 code (e.g. BD, PK, US)."
  }
}

Error codes

HTTPCodeMeaning
400MISSING_PARAMA required query parameter was omitted.
400INVALID_ISO2Country code is not a valid 2-letter ISO 3166-1 alpha-2.
400SAME_COUNTRYPassport and visiting country are identical.
400INVALID_TYPEThe type parameter is not one of the allowed values.
400INVALID_CURRENCY NEW v1.7.0The currency parameter is not a 3-letter alphabetic ISO 4217 code.
400UNSUPPORTED_CURRENCY NEW v1.7.0The currency value is a valid ISO format but isn't in the currencies catalog. See /currencies.php.
404CURRENCY_NOT_FOUND NEW v1.7.0Returned by /currencies.php?code=XXX when no matching currency exists.
400INVALID_CONTINENT NEW v1.6.0The continent parameter is not one of: Africa, Americas, Asia, Europe, Oceania, Antarctica.
400INVALID_SUBREGION NEW v1.6.0The subregion value is not a known UN M.49 subregion. See /countries-list.php?type=subregions.
400INVALID_GROUP NEW v1.6.0One or more values in the group parameter is not a recognized group code. See /groups.php.
500MIGRATION_NOT_APPLIED NEW v1.6.0Returned by region/group endpoints when migration_regions_groups.sql has not been applied. Run the migration to enable.
404GROUP_NOT_FOUND NEW v1.6.0The code requested in /groups.php does not exist.
400INVALID_VISA_TYPE v1.5.1One or more values in the visa_types parameter is not a valid visa category.
400INSUFFICIENT_CODESFewer than 2 codes supplied to /passport-compare.php.
400TOO_MANY_CODESMore than 10 codes supplied to /passport-compare.php.
404PASSPORT_NOT_FOUNDNo data for the specified passport country.
404VISA_RECORD_NOT_FOUNDNo data for the specified passport-destination pair.
405METHOD_NOT_ALLOWEDUse GET; other methods rejected.
500MIGRATION_NOT_APPLIEDv1.3 schema columns missing — run migration scripts first.
500DB_CONNECTION_ERRORInternal database connection failed. Retry later.
GET/groups.php

Country Groups NEW v1.6.0

Lists all 20 country groups (Schengen, GCC, ASEAN, SAARC, EU, Eurozone, NATO, BRICS+, US VWP, ETIAS, EAC, CARICOM, Arab League, Commonwealth, G7, G20, OPEC, EFTA, CIS, Mercosur) with their members and metadata. Useful for populating filter dropdowns or displaying group memberships in client UIs.

Parameters

ParamTypeDescription
codeStringOptional. Return only this group (e.g. schengen). When set, the response is a single group object (not a list).
categoryStringOptional. Filter by category: politicaleconomicvisa-bloccustom
includeStringOptional. members to include the full member list (default for single-code request). count for member count only (default for list request).

Example Requests

# List all 20 groups with member counts
GET /groups.php

# Only visa-bloc category (Schengen, GCC, ASEAN, CARICOM, EAC, US VWP, ETIAS)
GET /groups.php?category=visa-bloc

# Single group with full member list
GET /groups.php?code=schengen

The 20 country groups

CategoryCodeNameMembers
visa-blocschengenSchengen Area29
visa-blocgccGulf Cooperation Council6
visa-blocaseanASEAN10
visa-bloccaricomCARICOM15
visa-bloceacEast African Community7
visa-blocus_vwpUS Visa Waiver Program40
visa-blocetiasETIAS (EU pre-authorization)58
politicaleuEuropean Union27
politicalsaarcSAARC8
politicalnatoNATO32
politicalcommonwealthCommonwealth of Nations56
politicalarab_leagueArab League22
politicalcisCIS9
economiceurozoneEurozone20
economicg7G77
economicg20G2019
economicbricsBRICS+9
economicopecOPEC13
economiceftaEFTA4
economicmercosurMercosur5