CLI automation — scheduled data pipelines and ops workflows
How ops and data teams use the NTHMAP CLI to build scheduled pipelines, export datasets, and integrate into existing infrastructure.
The NTHMAP CLI is a single Python file that wraps the REST API. It's designed to be scriptable: JSON/CSV/TSV output, exit codes, pipe-friendly, environment-driven configuration. If you've ever written a bash script against a REST API, you'll feel at home in 30 seconds.
This article shows six automation patterns that teams have deployed on NTHMAP.
Pattern 1: Morning CSV export
Export yesterday's LNG carrier positions to a CSV for the morning desk meeting.
#!/bin/bash
# /opt/nthmap/morning-lng.sh
set -e
export NTHMAP_API_KEY=ntm_live_...
DATE=$(date +%Y-%m-%d)
OUTDIR=/var/nthmap/exports
nthmap vessels list \
--types "LNG Carrier" \
--format csv \
--fields mmsi,name,flag,dwt,lat,lng,load_pct,est_cargo_mt,destination,speed_knots \
> "$OUTDIR/lng-$DATE.csv"
# Upload to S3 for the team
aws s3 cp "$OUTDIR/lng-$DATE.csv" s3://desk-data/lng/$DATE.csv
# Generate a summary
COUNT=$(wc -l < "$OUTDIR/lng-$DATE.csv")
LOADED=$(nthmap vessels list --types "LNG Carrier" --min-load 80 --format json | jq length)
echo "LNG snapshot $DATE: $COUNT total, $LOADED loaded" | \
slack-notify "#lng-desk"
Cron it: 0 6 * * * /opt/nthmap/morning-lng.sh. Done.
Pattern 2: Portfolio exposure monitor
If you manage a portfolio of hulls (insurance, shipping, P&I), you want to know which ones are currently in high-risk zones. Run this every hour:
#!/bin/bash
# /opt/nthmap/check-exposure.sh
export NTHMAP_API_KEY=ntm_live_...
PORTFOLIO=/etc/nthmap/insured-mmsis.txt
# Define risk zones as bboxes
declare -A ZONES=(
["red-sea-south"]="41,10,50,16"
["hormuz"]="54,25,58,28"
["black-sea"]="28,41,42,47"
["gulf-of-guinea"]="-5,-5,10,5"
)
for zone in "${!ZONES[@]}"; do
# Get vessels in the zone
nthmap vessels list --bbox "${ZONES[$zone]}" --format json > "/tmp/zone-$zone.json"
# Intersect with our portfolio
jq --rawfile portfolio "$PORTFOLIO" '
[.[] | select(.mmsi as $m | $portfolio | split("\n") | index($m))]
' "/tmp/zone-$zone.json" > "/tmp/exposure-$zone.json"
COUNT=$(jq length "/tmp/exposure-$zone.json")
if [ "$COUNT" -gt 0 ]; then
echo "ALERT: $COUNT insured vessels in $zone" | \
mail -s "NTHMAP exposure alert: $zone" underwriting@firm.com
fi
done
This gives an underwriting team a live read on exposure to war-risk zones with no human effort.
Pattern 3: Data pipeline into BigQuery / Snowflake
For teams that want NTHMAP data in their existing warehouse:
#!/bin/bash
# /opt/nthmap/sync-to-bigquery.sh
export NTHMAP_API_KEY=ntm_live_...
DATE=$(date -u +%Y-%m-%d)
HOUR=$(date -u +%H)
# Snapshot all vessels
nthmap vessels list \
--format json \
| jq --arg snap "$DATE-$HOUR" '[.[] | . + {snapshot_time: $snap}]' \
> "/tmp/vessels-$DATE-$HOUR.json"
# Stream into BigQuery
bq load \
--source_format=NEWLINE_DELIMITED_JSON \
--autodetect \
dataset.vessels_snapshots \
"/tmp/vessels-$DATE-$HOUR.json"
# Do the same for events, infrastructure
for ds in events infrastructure; do
nthmap $ds list --format json > "/tmp/$ds-$DATE-$HOUR.json"
bq load --source_format=NEWLINE_DELIMITED_JSON \
dataset.${ds}_snapshots \
"/tmp/$ds-$DATE-$HOUR.json"
done
Run hourly from Airflow or Prefect. You now have a time-series of the global physical world in your warehouse.
Pattern 4: Event-triggered AI analysis
When a new conflict event appears, auto-run an AI flow analysis for the affected region.
#!/bin/bash
# /opt/nthmap/event-watcher.sh — runs every 10 minutes
export NTHMAP_API_KEY=ntm_live_...
STATE_FILE=/var/nthmap/last-event-ids
# Get current conflict events
nthmap events list --types conflict --format json | \
jq -r '.[] | .id' > /tmp/current-events.txt
# Find new events (in current but not in state file)
comm -23 <(sort -u /tmp/current-events.txt) <(sort -u "$STATE_FILE") > /tmp/new-events.txt
while read -r EVENT_ID; do
# Get event details
EVENT=$(nthmap events get $EVENT_ID --format json)
LAT=$(echo "$EVENT" | jq -r .lat)
LNG=$(echo "$EVENT" | jq -r .lng)
# Run AI flow analysis in a 500km box around it
BBOX="$(python -c "print(f'{$LNG-2.5},{$LAT-2.5},{$LNG+2.5},{$LAT+2.5}')")"
ANALYSIS=$(nthmap ai flow --bbox "$BBOX")
# Send to ops channel
echo "$EVENT\n\n$ANALYSIS" | slack-notify "#ops-alerts"
done < /tmp/new-events.txt
cp /tmp/current-events.txt "$STATE_FILE"
Pattern 5: Saved view as a scheduled query
Saved views in NTHMAP are user-defined combinations of filters + map state. The CLI can re-run a saved view as a query:
# Save a view in the web app, then run it from CLI
nthmap views run "Persian Gulf Watch" --format json > gulf-snapshot.json
# Or list all saved views
nthmap views list
For teams, standardize on a set of named views for recurring queries. You change the definition once in the web app, all the cron jobs pick up the new filters.
Pattern 6: CI/CD integration
If your product depends on NTHMAP data, integrate into your CI:
# .github/workflows/data-freshness.yml
name: NTHMAP data freshness check
on:
schedule:
- cron: '0 */4 * * *'
jobs:
check:
runs-on: ubuntu-latest
steps:
- run: |
curl -sSLo /usr/local/bin/nthmap https://nthmap.com/cli/nthmap.py
chmod +x /usr/local/bin/nthmap
- env:
NTHMAP_API_KEY: ${{ secrets.NTHMAP_API_KEY }}
run: |
COUNT=$(nthmap vessels list --format json | jq length)
if [ "$COUNT" -lt 100 ]; then
echo "::error::Vessel count suspiciously low: $COUNT"
exit 1
fi
echo "$COUNT vessels — data healthy"
Now if the NTHMAP data pipeline has a hiccup, your own CI catches it and alerts you before a customer does.
Tips
- Set
NTHMAP_API_KEYin systemd service files usingEnvironmentFile=/etc/nthmap/env, not hardcoded in scripts. - Use
--format json+jqfor anything non-trivial. CSV is for spreadsheets, JSON is for pipelines. - Add
--profile <name>to~/.nthmaprcif you use multiple environments (prod, staging, dev). - Log responses to
/var/log/nthmap/so you can debug pipeline failures after the fact. - Don't poll too aggressively. Most datasets update every 5-30 minutes server-side; polling every 60 seconds just burns rate limits.
Learn more
- CLI docs — full command reference
- API reference — underlying HTTP endpoints
- Authentication — API key best practices