Vacant berth hopping

Build a same-train berth chain when no berth covers the full route.

GET /v1/charts/vacant-berths/hopping

Scope charts:read · Credits 10 · Plans Scale and Enterprise

Combines chart data, schedule, coach position, preferences, optional fares, alternate boarding, and multiple optimization strategies.

Authentication

Send your key in the X-RailCore-Key header. This operation requires the charts:read scope. See the authentication guide.

Request parameters

NameInTypeRequiredDescription
train_numberquerystringRequiredTrain number, 4 to 6 uppercase letters or digits.
fromquerystringRequiredBoarding station code.
toquerystringRequiredDestination station code.
datequerystring(date)RequiredJourney date in YYYY-MM-DD format.
viaquerystringOptionalPinned intermediate station codes in journey order, comma-separated.
max_hopsqueryintegerOptionalMaximum hopping chain length.
prefer_berthquerystringOptionalPreferred berth codes or aliases, comma-separated.
avoid_berthquerystringOptionalBerth codes or aliases to avoid. Avoid wins on conflicts.
prefer_classquerystringOptionalPreferred travel classes, comma-separated.
avoid_classquerystringOptionalClasses to skip entirely, comma-separated.
include_farequerybooleanOptionalAdd hop and direct-option fare data.
include_alternate_boardingquerybooleanOptionalEvaluate nearby stations as alternate boarding points.
strategiesquerystringOptionalmin_hops, min_seat_changes, cheapest, or all.
alternate_boarding_modequerystringOptionallightweight or extended candidate evaluation.
alternate_boarding_max_candidatesqueryintegerOptionalMaximum extended-mode candidates.
include_cross_classquerybooleanOptionalBuild one plan that can switch classes between hops.

Code examples

Base URL https://ir.railcore.tech/v1. Keep the key in an environment variable and call from a trusted server-side environment.

cURL

curl -sS -X GET \
  -H "X-RailCore-Key: $RAILCORE_KEY" \
  "https://ir.railcore.tech/v1/charts/vacant-berths/hopping?train_number=12656&from=BSL&to=ADI&date=2026-08-27&via=JL%2CAN&max_hops=6&prefer_berth=LB%2CSLB&avoid_berth=UB%2CSUB&prefer_class=SL%2C3A&avoid_class=1A&include_fare=false&include_alternate_boarding=false&strategies=min_hops%2Ccheapest&alternate_boarding_mode=lightweight&alternate_boarding_max_candidates=3&include_cross_class=false"

JavaScript

const response = await fetch("https://ir.railcore.tech/v1/charts/vacant-berths/hopping?train_number=12656&from=BSL&to=ADI&date=2026-08-27&via=JL%2CAN&max_hops=6&prefer_berth=LB%2CSLB&avoid_berth=UB%2CSUB&prefer_class=SL%2C3A&avoid_class=1A&include_fare=false&include_alternate_boarding=false&strategies=min_hops%2Ccheapest&alternate_boarding_mode=lightweight&alternate_boarding_max_candidates=3&include_cross_class=false", {
  method: "GET",
  headers: {
    "X-RailCore-Key": process.env.RAILCORE_KEY,
  },
});

const body = await response.json();
console.log(response.status, body);

Python

import os
import requests

response = requests.request(
    "GET",
    "https://ir.railcore.tech/v1/charts/vacant-berths/hopping?train_number=12656&from=BSL&to=ADI&date=2026-08-27&via=JL%2CAN&max_hops=6&prefer_berth=LB%2CSLB&avoid_berth=UB%2CSUB&prefer_class=SL%2C3A&avoid_class=1A&include_fare=false&include_alternate_boarding=false&strategies=min_hops%2Ccheapest&alternate_boarding_mode=lightweight&alternate_boarding_max_candidates=3&include_cross_class=false",
    headers={"X-RailCore-Key": os.environ["RAILCORE_KEY"]},
    timeout=20,
)
print(response.status_code, response.json())

Rate limits and credits

This call costs 10 credits and is available on Scale and Enterprise. Per-minute and daily budgets, and the headers reporting remaining quota, are documented in rate limits and credits and billing.

Response fields

