Skip to content
InstantRailCheck

API

Read-only, unauthenticated, and CORS-enabled — free to use in your own tools. Responses are JSON by default; list endpoints also support &format=csv. Every response includes an X-Api-Version header, bumped whenever a documented response shape changes.

GET/banks

List all banks. Optional ?q= to search by name. Optional ?limit=/&offset= to page through results (max limit 500) — omitting them still returns the full directory in one response, capped at 5000 as a safety net, so this remains additive rather than a breaking change. Only currently-listed (is_active) institutions by default — pass ?include_inactive=true to also include closed/merged/unlisted ones. Each bank row now also includes city/state. The response includes total (the full matching count, independent of limit/offset), truncated (whether more rows exist beyond this response), and next_offset (the offset to fetch them, or null) alongside banks. CSV responses carry the same three as X-Total-Count/X-Truncated/X-Next-Offset headers instead of body fields. Add &format=csv for CSV instead of JSON.

GET https://api.instantrailcheck.com/banks?q=chase&limit=50&offset=0
GET/banks/:id

Full profile for one bank: contact info, network participation, and per-rail evidence sending/receiving (attributable report counts by outcome, distinct routes observed, latest observation date — no success percentage).

GET https://api.instantrailcheck.com/banks/c681154f-c3c4-4f50-9031-a05c79b2d152
GET/routes

Evidence between two specific banks, per rail. Requires ?from= and ?to= bank ids. Only rails with at least one attributable (signed-in, non-duplicate) report are included — see the evidence states below.

GET https://api.instantrailcheck.com/routes?from=<bank-id>&to=<bank-id>
GET/changelog

Recent activity feed — banks added and attributable (signed-in) route reports submitted. Unattributed/legacy reports never appear. "First confirmed" is scored per directional route+rail, same unit as /routes. Optional ?limit= (max 200, default 50). Add &format=csv for CSV instead of JSON.

GET https://api.instantrailcheck.com/changelog?limit=10

Route evidence states

/routes and /banks/:id describe evidence rather than a single confidence score. A report only counts if it's from a signed-in user (unattributed/legacy rows never count), and only each reporter's newest report for a given route and rail is used — so one person can't inflate the count. A route or rail with no attributable reports is simply absent from the response, not marked with a "none" state.

Limited evidence
Exactly one attributable reporter within the last 180 days.
Observed working
Two attributable reporters within 180 days, all successful.
Consistently reported
Three or more attributable reporters within 180 days, all successful.
Reported unsuccessful
Every attributable report within 180 days failed.
Reported delayed
Every attributable report within 180 days was delayed.
Variable timing
A mix of successful and delayed attributable reports within 180 days, with no failures.
Conflicting reports
Attributable reports within 180 days disagree — at least one failure alongside a success or delay.
Previously observed
Attributable evidence exists, but all of it is older than 180 days.

Early Direct Deposit evidence

/banks/:id's eddEvidence is null until at least 2 distinct signed-in reporters have reported early direct deposit for that bank (same one-report-per-reporter rule as route evidence). When present, it includes avgDaysEarly, reportCount, hasMoreThanFive (some reporters selected the open-ended "more than 5 days" option, which avgDaysEarly excludes rather than averaging in), and providers.

Reporters can optionally note what kind of deposit it was and which payroll platform or provider paid it. providers breaks out bank-wide EDD evidence by provider (e.g. "ADP payroll deposits were reported 2 days early by 6 distinct reporters"), but only once a provider has 3 distinct reporters — a higher bar than overall eddEvidence, since naming a specific company is more identifying. A provider below that threshold is simply absent from the array, not included as a zero-count entry. Deposit types that aren't payroll (government benefits, tax refunds, pensions) never contribute to a provider's count, even if a provider was recorded alongside them.

avgDaysEarly is this endpoint's own bank-profile aggregate — a plain average of each reporter's newest value, excluding any reporter who chose the open-ended "more than 5 days" option (that sentinel is never averaged in as though it meant literally six days). It is a separate methodology from the /early-direct-deposit leaderboard, which ranks by a median/categorical typical value instead; the two are not expected to produce identical numbers for the same bank. avgDaysEarly is null — not a number, not omitted — when every attributable reporter chose the open-ended option, since no numeric average exists in that case. hasMoreThanFive flags that at least one reporter selected the open-ended option, independently of whether avgDaysEarly is a number or null. The same avgDaysEarly: number | null contract applies to each entry in providers. Raw edd_reports rows and reporter identities are never exposed by this or any other endpoint — only these pre-aggregated values.

v6 breaking change

/routes' confidence (a raw report-count threshold) and every rail's successRate were removed — both could reach a precise-looking number or a HIGH/MEDIUM/LOW label from unattributed or single-report data. /banks/:id's per-rail successRate was removed for the same reason. Both now expose an evidence object (or, on /banks/:id, attributable/successful/delayed/unsuccessful report counts and distinct-route counts) instead — see the evidence states above.

v7 breaking change

/banks now defaults to currently-listed institutions only — a bank the sync has marked closed, merged, or unlisted is excluded unless you pass ?include_inactive=true. The same unpaginated request as before can now return fewer rows than it used to for that reason alone. Every row also gains city/state, and both JSON (truncated/next_offset) and CSV (X-Truncated/X-Next-Offset headers) now say explicitly whether more rows exist beyond the current response.

v8 breaking change

eddEvidence.avgDaysEarly and each entry in eddEvidence.providers[].avgDaysEarly are now typed number | null instead of always number. Previously, a reporter who chose the open-ended "more than 5 days" option was averaged in as though they meant literally six days, silently overstating the true average. The sentinel is now excluded from the arithmetic entirely; null means every attributable reporter for that bank (or provider) chose the open-ended option, so no numeric average exists.

Webhooks

Rather than polling https://api.instantrailcheck.com/changelog, register a URL at /webhooks (requires signing in) to get a signed POST whenever a new bank is added. Each delivery includes an X-InstantRailCheck-Signature header — HMAC-SHA256 of the raw request body using the secret shown when you register. Deliveries are fire-and-forget with no retry, so your endpoint should respond quickly with a 2xx.