All methods are async and belong to EveOnlineClient. Public endpoints only need a session; authenticated endpoints require auth.
Get the current Tranquility server status.
status = await client.async_get_server_status()Returns: ServerStatus
| Field | Type | Description |
|---|---|---|
players |
int |
Players currently online |
server_version |
str |
Server build version |
start_time |
datetime |
When the server last started |
vip |
bool | None |
VIP mode active |
Get public information about any character.
char = await client.async_get_character_public(2117905894)
print(char.name, char.corporation_id)Returns: CharacterPublicInfo
| Field | Type | Description |
|---|---|---|
character_id |
int |
EVE character ID |
name |
str |
Character name |
corporation_id |
int |
Current corporation |
birthday |
datetime |
Character creation date |
gender |
str |
"male" or "female" |
race_id |
int |
Race identifier |
bloodline_id |
int |
Bloodline identifier |
ancestry_id |
int | None |
Ancestry identifier |
alliance_id |
int | None |
Alliance, if any |
security_status |
float | None |
Security standing |
Get portrait image URLs for a character.
portrait = await client.async_get_character_portrait(2117905894)
print(portrait.px256x256) # URL to 256x256 imageReturns: CharacterPortrait
| Field | Type | Description |
|---|---|---|
px64x64 |
str | None |
64×64 portrait URL |
px128x128 |
str | None |
128×128 portrait URL |
px256x256 |
str | None |
256×256 portrait URL |
px512x512 |
str | None |
512×512 portrait URL |
Get public information about a corporation.
corp = await client.async_get_corporation_public(98553333)
print(corp.name, corp.ticker, corp.member_count)Returns: CorporationPublicInfo
| Field | Type | Description |
|---|---|---|
corporation_id |
int |
Corporation ID |
name |
str |
Corporation name |
ticker |
str |
Ticker symbol |
member_count |
int |
Number of members |
ceo_id |
int |
CEO character ID |
tax_rate |
float |
Tax rate (0.0–1.0) |
alliance_id |
int | None |
Alliance, if any |
date_founded |
datetime | None |
Founding date |
Resolve a list of EVE entity IDs to names and categories.
names = await client.async_resolve_names([2117905894, 98553333, 30000142])
for n in names:
print(f"{n.name} ({n.category})")
# → Jita (solar_system), CCP (corporation), ...Returns: list[UniverseName]
| Field | Type | Description |
|---|---|---|
id |
int |
Entity ID |
name |
str |
Display name |
category |
str |
"character", "corporation", "solar_system", etc. |
Returns an empty list when called with an empty ids list.
All authenticated endpoints require EveOnlineClient(auth=...). See Authentication for scope details.
Some ESI endpoints return data across multiple pages. The client handles this automatically:
- It fetches page 1 and reads the
X-Pagesresponse header to determine the total page count. - It sequentially fetches any remaining pages.
- All pages are merged into a single list before returning.
No extra code is needed — just call the method as usual.
Endpoints with automatic pagination:
| Method | Max items per page |
|---|---|
async_get_wallet_journal() |
50 |
async_get_contacts() |
500 |
async_get_killmails() |
50 |
Endpoints that use automatic pagination are also marked with all pages fetched automatically in their return type description below.
Scope: esi-location.read_online.v1
status = await client.async_get_character_online(character_id)
if status.online:
print(f"Online since {status.last_login}")Returns: CharacterOnlineStatus
| Field | Type | Description |
|---|---|---|
online |
bool |
Currently online |
last_login |
datetime | None |
Last login time |
last_logout |
datetime | None |
Last logout time |
logins |
int | None |
Total login count |
Scope: esi-location.read_location.v1
loc = await client.async_get_character_location(character_id)
print(f"System: {loc.solar_system_id}")
if loc.station_id:
print(f"Docked at station {loc.station_id}")Returns: CharacterLocation
| Field | Type | Description |
|---|---|---|
solar_system_id |
int |
Current solar system |
station_id |
int | None |
NPC station, if docked |
structure_id |
int | None |
Player structure, if docked |
Scope: esi-location.read_ship_type.v1
ship = await client.async_get_character_ship(character_id)
print(f"In: {ship.ship_name} (type {ship.ship_type_id})")Returns: CharacterShip
| Field | Type | Description |
|---|---|---|
ship_type_id |
int |
Ship type ID |
ship_item_id |
int |
Unique item ID of this ship |
ship_name |
str |
Player-assigned name |
Scope: esi-wallet.read_character_wallet.v1
wallet = await client.async_get_wallet_balance(character_id)
print(f"{wallet.balance:,.2f} ISK")Returns: WalletBalance
| Field | Type | Description |
|---|---|---|
balance |
float |
ISK balance |
Scope: esi-skills.read_skills.v1
skills = await client.async_get_skills(character_id)
print(f"{skills.total_sp:,} SP total, {skills.unallocated_sp:,} unallocated")Returns: CharacterSkillsSummary
| Field | Type | Description |
|---|---|---|
total_sp |
int |
Total skill points |
unallocated_sp |
int |
Free/unallocated skill points |
Scope: esi-skills.read_skillqueue.v1
queue = await client.async_get_skill_queue(character_id)
if queue:
current = queue[0] # position 0 is actively training
print(f"Training skill {current.skill_id} to level {current.finished_level}")
print(f"Finishes: {current.finish_date}")Returns: list[SkillQueueEntry], ordered by queue_position
| Field | Type | Description |
|---|---|---|
skill_id |
int |
Skill type ID |
queue_position |
int |
Position in queue (0 = active) |
finished_level |
int |
Level being trained to |
start_date |
datetime | None |
Training start time |
finish_date |
datetime | None |
Estimated finish time |
level_end_sp |
int | None |
SP required to complete level |
Scope: esi-mail.read_mail.v1
mail = await client.async_get_mail_labels(character_id)
print(f"{mail.total_unread_count} unread messages")Returns: MailLabelsSummary
| Field | Type | Description |
|---|---|---|
total_unread_count |
int |
Total unread mail count |
Scope: esi-industry.read_character_jobs.v1
jobs = await client.async_get_industry_jobs(character_id)
active = [j for j in jobs if j.status == "active"]
print(f"{len(active)} active jobs")Returns: list[IndustryJob]
| Field | Type | Description |
|---|---|---|
job_id |
int |
Job ID |
activity_id |
int |
Activity (1=manufacturing, 3=TE research, etc.) |
status |
str |
"active", "delivered", "cancelled", etc. |
start_date |
datetime |
Job start time |
end_date |
datetime |
Scheduled completion time |
runs |
int |
Number of runs |
cost |
float | None |
Installation cost in ISK |
Pass include_completed=True to also return delivered/cancelled jobs.
Scope: esi-markets.read_character_orders.v1
orders = await client.async_get_market_orders(character_id)
buy_orders = [o for o in orders if o.is_buy_order]
sell_orders = [o for o in orders if not o.is_buy_order]
print(f"{len(buy_orders)} buy / {len(sell_orders)} sell orders")Returns: list[MarketOrder]
| Field | Type | Description |
|---|---|---|
order_id |
int |
Order ID |
type_id |
int |
Item type ID |
is_buy_order |
bool |
True for buy, False for sell |
price |
float |
Price per unit in ISK |
volume_remain |
int |
Units remaining |
volume_total |
int |
Original volume |
region_id |
int |
Region |
issued |
datetime |
Order creation/update time |
Scope: esi-characters.read_fatigue.v1
fatigue = await client.async_get_jump_fatigue(character_id)
if fatigue.jump_fatigue_expire_date:
print(f"Fatigue expires: {fatigue.jump_fatigue_expire_date}")Returns: JumpFatigue
| Field | Type | Description |
|---|---|---|
jump_fatigue_expire_date |
datetime | None |
When fatigue expires |
last_jump_date |
datetime | None |
Last jump timestamp |
last_update_date |
datetime | None |
Data update timestamp |
Scope: esi-characters.read_notifications.v1
notifications = await client.async_get_notifications(character_id)
unread = [n for n in notifications if not n.is_read]
print(f"{len(unread)} unread notifications")Returns: list[CharacterNotification]
| Field | Type | Description |
|---|---|---|
notification_id |
int |
Notification ID |
sender_id |
int |
Sender entity ID |
sender_type |
str |
"character", "corporation", etc. |
type |
str |
Notification type (e.g. "StructureUnderAttack") |
timestamp |
datetime |
When the notification was sent |
is_read |
bool | None |
Whether it has been read |
text |
str | None |
YAML-encoded notification body |
Scope: esi-clones.read_clones.v1
clones = await client.async_get_clones(character_id)
print(f"Home: {clones.home_location.location_id}")
print(f"{len(clones.jump_clones)} jump clones")Returns: CharacterClones
| Field | Type | Description |
|---|---|---|
home_location |
CloneHomeLocation | None |
Medical clone station/structure |
jump_clones |
tuple[JumpClone, ...] |
List of jump clones |
last_clone_jump_date |
datetime | None |
Last clone jump |
last_station_change_date |
datetime | None |
Last home station change |
CloneHomeLocation fields: location_id (int), location_type (str).
JumpClone fields: jump_clone_id (int), location_id (int), location_type (str), implants (tuple[int, ...]), name (str | None).
Scope: esi-clones.read_implants.v1
implants = await client.async_get_implants(character_id)
print(f"{len(implants)} active implants: {implants}")Returns: tuple[int, ...] — type IDs of active implants.
Scope: esi-wallet.read_character_wallet.v1
journal = await client.async_get_wallet_journal(character_id)
for entry in journal[:5]:
print(f"{entry.date}: {entry.ref_type} {entry.amount:+,.2f} ISK")Returns: list[WalletJournalEntry] — all pages fetched automatically
ESI returns up to 50 entries per page. The client fetches all pages and returns the combined result.
| Field | Type | Description |
|---|---|---|
id |
int |
Journal entry ID |
date |
datetime |
Transaction time |
ref_type |
str |
Transaction type (e.g. "bounty_prizes") |
description |
str |
Human-readable description |
amount |
float | None |
ISK amount (+income / −expense) |
balance |
float | None |
Balance after transaction |
first_party_id |
int | None |
First party ID |
second_party_id |
int | None |
Second party ID |
reason |
str | None |
Additional reason text |
Scope: esi-characters.read_contacts.v1
contacts = await client.async_get_contacts(character_id)
friends = [c for c in contacts if c.standing > 0]
print(f"{len(friends)} friendly contacts")Returns: list[CharacterContact] — all pages fetched automatically
ESI returns up to 500 contacts per page. The client fetches all pages and returns the combined result.
| Field | Type | Description |
|---|---|---|
contact_id |
int |
Contact entity ID |
contact_type |
str |
"character", "corporation", "alliance", "faction" |
standing |
float |
Standing (-10.0 to +10.0) |
is_blocked |
bool | None |
Whether blocked |
is_watched |
bool | None |
Whether on watch list |
label_ids |
tuple[int, ...] | None |
Assigned label IDs |
Scope: esi-calendar.read_calendar_events.v1
events = await client.async_get_calendar(character_id)
for event in events:
print(f"{event.event_date}: {event.title}")Returns: list[CalendarEvent]
| Field | Type | Description |
|---|---|---|
event_id |
int |
Event ID |
event_date |
datetime |
Event start time |
title |
str |
Event title |
importance |
int | None |
0 = normal, 1 = important |
event_response |
str | None |
"accepted", "declined", "tentative", "not_responded" |
Scope: esi-characters.read_loyalty.v1
lp = await client.async_get_loyalty_points(character_id)
for entry in lp:
print(f"Corp {entry.corporation_id}: {entry.loyalty_points:,} LP")Returns: list[LoyaltyPoints]
| Field | Type | Description |
|---|---|---|
corporation_id |
int |
Corporation ID |
loyalty_points |
int |
LP accumulated |
Scope: esi-killmails.read_killmails.v1
killmails = await client.async_get_killmails(character_id)
for km in killmails:
print(f"Killmail {km.killmail_id} — hash {km.killmail_hash}")Returns: list[CharacterKillmail] — all pages fetched automatically
ESI returns up to 50 entries per page. The client fetches all pages and returns the combined result.
| Field | Type | Description |
|---|---|---|
killmail_id |
int |
Unique killmail identifier |
killmail_hash |
str |
Hash required to fetch the full killmail detail |
Discards all cached responses (both TTL and ETag layers) so the next request to each endpoint fetches fresh data from ESI.
client.clear_etag_cache()Useful when you need up-to-date data immediately, regardless of the remaining cache lifetime.
The client uses two automatic caching layers to reduce ESI traffic. Caching is active when a GET endpoint returns an ETag header — which is true for all endpoints documented here.
When ESI returns an Expires header, the client stores the expiry timestamp alongside the cached data. A repeat call before that time returns the cached result immediately without making any HTTP request.
# First call — real HTTP request, Expires stored
status = await client.async_get_server_status()
# Second call within TTL window — no HTTP request, cache returned instantly
status = await client.async_get_server_status()ESI cache durations vary by endpoint. Common values:
| Endpoint | Cache duration |
|---|---|
/status/ |
30 seconds |
/characters/{id}/online/ |
60 seconds |
/characters/{id}/wallet/ |
120 seconds |
/characters/{id}/skills/ |
120 seconds |
/characters/{id}/industry/jobs/ |
300 seconds |
/characters/{id}/orders/ |
1200 seconds |
/universe/names/ |
3600 seconds |
Once the TTL has expired (or if no Expires header was present), the client sends the stored ETag value in an If-None-Match request header. If the data has not changed since it was last fetched, ESI responds with 304 Not Modified and the client returns the previously cached data without downloading a response body.
Both layers are fully transparent — no configuration is needed. Use clear_etag_cache() to bypass them when fresh data is required.