GTFS Validator Micro-service 🚌

A lightweight, stateless API that wraps the official MobilityData GTFS Validator and exposes it as a single /validate endpoint.

Upload a GTFS .zip or provide a URL, receive a validation report in your chosen format.

Feature Notes
Serverless-ready Designed for Google Cloud Run (default) but can run wherever Docker can.
Fast cold-starts One-shot Java CLI lives in a slim image; typical cold-start ≤ 3 s.
Zero persistence No database to manage (other than API keys...and those are optional).
API-key & quota support Optionally uses Firestore to manage users and API keys in order to impose rates based on keys.
User registration & verification Auto-issues API keys to emails which are verified. Currently leverages Mailjet's free usage tier to send verification emails.
Language binding Pure REST (OpenAPI 3.0 spec included) → generate clients for Python, JS/TS, Go, etc.
Cost @ 100 feeds/day Currently fits well inside Cloud Run's free tier.

Endpoint Reference

Full documentation of endpoints is at https://validategtfs.urbanlabs.io/docs

Note: you can also use the API directly from the docs by clicking "try out".

Method Path Body Query Params Response
POST /validate multipart/form-data field file (GTFS .zip) or url (GTFS .zip URL) format (optional: json (default), html, errors) 200 OK JSON, HTML, or errors-only JSON report.
400 if neither or both file and url are provided.
500 if validator fails.

Parameters

Note: You must provide either file or url, but not both.


Deployed Usage

Command Line

Validate gtfsfeed.zip

curl -X POST \
  -F "file=@gtfsfeed.zip" \
  https://validategtfs.urbanlabs.io/validate

Use your API key in the header to increase your rate limits:

curl -X POST \
  -F "file=@feed.zip" \
  -H "x-api-key: <YOUR_API_KEY>" \
  https://validategtfs.urbanlabs.io/validate

Validate a feed hosted remotely at mobilitydata.org:

curl -X POST \
  -F "url=https://download.mobilitydata.org/gtfs/mdb/gtfs-2245.zip" \
  -H "x-api-key: <YOUR_API_KEY>" \
  https://validategtfs.urbanlabs.io/validate

Validate a feed and get returned the HTML report:

curl -X POST \
  -F "url=https://download.mobilitydata.org/gtfs/mdb/gtfs-2245.zip" \
  -H "x-api-key: <YOUR_API_KEY>" \
  "https://validategtfs.urbanlabs.io/validate?format=html"

Python

import requests

api_url = "https://https://validategtfs.urbanlabs.io/validate"
api_key = "<YOUR_API_KEY>"
gtfs_zipfile = "gtfsfeed.zip"

with open(gtfs_zipfile, "rb") as f:
    response = requests.post(
        api_url,
        params={"format": "html"}, # <--- Optional. can be json (default), html or errors (which is also json)
        files={"file": (gtfs_zipfile, f, "application/zip")}, # use this to validate a local feed
        # url = "https://download.mobilitydata.org/gtfs/mdb/gtfs-2245.zip", # use this if you want to validate a feed at a URL
        headers={"x-api-key": api_key}
    )
print(response.status_code)
print(response.json())

JavaScript (Node.js, using axios)

const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');

const apiUrl = 'https://https://validategtfs.urbanlabs.io/validate';
const apiKey = '<YOUR_API_KEY>';

const form = new FormData();
form.append('file', fs.createReadStream('gtfsfeed.zip'));

axios.post(apiUrl, form, {
  headers: {
    ...form.getHeaders(),
    'x-api-key': apiKey
  }
})
.then(res => {
  console.log(res.data);
})
.catch(err => {
  console.error(err.response ? err.response.data : err);
});

Licenses


Terms of Service

This hosted service is provided by UrbanLabs LLC and is provided "as is" without any warranty.

Privacy Policy

This service does not collect any personal data. It is provided by UrbanLabs LLC and is provided "as is" without any warranty.

Feedback

Please provide feedback via GitHub Issues.

Request an API Key

Already have a key? Use it in the x-api-key header for higher limits.