Data Handling
This skill communicates with the following external services:
- EVE Online ESI API (
esi.evetech.net) — all character and universe data queries
- EVE SSO (
login.eveonline.com) — OAuth2 authentication and token refresh
- zKillboard API (
zkillboard.com/api/) — optional, for PVP threat assessment data (public, no auth required)
- Telegram Bot API — optional, user-configured via
TELEGRAM_BOT_TOKEN for alert notifications
- Discord Webhooks — optional, user-configured via
DISCORD_WEBHOOK_URL for alert notifications
No character data is sent to third-party servers beyond the above. Telegram/Discord only transmit alerts defined by the user.
EVE Online ESI
The ESI (EVE Swagger Interface) is the official REST API for EVE Online third-party development.
Skill Location
All scripts live at: ~/.openclaw/workspace/skills/eve-esi/scripts/
Always use full paths when calling scripts:
SKILL=~/.openclaw/workspace/skills/eve-esi
Authentication
Tokens are stored in ~/.openclaw/eve-tokens.json (created by auth_flow.py, chmod 600).
All scripts (get_token.py, esi_query.py) read from this file directly — no env vars are required for normal operation.
First-time setup (once per character):
# 1. Set up SSH tunnel on your local PC:
# ssh -L 8080:127.0.0.1:8080 user@your-server -N
# 2. Run auth flow on server (pass Client ID directly):
python3 ~/.openclaw/workspace/skills/eve-esi/scripts/auth_flow.py --client-id <YOUR_CLIENT_ID> --char-name main
# 3. Open the shown URL in browser, log in with EVE account
Get a fresh access token (tokens expire after ~20min, refresh is automatic):
TOKEN=$(python3 ~/.openclaw/workspace/skills/eve-esi/scripts/get_token.py --char main)
List authenticated characters:
python3 ~/.openclaw/workspace/skills/eve-esi/scripts/get_token.py --list
For full OAuth2/PKCE details: see references/authentication.md.
Public endpoints (no auth)
# Character public info
curl -s "https://esi.evetech.net/latest/characters/2114794365/" | python -m json.tool
# Portrait URLs
curl -s "https://esi.evetech.net/latest/characters/2114794365/portrait/"
# Corporation history
curl -s "https://esi.evetech.net/latest/characters/2114794365/corporationhistory/"
# Bulk affiliation lookup
curl -s -X POST "https://esi.evetech.net/latest/characters/affiliation/" \
-H "Content-Type: application/json" \
-d '[2114794365, 95538921]'
Character info (authenticated)
TOKEN="<your_access_token>"
CHAR_ID="<your_character_id>"
# Online status (scope: esi-location.read_online.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/online/"
Wallet
# Balance (scope: esi-wallet.read_character_wallet.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/wallet/"
# Journal (paginated)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/wallet/journal/?page=1"
# Transactions
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/wallet/transactions/"
Assets
# All assets (paginated; scope: esi-assets.read_assets.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/assets/?page=1"
# Resolve item locations
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[1234567890, 9876543210]' \
"https://esi.evetech.net/latest/characters/$CHAR_ID/assets/locations/"
# Resolve item names
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[1234567890]' \
"https://esi.evetech.net/latest/characters/$CHAR_ID/assets/names/"
Skills
# All trained skills + total SP (scope: esi-skills.read_skills.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/skills/"
# Skill queue (scope: esi-skills.read_skillqueue.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/skillqueue/"
# Attributes (intelligence, memory, etc.)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/attributes/"
Location and ship
# Current location (scope: esi-location.read_location.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/location/"
# Current ship (scope: esi-location.read_ship_type.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/ship/"
Clones and implants
# Jump clones + home station (scope: esi-clones.read_clones.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/clones/"
# Active implants (scope: esi-clones.read_implants.v1)
curl -s -H "Authorization: Bearer $TOKEN" \
"https://esi.evetech.net/latest/characters/$CHAR_ID/implants/"
More endpoints
For contracts, fittings, mail, industry, killmails, market orders, mining, planetary interaction, loyalty points, notifications, blueprints, standings, and all other character endpoints, see references/endpoints.md.
Dashboard Config
The skill supports a modular dashboard config for alerts, reports, and market tracking. Each user defines what they need in a JSON config file.
Features
| Module | Description |
|---|
| Alerts | Real-time polling for war decs, structure attacks, skill completions, wallet changes, industry jobs, PI extractors, killmails, contracts, clone jumps, mail |
| Reports | Cron-scheduled summaries: net worth, skill queue, industry, market orders, wallet, assets |
| Market | Price tracking with absolute thresholds and trend detection |
Security
Tokens should not be stored in plain text. Use environment variable references:
{
"token": "$ENV:EVE_TOKEN_MAIN",
"refresh_token": "$ENV:EVE_REFRESH_MAIN"
}
The config file should live outside the workspace (e.g. ~/.openclaw/eve-dashboard-config.json).
Validate a config
python scripts/validate_config.py path/to/config.json
# Show example config
python scripts/validate_config.py --example
# Show JSON schema
python scripts/validate_config.py --schema
Using the query script
SKILL=~/.openclaw/workspace/skills/eve-esi
# Replace 'main' with your --char-name if you authenticated under a different name.
TOKEN=$(python3 $SKILL/scripts/get_token.py --char main)
# get_token.py --char-id prints just the character ID for the named character.
CHAR_ID=$(python3 $SKILL/scripts/get_token.py --char main --char-id 2>/dev/null) || \
CHAR_ID=$(python3 -c "import json, os, pathlib; p = pathlib.Path(os.environ.get('OPENCLAW_STATE_DIR', os.path.expanduser('~/.openclaw'))) / 'eve-tokens.json'; d = json.loads(p.read_text(encoding='utf-8')); chars = d.get('characters', {}); char = chars.get('main') or next(iter(chars.values()), None); print(char['character_id'] if char else '')")
# Simple query
python3 $SKILL/scripts/esi_query.py --token "$TOKEN" --endpoint "/characters/$CHAR_ID/wallet/" --pretty
# Fetch all pages of assets
python3 $SKILL/scripts/esi_query.py --token "$TOKEN" --endpoint "/characters/$CHAR_ID/assets/" --pages --pretty
# POST request (e.g. asset names)
python3 $SKILL/scripts/esi_query.py --token "$TOKEN" --endpoint "/characters/$CHAR_ID/assets/names/" \
--method POST --body '[1234567890]' --pretty
Best practices
- Caching: respect the
Expires header; do not poll before it expires.
- Error limits: monitor
X-ESI-Error-Limit-Remain; back off when low.
- User-Agent: always set a descriptive User-Agent with contact info.
- Rate limits: some endpoints (mail, contracts) have internal rate limits returning HTTP 520.
- Pagination: check the
X-Pages response header; iterate with ?page=N.
- Versioning: use
/latest/ for current stable routes. /dev/ may change without notice.
Threat Assessment & Route Planning
The skill provides threat intelligence for PI systems in low/null-sec space. Data sources: ESI (kills, jumps, FW, incursions) and zKillboard (PVP activity).
ESI Threat Endpoints
SKILL=~/.openclaw/workspace/skills/eve-esi
# System kills (last hour) — all or filtered
python3 $SKILL/scripts/esi_query.py --action system_kills --pretty
python3 $SKILL/scripts/esi_query.py --action system_kills --system-ids 30002537,30045337 --pretty
# System jump traffic (last hour)
python3 $SKILL/scripts/esi_query.py --action system_jumps --system-ids 30045337 --pretty
# System info (name, security status)
python3 $SKILL/scripts/esi_query.py --action system_info --system-id 30002537 --pretty
# Route planning (flags: secure, shortest, insecure)
python3 $SKILL/scripts/esi_query.py --action route_plan --origin 30000142 --destination 30002537 --route-flag secure --pretty
# Character location (requires auth)
TOKEN=$(python3 $SKILL/scripts/get_token.py --char main)
python3 $SKILL/scripts/esi_query.py --action character_location --token "$TOKEN" --character-id $CHAR_ID --pretty
# Faction warfare systems
python3 $SKILL/scripts/esi_query.py --action fw_systems --pretty
# Active incursions
python3 $SKILL/scripts/esi_query.py --action incursions --pretty
Threat Assessment Scripts (Workspace)
Hinweis: Die Workspace-Skripte (threat_query.py, cache_threat_data.py, cache_market_prices.py) sind Referenz-Beschreibungen und müssen erst im Agent-Workspace erstellt werden, bevor sie genutzt werden können.
These scripts live in ~/.openclaw/workspace/scripts/ (not in the skill repo):
# Threat level for specific systems
python3 ~/.openclaw/workspace/scripts/threat_query.py --action threat_assessment --system-ids 30002537,30045337
# Threat for all PI systems across all characters
python3 ~/.openclaw/workspace/scripts/threat_query.py --action threat_assessment_pi
# Route with per-system threat annotation
python3 ~/.openclaw/workspace/scripts/threat_query.py --action route_annotated --origin 30000142 --destination 30002537
# Route from character's current location
python3 ~/.openclaw/workspace/scripts/threat_query.py --action route_annotated --character main --destination 30045337
# Full PI + Threat morning briefing
python3 ~/.openclaw/workspace/scripts/threat_query.py --action pi_briefing
Threat Levels
| Level | Score | Meaning |
|---|
low | 0-15 | Normaler PI-Betrieb |
medium | 15-40 | Schnell rein, schnell raus |
high | 40-80 | Nur mit Scout/Cloak |
critical | 80+ | NICHT reinfliegen |
Threat Cache
Threat data is cached in Redis (30min TTL for ESI, 1h for zKillboard). The cache is updated every 30 minutes via cron:
# Update cache manually
python3 ~/.openclaw/workspace/scripts/cache_threat_data.py
# Show cached threat data
python3 ~/.openclaw/workspace/scripts/cache_threat_data.py --check
Resolving type IDs
ESI returns numeric type IDs (e.g. for ships, items, skills). Resolve names via:
# Single type
curl -s "https://esi.evetech.net/latest/universe/types/587/"
# Bulk names (up to 1000 IDs)
curl -s -X POST "https://esi.evetech.net/latest/universe/names/" \
-H "Content-Type: application/json" \
-d '[587, 638, 11393]'