Rank every route train by chart vacancy and hopping coverage.
GET /v1/charts/vacant-berths/route-scan
Scope charts:read · Credits 25 · Plans Scale and Enterprise
Resolves station names or codes, scans route trains with bounded concurrency, scores each option, and returns plain-language recommendations.
Send your key in the X-RailCore-Key header. This operation requires the charts:read scope. See the authentication guide.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string | Required | Boarding station code or name. Fuzzy station-name matching is supported. |
to | query | string | Required | Destination station code or name. |
date | query | string(date) | Required | Journey date in YYYY-MM-DD format. |
quota | query | string | Optional | Reservation quota. |
max_trains | query | integer | Optional | Maximum trains fanned out for a full scan. Other trains remain visible as skipped. |
min_score | query | number | Optional | Drop returned matches below this score. |
only_running | query | boolean | Optional | Include only trains scheduled to run on the requested date. |
only_chart_prepared | query | boolean | Optional | Include only trains with at least one prepared chart. |
sort_by | query | string | Optional | Order matches by departure, latest departure, duration, score, or chart readiness. |
include_detail | query | boolean | Optional | Include full hopping_detail for every scanned train. |
train_types | query | string | Optional | Comma-separated train-type allow list. |
avoid_train_types | query | string | Optional | Comma-separated train-type deny list. Deny wins over allow. |
max_hops | query | integer | Optional | Maximum hopping chain length per train. |
prefer_berth | query | string | Optional | Preferred berth codes or aliases, comma-separated. |
avoid_berth | query | string | Optional | Berth codes or aliases to avoid. Avoid wins on conflicts. |
prefer_class | query | string | Optional | Preferred travel classes, comma-separated. |
avoid_class | query | string | Optional | Classes to skip entirely, comma-separated. |
include_fare | query | boolean | Optional | Add fare lookups to direct and hopping options. |
include_alternate_boarding | query | boolean | Optional | Evaluate nearby boarding points on the same train. |
strategies | query | string | Optional | Comma-separated strategy list: min_hops, min_seat_changes, cheapest, or all. |
alternate_boarding_mode | query | string | Optional | lightweight reuses fetched data; extended performs fresh candidate lookups. |
alternate_boarding_max_candidates | query | integer | Optional | Maximum extended-mode candidates. |
include_cross_class | query | boolean | Optional | Build one plan that can switch travel classes between hops. |
Base URL https://ir.railcore.tech/v1. Keep the key in an environment variable and call from a trusted server-side environment.
curl -sS -X GET \
-H "X-RailCore-Key: $RAILCORE_KEY" \
"https://ir.railcore.tech/v1/charts/vacant-berths/route-scan?from=Bhusaval&to=Ahmedabad&date=2026-08-27"a=GN&max_trains=8&min_score=50&only_running=true&only_chart_prepared=false&sort_by=score&include_detail=true&train_types=SF%2CRAJDHANI%2CVANDE_BHARAT&avoid_train_types=PASSENGER%2CMEMU%2CDEMU&max_hops=6&prefer_berth=LB%2CSLB&avoid_berth=UB%2CSUB&prefer_class=3A%2C2A&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"
const response = await fetch("https://ir.railcore.tech/v1/charts/vacant-berths/route-scan?from=Bhusaval&to=Ahmedabad&date=2026-08-27"a=GN&max_trains=8&min_score=50&only_running=true&only_chart_prepared=false&sort_by=score&include_detail=true&train_types=SF%2CRAJDHANI%2CVANDE_BHARAT&avoid_train_types=PASSENGER%2CMEMU%2CDEMU&max_hops=6&prefer_berth=LB%2CSLB&avoid_berth=UB%2CSUB&prefer_class=3A%2C2A&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);
import os
import requests
response = requests.request(
"GET",
"https://ir.railcore.tech/v1/charts/vacant-berths/route-scan?from=Bhusaval&to=Ahmedabad&date=2026-08-27"a=GN&max_trains=8&min_score=50&only_running=true&only_chart_prepared=false&sort_by=score&include_detail=true&train_types=SF%2CRAJDHANI%2CVANDE_BHARAT&avoid_train_types=PASSENGER%2CMEMU%2CDEMU&max_hops=6&prefer_berth=LB%2CSLB&avoid_berth=UB%2CSUB&prefer_class=3A%2C2A&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())
This call costs 25 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.
| Field | Type | Description |
|---|---|---|
from / to | ResolvedStation | Canonical station match, input, confidence, and alternates. |
journey_date / quota | string | Applied search context. |
route_summary | object | Route totals, scanned counts, coverage counts, and the best result. |
matches[].train_number / train_name / train_type | string | Train identity. |
matches[].departure_time / arrival_time / duration_minutes | string / integer | Segment schedule. |
matches[].runs_on_date / chart_prepared | boolean | Eligibility and chart state. |
matches[].recommendation / urgency_hint | string | null | Display-ready booking guidance. |
matches[].score / score_breakdown | integer / object | 0 to 100 ranking and auditable components. |
matches[].classes_summary | ClassSummary[] | Compact direct and hopping coverage per class. |
matches[].hopping_detail | VacantBerthsHoppingResponse | null | Full analysis when include_detail is true. |
matches[].scan_status / scan_status_reason | string | null | OK, chart state, upstream failure, or skip reason. |
_meta | object | Partial failures, filters, cap decisions, sort, preferences, and upstream summary. |
{
"success": true,
"data": {
"from": {
"station_code": "BSL",
"station_name": "Bhusaval Jn",
"resolved_from": "name",
"input": "Bhusaval",
"confidence": 0.98,
"alternates": []
},
"to": {
"station_code": "ADI",
"station_name": "Ahmedabad Jn",
"resolved_from": "name",
"input": "Ahmedabad",
"confidence": 0.99,
"alternates": []
},
"journey_date": "2026-08-27",
"quota": "GN",
"route_summary": {
"total_trains_on_route": 12,
"trains_running_on_date": 10,
"trains_scanned": 8,
"trains_with_direct_vacancy": 2,
"trains_with_hopping_coverage": 4,
"best_train_number": "12656",
"best_recommendation": "Direct berth available in 3A",
"best_score": 92
},
"matches": [
{
"train_number": "12656",
"train_name": "Navjeevan SF Express",
"departure_time": "10:25",
"arrival_time": "18:00",
"duration_minutes": 455,
"runs_on_date": true,
"chart_prepared": true,
"recommendation": "Direct berth available in 3A",
"urgency_hint": "Chart 2 prepared. Vacancy is authoritative.",
"score": 92,
"classes_summary": [
{
"class_code": "3A",
"direct_available": true,
"direct_berth_count": 4
}
],
"hopping_detail": null,
"scan_status": "OK",
"scan_status_reason": null
}
],
"_meta": {
"trains_dispatched": 8,
"partial_failures": [],
"sort_by": "score"
}
},
"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"
}
]
}
}
}
| Status | Code | Description | Retry |
|---|---|---|---|
| 404 | STATION_NOT_FOUND | A station input could not be resolved above the confidence threshold. | Not retryable |
| 400 | VALIDATION_ERROR | A required field is missing or invalid. | Not retryable |
| 401 | MISSING_API_KEY / INVALID_API_KEY | The credential is absent, unknown, disabled, or expired. | Not retryable |
| 403 | SCOPE_MISSING / PLAN_ENDPOINT_DISABLED | The key lacks the required scope or plan entitlement. | Not retryable |
| 402 | CREDITS_EXHAUSTED | The account balance cannot cover this operation. | Not retryable |
| 429 | RATE_LIMITED | Minute or daily request budget is exhausted. Honor Retry-After. | Retryable |
| 410 | API_VERSION_SUNSET | This API version has reached its announced sunset date. Migrate to a supported major version. | Not retryable |
| 502 | UPSTREAM_UNAVAILABLE | Live data could not be retrieved. Retry with backoff. | Retryable |
| 504 | UPSTREAM_TIMEOUT | The live-data request exceeded its deadline. Retry with backoff. | Retryable |
| 503 | METERING_UNAVAILABLE | Credit settlement is temporarily unavailable and no data was returned. | Retryable |
All RailCore Indian Railways API endpoints · Quickstart · Rate limits