FieldTypeDescription
train_number / train_namestringResolved train identity.
from_station_code / to_station_codestringRequested segment.
train_start_datestring(date)Train origin start date used for chart lookup.
remote_station_codestringRemote charting station.
chart_statusobjectChart one and chart two flags and preparation times.
coach_summary[]object[]Coach, class, engine position, and vacant berth count.
vacant_berths[]object[]Coach, class, berth, vacancy segment, split number, and segment coverage flag.
requested_segmentobjectResolved stop sequences, stations, and pinned via points.
direct.availablebooleanTrue when one berth covers the full segment.
direct.options[]object[]Direct options grouped by class, with berths and optional fare.
hopping.disabled / disabled_reasonboolean / string | nullWhether schedule limitations prevented hopping analysis.
hopping.options[]object[]Per-class coverage plan, hop count, physical seat changes, reason, fare, and strategy plans.
hopping.options[].hops[]object[]Effective segment, coach, class, berth, stop sequence, fare, and ergonomics for each leg.
alternate_boardingobjectCandidate stations, vacancy deltas, chart status, fares, notes, and recommendation scores.
cross_classobjectOptional plan that allows class changes between hops.
_metaobjectChart type, classes, partial failures, enrichment status, preferences, and algorithm notes.

Example response

{
  "success": true,
  "data": {
    "train_number": "12656",
    "train_name": "Navjeevan SF Express",
    "from_station_code": "BSL",
    "to_station_code": "ADI",
    "train_start_date": "2026-08-27",
    "chart_status": {
      "chart_one_prepared": true,
      "chart_two_prepared": true
    },
    "direct": {
      "available": false,
      "options": []
    },
    "hopping": {
      "disabled": false,
      "disabled_reason": null,
      "options": [
        {
          "class_code": "3A",
          "is_covered": true,
          "total_hops": 2,
          "physical_seat_changes": 1,
          "total_fare_inr": 1190,
          "hops": [
            {
              "from_station_code": "BSL",
              "to_station_code": "AN",
              "coach_name": "B1",
              "class_code": "3A",
              "berth_number": 17,
              "berth_code": "L",
              "fare_inr": 610
            },
            {
              "from_station_code": "AN",
              "to_station_code": "ADI",
              "coach_name": "B2",
              "class_code": "3A",
              "berth_number": 28,
              "berth_code": "SL",
              "fare_inr": 580
            }
          ]
        }
      ]
    },
    "alternate_boarding": {
      "enabled": false,
      "candidates": []
    },
    "cross_class": {
      "enabled": false,
      "plan": null
    },
    "_meta": {
      "classes_requested": [
        "3A"
      ],
      "max_hops": 6,
      "partial_failures": []
    }
  },
  "meta": {
    "api_version": "v1",
    "request_id": "req_01J5Z7Y8N2K4M6P8R0T2V4X6Z8",
    "trace_id": "trc_01J5Z7Y8N2K4M6P8R0T2V4X6Z9",
    "timestamp": "2026-08-20T17:12:23.305Z",
    "freshness": {
      "mode": "live",
      "retrieved_at": "2026-08-20T17:12:23.305Z",
      "sources": [
        {
          "confidence": "high"
        }
      ]
    }
  }
}

Errors

StatusCodeDescriptionRetry
409CHART_NOT_PREPAREDThe chart is not ready for analysis.Retryable
400VALIDATION_ERRORA required field is missing or invalid.Not retryable
401MISSING_API_KEY / INVALID_API_KEYThe credential is absent, unknown, disabled, or expired.Not retryable
403SCOPE_MISSING / PLAN_ENDPOINT_DISABLEDThe key lacks the required scope or plan entitlement.Not retryable
402CREDITS_EXHAUSTEDThe account balance cannot cover this operation.Not retryable
429RATE_LIMITEDMinute or daily request budget is exhausted. Honor Retry-After.Retryable
410API_VERSION_SUNSETThis API version has reached its announced sunset date. Migrate to a supported major version.Not retryable
502UPSTREAM_UNAVAILABLELive data could not be retrieved. Retry with backoff.Retryable
504UPSTREAM_TIMEOUTThe live-data request exceeded its deadline. Retry with backoff.Retryable
503METERING_UNAVAILABLECredit settlement is temporarily unavailable and no data was returned.Retryable

Related Charts endpoints

All RailCore Indian Railways API endpoints · Quickstart · Rate limits