---
title: Changelog
description: Recent free and Pro releases — what changed, what to test, and the safe upgrade path.
prev:
text: Troubleshooting
link: /troubleshooting
next:
text: Support
link: /support
---
# Changelog
This is the operator-facing release log for Yatra Free and Yatra Pro. The canonical changelogs ship inside each plugin's `readme.txt` (free: [WordPress.org](https://wordpress.org/plugins/yatra/#developers); Pro: bundled in the plugin ZIP). Use this page for context — what changed, why it matters, and what to test before deploying to production.
## How to read these notes
- **Safe to update from X** means the patch is non-breaking. You can update and keep working.
- **Major version** (3.x → 4.x) means breaking changes; back up first.
- **Pro depends on free** — always update the free plugin first, then Pro.
## Yatra Free
### 3.0.5
Routing, FSE compatibility, and bug-fix release. **Strongly recommended** for any site running a block theme. Backward compatible with 3.0.4.
**Full Site Editing (FSE) compatibility**
- **No more 404 chrome on plugin pages.** Block themes were resolving Yatra URLs to `404.html` (with its 404 header template part) because `WP::handle_404()` saw no matching post. Yatra now hooks `pre_handle_404` to opt its routes out of WordPress's 404 logic, so the resolved template is `index.html` / the singular / archive variant — not 404. The visible symptom (404-flavoured header bar on trip / listing / booking / account pages) is gone.
- **Proper template-include flow.** Page handlers no longer `include + exit` inside `template_redirect`. They configure `$wp_query` (virtual `WP_Post`, correct conditional tags) and stash the chosen PHP template in a per-request `PageContext`; a `template_include` filter at priority 99 swaps it in. WordPress's full template-loader pipeline runs, so SEO plugins, caching layers, `wp_head` / `wp_footer` extensions, and theme overrides all work.
- **Site Editor visibility.** Yatra registers virtual block templates (*Yatra: Single Trip*, *Yatra: Trip Listing*, *Destination*, *Activity*, *Booking*, *Booking Confirmation*, *My Account*). Admins can find and edit them under Appearance → Editor → Templates. Saved customisations override the bundled PHP template. The embedded `yatra/page-content` server block renders Yatra's content inside whatever chrome the admin designs.
- **Theme overrides without the editor.** Drop a copy of any Yatra template at `wp-content/themes/{your-theme}/yatra/{template}.php` and `locate_template()` picks it up first — works for classic themes and block themes.
**Per-trip Deposit fields now actually save**
- `TripValidator::sanitize()` previously had an explicit allowlist that included `payment_terms` but **silently dropped** `deposit_amount` and `deposit_percentage`. The fields appeared to save (no error), the DB columns just never received the values. Validator now sanitises all three plus does range validation (amount ≥ 0, percentage 0–100).
- Empty values clear the column (NULL) rather than coercing to 0, so the Pro Flexible Payments filter can correctly distinguish *no per-trip override* from *intentional $0 deposit*.
**Deposit option now appears for per-trip values**
- `templates/partials/booking-form-fields.php` now passes `trip_id` to the `yatra_payment_method_options` filter context. Pro's Flexible Payments module can read it and show the *Pay X% Deposit* radio whenever a trip has per-trip deposit values, even when the site-wide deposit flag is off. Previously the radio only appeared if you globally enabled deposits.
**Filter signatures (additive, backward compatible)**
`$context` is now passed to:
- `yatra_deposit_percentage(int $default, array $context = [])`
- `yatra_partial_payment_percentage(int $default, array $context = [])`
- `yatra_calculate_amount_due(float $amount_due, float $total_amount, string $method, array $context = [])`
- `yatra_payment_method_options(array $options, array $booking_data)` — `$booking_data` gains `trip_id`.
Old callbacks that ignore the new arg continue to work; they just won't see per-trip overrides. See [Hooks & filters → Flexible / Scheduled Payments](/hooks-filters#pro-flexible-scheduled-payments).
**UI polish**
- Booking-page tax line item now uses a proper Feather *percent* icon (the previous SVG had two overlapping paths that rendered as a broken wallet shape).
- The **Deposit & Payment Terms** section on the Trip Edit form is now visible in the free plugin — fields are disabled with a **PRO** badge and an *Upgrade to Pro* / *Activate module* CTA. Operators on the free plugin can now discover the feature instead of finding nothing.
**Internal cleanup**
- Removed unused `app/Core/Template/TemplateRenderer.php` (zero external consumers in Free or Pro).
- Replaced two hardcoded table names in Pro (`{$wpdb->prefix}yatra_trips`, `{$wpdb->prefix}yatra_departures`) with `TripsTable::getTableName()` / `DeparturesTable::getTableName()` — the hardcoded names referenced tables that no longer exist after the `_new_` rename and would surface as *Table doesn't exist* warnings.
**Upgrade safety:** safe to update from 3.0.4.
### 3.0.4
Security and correctness release. **Strongly recommended** if you accept payments. No UI changes — all fixes are server-side and backward compatible.
**Payment-flow security**
- **Server-authoritative amounts.** `POST /yatra/v1/payment/create-intent` now ignores the `amount` and `currency` in the request body when a `booking_id` is supplied — both values are recomputed from the stored booking row. A tampered front-end can no longer pay $1 for a $1000 trip. Mismatches fire a new `yatra_payment_amount_mismatch` action so you can wire fraud monitoring.
- **Booking ownership enforcement.** `POST /payment/confirm` and `GET /payment/status/{booking_id}` now verify the requester is the booking owner, an admin, or a guest with a matching short-lived `booking_token`. Anonymous reads of arbitrary booking IDs return `401`.
- **Idempotent payment recording.** `PaymentRepository::create()` and `handle_successful_payment()` now skip insertion if a payment with the same `transaction_id` already exists for the booking. Reloads, parallel return-to-site + webhook races, and double-clicked confirmations all collapse to a single payment row and a single confirmation email.
- **Cross-booking transaction reuse blocked.** Submitting a successful `transaction_id` against a different booking now returns `409 transaction_mismatch`.
**PDF generation hardening**
- dompdf is now `chroot`'d to `ABSPATH` so a crafted template can no longer read `/etc/passwd` via `file://`.
- Remote fetches restricted to `http://` / `https://` only, with a 5-second timeout, peer-verified TLS, and a `YatraPDF/` user-agent so dompdf-originated traffic is greppable in upstream logs.
- New `yatra_pdf_remote_enabled` filter — return `false` to disable remote loading entirely if your PDFs never reference external images.
- `Content-Disposition` filename now CR/LF-stripped and emits an RFC 5987 `filename*=UTF-8''…` form alongside the ASCII fallback. Closes a header-injection / cache-poisoning vector for PDFs whose filename derives from booking metadata.
- Template renderer no longer uses `extract($data, EXTR_OVERWRITE)` — switched to identifier-validated keys with `EXTR_SKIP` so a malicious data array cannot inject arbitrary local variables into the template scope.
**Migration safety**
- `ItineraryMigration::parseItineraryData()` now passes `['allowed_classes' => false]` to `unserialize()`, blocking PHP object-injection / `__destruct` gadget chains via crafted legacy post meta. Stopped silently swallowing `json_decode` errors.
**Upgrade safety:** safe to update from 3.0.3.x. PHP 7.4+ continues to be supported.
### 3.0.3
The most recent free release. Significant content for both authors and operators.
**Trip catalog and listings**
- New `[yatra_trip_category]` shortcode and **Trip categories** block — list trip categories in the same card layout as destinations, with optional filters and pagination (`trip_category_page`).
- **Featured Priority** filter is now a first-class attribute on `[yatra_trip]` and the Trip block (`featured_priority="featured|new|limited"`). It mirrors the trip form's *Categorization → Featured Priority* value.
- **Difficulty / fitness-level** filter (`difficulty="3,5"`) now works on both shortcode and block.
- The legacy `featured="1"` shortcode attribute is preserved as a back-compat alias for `featured_priority="featured"`. If both are set, `featured_priority` wins.
- Filter rules are centralized in `TripListingFilterBuilder` so the same logic applies to shortcode and block inputs.
**Trip block**
- The legacy "Show only featured trips" toggle was retired. Its behavior is now expressed by setting **Featured Priority = Featured**.
- Existing block instances saved with `featured: true` are auto-migrated to `featured_priority: "featured"` when reopened in the editor.
- Inserter title and labels read **Trip** (registered block name `yatra/tour` is preserved for back-compat with saved posts).
**Card UX (Destination / Activity / Trip Category)**
- The whole card is now a click target instead of just the title text. Implemented via the WAI-ARIA "stretched link" pattern (CSS pseudo-element on the existing title ``) so a single canonical link is exposed to screen readers and crawlers; keyboard focus shows a card-wide outline.
**Enquiry emails**
- {{trip_name}} (and other trip merge tags) now resolve correctly when an enquiry is submitted from a single-trip page. The modal posts `trip_id` / `trip_slug` reliably; backend normalizes `tripId` casing and derives `trip_id` from slug or `HTTP_REFERER` when missing.
- `EnquiryService` now eager-loads joined trip data before firing `yatra_enquiry_created` so admin templates and Pro automation receive a complete object.
- Merge-tag regex now tolerates surrounding whitespace ({{ trip_name }}).
**Payments admin**
- The *Add / Edit Payment* form's **Booking ID** text field is replaced with a searchable **booking picker** that queries `GET /yatra/v1/bookings?search=…` and matches against booking code (reference), customer name, and email — debounced server-side search with rich rows.
- The *Payment Date* field now uses the shared admin **DatePicker** for visual parity with every other date field in the admin and prevents future-dated payments by default.
**Single trip**
- Group discount discoverability in the sidebar.
- **Similar trips** links respect plain permalinks via `yatra_get_trip_permalink()`.
- Enquiry modal **Send Enquiry** uses `yatra-booking-button` so primary color matches **Check Availability** and global `--yatra-primary` tokens.
**Discounts**
- REST and repository hardening — writable column whitelist, safer updates.
**Upgrades**
- Version-gated free upgrade runner.
- Legacy payment tokens table dropped when applicable (see `Upgrade_3_0_3`).
**Admin / i18n**
- Trip Builder meal plan strings use shared labels.
- Attribute icon picker preserves Font Awesome `provider` after save.
- Front-end Important Info shows translated meal plan labels (`yatra_meal_plan_label()`).
**Upgrade safety:** safe to update from 3.0.2.x.
### 3.0.2.9
- **Mobile booking bar:** Improved sticky booking UI on small screens (date + travelers layout, full-width travelers dropdown opening upward, and reliable click targets).
- **Admin caching:** Fixed service cache invalidation so updates (including SEO fields) reflect immediately when cache is enabled.
Safe to update from 3.0.2.8.
### 3.0.2.8
- **Booking UI:** Added Advanced settings to select **Terms & Conditions** and **Privacy Policy** pages; booking form now links to these pages (Privacy falls back to WordPress Settings → Privacy when unset).
- **Fix (Usage Tracking):** Moved `StatsUsage` into `app/Services` and updated references to avoid case-sensitive autoload issues on Linux hosts.
- **Fix (Gallery Modal):** Hardened gallery modal image URL resolution against LiteSpeed Cache lazy-load placeholders.
Safe to update from 3.0.2.7.
### 3.0.2.7
- **Fix (Gallery Modal):** Improved compatibility with LiteSpeed Cache lazy-load placeholders (base64 `src`) so the modal always opens the real image URLs.
- **Compat (LiteSpeed Cache):** Excluded Yatra hero/gallery selectors from LiteSpeed lazy-load and excluded Yatra trip assets from optimisation where needed.
Safe to update from 3.0.2.6.
### 3.0.2.6
- **Fix:** Composer autoload path was declared as `includes/Admin/` (uppercase) but the directory on disk is `includes/admin/` (lowercase); caused fatal `include` warnings on Linux/cPanel servers (case-sensitive filesystems).
- **License:** Removed stub `LicenseController` from the free plugin — all `/yatra/v1/license/*` routes are now registered exclusively by Yatra Pro's own controller, eliminating any route conflicts.
- **Admin UI (Additional Services):** Added missing **Add New Service** button via the `PageHeader` component on the Additional Services screen.
Safe to update from 3.0.2.5.
### 3.0.2.5
- Admin: add Review + Upgrade notices (React UI + WordPress notices) with smart dismiss scheduling.
- Setup wizard: save step settings when navigating between steps.
### 3.0.2.4
- **REST:** implemented `TripService::permanentDelete()` so `DELETE /yatra/v1/trips/{id}/permanent-delete` no longer fatals (fixes permanent delete from trash and bulk actions).
- **Admin (React):** bulk trip actions rely on `BulkActionToolbar` confirmation only (removed duplicate `window.confirm`); improved bulk dialog copy for `mark_*` actions.
Safe to update from 3.0.2.3.
### 3.0.2.3
- **Admin (React):** moved fullscreen shell CSS into the document head to reduce wp-admin chrome flicker; added HTML/CSS boot splash and `modulepreload` for the admin bundle; primary sidebar navigation uses client-side URL updates so the PHP loading state does not repeat on every screen change.
- **REST:** registered License routes in the API registry so `GET /yatra/v1/license` works on the free plugin (License screen and scripts that probe it).
- **Admin UI:** hardened Departures and Availability trip dropdowns against TanStack Query cache shapes and `/trips` list payloads (fixes `map` / `find` errors when navigating without a full reload).
Safe to update from 3.0.2.2.
### 3.0.2.2
Maintenance / patch release. Safe to update from 3.0.2.1.
### 3.0.2.1
- **Readme:** linked Pro gateways, modules, traveler features, and related mentions to wpyatra.com/pricing throughout the long description, FAQ, and quick links.
Patch release; safe to update from 3.0.2.
### 3.0.2
- **Readme:** reorganized the long description — the **Yatra Pro** section now appears **before** **Blocks and shortcodes** for a clearer Free → Pro → integration flow.
Documentation-only release for the plugin directory listing; no code changes required for existing 3.0.x sites.
### 3.0.1
- Maintenance release: updated WordPress.org banner and directory assets (including screenshots) for the 3.x listing.
- Shortened the plugin short description to meet WordPress.org's 150-character limit so imports are no longer truncated.
### 3.0.0
- **Major release:** redesigned admin experience, streamlined booking and traveler account flows, expanded gateway and module architecture for Pro, and ongoing hardening for production travel sites.
- See [wpyatra.com/yatra-3-0/](https://wpyatra.com/yatra-3-0/?utm_source=docs&utm_medium=referral&utm_campaign=yatra-docs) for the release writeup.
- **Always back up** before upgrading from 2.x; follow migration guidance in [Installation](/installation).
### Earlier versions (2.x)
For 2.x changelog entries, see the plugin's [GitHub releases](https://github.com/MantraBrain/yatra/releases).
## Yatra Pro
### 3.0.1
The most recent Pro release. Pair with Yatra Free 3.0.3 (or current 3.0.x).
**Dynamic Pricing — admin actions**
- The **Move to Trash** and **Delete Permanently** confirmations on a single rule now actually run (previously stub callbacks did nothing).
- Bulk **Move to Trash** is fixed end-to-end (the rules controller now accepts `status: trash` in both `PUT /rules/{id}` and `POST /bulk-status`).
- Bulk **Delete Permanently** is reachable from the Trash filter.
- Repository statistics expose `trash_rules`; default *Total* count and the *All* tab now exclude trashed rules per WordPress convention.
- Bulk runner uses `Promise.allSettled` and reports partial-success state instead of failing the entire batch on a single bad row.
**Email Automation (enquiry)**
- Defensive fallback in `EmailAutomationService::buildEnquiryVariables()` resolves `trip_name` / `trip_url` directly from `TripRepository` when an enquiry payload arrives without joined trip data (paired with the free plugin's eager-loading fix in `EnquiryService`).
- Prevents {{trip_name}} from rendering as *General Enquiry* on enquiry-created emails.
**Version**
- Yatra Pro **3.0.1** (release packaging). Use with Yatra free **3.0.3** or current supported 3.0.x.
- Safe to update from Pro **3.0.0.1** or **3.0.3**.
### 3.0.2
Security and correctness release. Pairs with Yatra free **3.0.4**. **Strongly recommended** if you have any Pro gateway enabled.
**Stripe**
- New webhook handler with proper `Stripe-Signature` HMAC-SHA256 verification (5-minute replay tolerance, key-rotation aware via multiple `v1=` signatures). Subscribe to `payment_intent.succeeded`, `payment_intent.payment_failed`, and `charge.refunded` in your Stripe dashboard. **Webhooks without a configured secret are now rejected** — set the *Webhook secret* field if you rely on Stripe's retry-driven delivery.
- `completePayment()` is now idempotent: a webhook arriving after the user already returned to your site is a no-op. Same `(booking_id, transaction_id)` pair can only ever produce one payment row.
- New actions `yatra_stripe_payment_succeeded`, `yatra_stripe_payment_failed`, `yatra_stripe_charge_refunded` for downstream automations.
**Razorpay**
- `completePayment()` is now idempotent on `(booking_id, transaction_id)` — webhook + return-handler races collapse to a single payment row.
**Partial / deposit payment correctness**
- Stripe and Razorpay no longer force-mark a booking as fully paid when only a deposit was collected. `amount_paid` now accumulates correctly; `payment_status` resolves to `partial` / `paid` based on the remaining balance.
**License & settings hardening**
- `GET /yatra/v1/license` no longer returns the raw license key or the full EDD `server_response` blob. Returns a masked key (last 4 visible) plus a whitelisted subset of expiry / activation fields.
- `POST /yatra/v1/settings` now writes only schema-approved keys via the new `yatra_pro_writable_settings_schema` filter. Unknown keys are reported in the response's `rejected_keys` array instead of silently overwriting arbitrary `yatra_pro_*` options. If you have a custom Pro module that wrote settings via this endpoint, register your keys with the filter.
**Upgrade safety:** update Yatra free to **3.0.4** *first*, then Yatra Pro to 3.0.2. Both are safe from their respective previous patch versions.
### 3.0.3
- **Scheduled payments:** migrate off legacy payment tokens to `gateway_payment_method_id`; Pro upgrade runner and `Upgrade_3_0_0_1` (runs when crossing from below 3.0.0.1).
- **Version:** aligned with Yatra Free 3.0.3 for release packaging.
Safe to update from 3.0.0.1.
### 3.0.0.1
- **Fix:** avoid database errors on sites missing the `zip` column on the customers table (Mailchimp + Facebook Pixel integrations).
### 3.0.0
- Initial release of Yatra Pro
- Added Google Calendar Integration module
- Enterprise-grade architecture with clean code structure
- PSR-4 autoloading and PSR-12 coding standards
## Upgrade strategy
### Patch updates
`3.0.x → 3.0.y`. Safe to update on the live site during a quiet window. The pre-upgrade check is:
1. Take a database backup (most managed hosts auto-backup; verify yours did).
2. Update on a staging or backup site first if you have one.
3. Update on production.
4. Visit **Yatra → Tools → Migration** to confirm any database upgrades ran cleanly.
### Minor updates (planned)
`3.0.x → 3.y.0`. Same as patch but read the changelog for any settings that need adjusting (e.g. a new module that's enabled by default).
### Major updates
`3.x → 4.x`. **Don't** run on production first. Migration steps:
1. Stage on a clone of production.
2. Run the migration tool, validate trips/bookings/customers visually.
3. Test a real booking end-to-end with a sandbox gateway.
4. Once confirmed, schedule a brief maintenance window on production.
5. Backup → update → verify → flush rewrites → unfreeze.
## Where else to track changes
- [WordPress.org Yatra plugin page](https://wordpress.org/plugins/yatra/) — official release dates and download counts.
- [GitHub releases](https://github.com/MantraBrain/yatra/releases) — release notes and downloadable ZIPs.
- [wpyatra.com/blog](https://wpyatra.com/?utm_source=docs&utm_medium=referral&utm_campaign=yatra-docs) — long-form release writeups for major versions.