Skip to content
JeffreyMichelPublic

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Trailgate

Checks Recreation.gov daily for permit availability — across one or more facilities — on your available dates and emails you when spots open up.

How it works

A GitHub Action runs daily in the early morning Pacific time (twice, at ~6 and ~7 AM, to cover the PST/PDT shift). It reads your facilities, dates, and target trailheads from config.yml, queries the Recreation.gov API, and sends you an email with a direct booking link if any permits are available. If every request fails (e.g. recreation.gov blocks the checker), the job exits non-zero and emails you a failure alert.

Setup

1. Configure your facilities, dates, and trailheads

Edit config.yml. Each entry under facilities is a recreation.gov facility with its own facility_id, dates, and trailheads:

facilities:
  - name: "Central Cascades Wilderness"
    facility_id: "300009"
    dates:
      - "2026-07-04"
      - "2026-07-12"
    trailheads:
      - name: "Green Lakes / Soda Creek"
        tour_id: "2003"
        url: "https://www.recreation.gov/ticket/300009/ticket/2003"
      - name: "Devils Lake / South Sister"
        tour_id: "10088687"
        url: "https://www.recreation.gov/ticket/300009/ticket/10088687"

  - name: "Enchantment Permit Area"
    facility_id: "233273"
    dates:
      - "2026-08-01"
    trailheads:
      - name: "Snow Lakes"
        tour_id: "4675311"
        url: "https://www.recreation.gov/ticket/233273/ticket/4675311"

The repo ships with the Central Cascades facility and all its trailheads pre-populated — trim or add as needed.

Adding a facility

Find the facility on Recreation.gov. Its id is the number in the URL (.../ticket/300009/... → "300009"). Add a new entry under facilities with that facility_id, the dates you want to check, and its trailheads.

Scoping a trailhead to specific dates

By default every trailhead is checked against its facility's dates. To watch a trailhead only on certain dates, give it its own dates list:

    trailheads:
      - name: "Devils Lake / South Sister"
        tour_id: "10088687"
        url: "https://www.recreation.gov/ticket/300009/ticket/10088687"
        dates:               # overrides the facility dates for this trailhead only
          - "2026-07-04"

Fields and defaults

Field Level Required Default
facility_id facility Yes —
name facility No falls back to facility_id in log output
dates facility No* empty — see note below
trailheads facility Yes —
name, tour_id, url trailhead Yes —
dates trailhead No inherits the facility's dates

* A facility's dates is only optional if every trailhead under it defines its own dates. If a facility has no dates and a trailhead doesn't either, that trailhead is checked against an empty date list — i.e. nothing happens for it (no API call, no error). Always set dates at one level or the other.

Overnight permits

facilities covers day-use permits (recreation.gov's ticket API). Overnight permits use a different API and go under a separate overnight_permits section, keyed by permit_id and division_id instead of facility_id and tour_id:

overnight_permits:
  - name: "Central Cascades Wilderness Overnight"
    permit_id: "4675311"          # from .../permits/4675311
    dates:
      - "2026-07-04"
    trailheads:
      - name: "Devils Lake / South Sister (overnight)"
        division_id: "467531103"  # from the permit's availability grid
        url: "https://www.recreation.gov/permits/4675311/registration/detailed-availability"
      - name: "Green Lake / Soda Creek (overnight)"
        division_id: "467531108"
        url: "https://www.recreation.gov/permits/4675311/registration/detailed-availability"

Both sections are optional and can be used together; hits from either land in the same email. dates and per-trailhead dates overrides work identically. Give day-use and overnight entries distinct names — a name reused across (or within) sections merges their results and logs a warning.

recreation.gov has no per-division deep link, so url is the same for every division under a permit: use .../permits/<permit_id>/registration/detailed-availability. The email appends ?date=<date>, landing you on that date's availability grid where you click the division's cell.

Field Level Required Default
permit_id permit Yes —
name permit No falls back to permit_id in log output
dates permit No* empty — same rule as facilities
trailheads permit Yes —
name, division_id, url trailhead Yes —
dates trailhead No inherits the permit's dates

2. Add GitHub Secrets

In your repo go to Settings → Secrets and variables → Actions and add:

Secret Required Value
GMAIL_ADDRESS Yes Your Gmail address (used to send the mail)
GMAIL_APP_PASSWORD Yes 16-character app password from myaccount.google.com/apppasswords
NOTIFY_EMAIL No Where to send alerts. Defaults to GMAIL_ADDRESS if unset.

3. Trigger manually to test

Go to Actions → Check Permit Availability → Run workflow to run it immediately and confirm the email works before waiting for the daily schedule.

Adding trailheads

Find the trailhead on Recreation.gov. The URL will look like:

https://www.recreation.gov/ticket/{facility_id}/ticket/{tour_id}

Copy the tour_id from the URL and add a new entry under the facility's trailheads list in config.yml.

Running locally

pip install -r requirements.txt
GMAIL_ADDRESS=you@gmail.com GMAIL_APP_PASSWORD=xxxx NOTIFY_EMAIL=you@gmail.com python check_permits.py

Tests

pip install -r requirements-dev.txt
python -m pytest tests/ -v

Linting

This repo uses ruff and pre-commit. After installing dev dependencies:

ruff check .          # lint
ruff format .         # format
pre-commit install    # run the hooks automatically on every commit

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages