Skip to main content

Output contract

Stable shape for machine-readable responses (--format json / --format yaml). Table output is shown by default and is not part of this contract.

Envelope

{
"meta": {
"request_id": "req_01j0zdq8q6k7y8d6w2g0y9p4m7",
"generated_at": "2026-02-19T20:45:09Z",
"profile": "default",
"locale": "en-FI"
},
"data": {},
"warnings": []
}

YAML uses the same fields. warnings[] carries non-fatal upstream issues (fallback used, address inferred from account, etc.). data can be null on errors.

Errors

{
"meta": { },
"data": null,
"warnings": [],
"error": {
"code": "WOLT_AUTH_REQUIRED",
"message": "Authentication is required. Run \"wolt login\" first.",
"details": { }
}
}

Stable error codes:

CodeMeaning
WOLT_AUTH_REQUIREDThe endpoint requires a logged-in session.
WOLT_INVALID_ARGUMENTFlag combination is invalid (e.g. --lat without --lon).
WOLT_UPSTREAM_ERRORUpstream returned a non-success status. --verbose adds the URL and status code to the message.
WOLT_STATS_BUNDLE_UNAVAILABLEwolt stats could not fetch a usable dashboard bundle (GitHub unreachable, missing release asset, or checksum mismatch) and no cached bundle is on disk.
WOLT_STATS_ENV_ERRORwolt stats environment issue: port busy, stats dir not writable, missing user email, sync failure.

Conventions

  • IDs are strings (venue_id, item_id, basket_id, purchase_id).
  • Money: amount in minor units (cents) plus an optional formatted_amount for display.
  • Time: ISO-8601 UTC for CLI-generated stamps; upstream-provided strings are passed through verbatim alongside parsed equivalents when available.
  • Booleans are never serialised as strings.

Schemas

wolt status — Status

authenticated: bool
user_id: string
country: string
session_expires_at: string|null (ISO-8601 UTC)
wolt_plus_subscriber: bool
token_preview?: string (--verbose only)
cookie_count?: int (--verbose only)

wolt account — ProfileSummary

user_id: string
name: string
email_masked: string
phone_masked: string
country: string

wolt account addresses — AddressList

addresses[]: { address_id, label, street, is_default }
profile_default_address_id: string
address_id: string
links: { address_link, entrance_link, coordinates_link }

wolt account payments — PaymentMethodList

methods[]: { method_id, type, label, is_default, is_available_for_checkout }

wolt account orders — OrderHistoryList

orders[]: {
purchase_id, received_at, status, venue_name,
total_amount, is_active, items_summary,
payment_time_ts, main_image, main_image_blurhash
}
count: int
next_page_token?: string
status_filter?: string

wolt account order <id> — OrderHistoryDetail

order_id, status, currency
venue: { id, name, address, phone, country, product_line }
totals: { items, delivery, service_fee, subtotal, credits, tokens, total }
(each value is { amount, formatted_amount })
items[]: { id, name, count, price, line_total, options }
payments[]: { name, amount, method_type, method_id, provider, payment_time }
delivery: { alias, address, city, comment }

# Optional
order_number, creation_time, delivery_time, delivery_method
discounts[]: { title, amount }
surcharges[]: { title, amount }

wolt venues — VenueSearchResult

query?: string
total: int
items[]: {
venue_id, slug, name, address,
tagline, top_offer,
rating, delivery_estimate, delivery_fee,
price_range, price_range_scale,
promotions[], badges[], menu_highlights[], wolt_plus
}

# Pagination
count, offset, limit, total_pages, next_offset, page

tagline is the venue's marketing one-liner (short_description / short_description_v2.value from upstream). top_offer is the most prominent promo text — preference order: discount-variant promos, then any promo (excluding Wolt+ membership labels). Both come from the same front-page payload, no extra HTTP. With --enrich, promotions is backfilled with dynamic campaign banners.

badges[]: { icon, variant, text } is sourced from upstream badges_v2 and surfaces newer icon-bearing badges (wolt-plus, coupon-fill, bike, …). Empty array when upstream omits the field. The table renderer prefixes the venue cell with single-rune glyphs derived from icon; set WOLT_BADGES_PLAIN=1 to fall back to bracketed text (e.g. [Wolt+]).

menu_highlights[]: { name, formatted_price } is sourced from upstream venue_preview_items and lists flagship dishes for sponsored / featured rows. Empty array when upstream omits the field. The venues table hides this column by default — pass --show-highlights to surface it.

wolt feed — DiscoveryFeed

city: string
wolt_plus_only: bool
sections[]: {
name: string # internal name, e.g. "popular-restaurants"
title: string # display title, e.g. "Popular near you"
kind: "venues" | "brands"
items[]: { # kind = "venues"
venue_id, slug, name,
tagline, top_offer,
rating, delivery_estimate, delivery_fee,
price_range, price_range_scale,
promotions[], badges[], menu_highlights[], wolt_plus
}
brands[]: { name, slug } # kind = "brands"
}

Venue sections have the same row shape as venues, including the additive badges[] and menu_highlights[] fields described above. Sections preserve the upstream ordering you see on wolt.com. The feed table renders the Highlights column by default (pass --show-highlights=false to hide).

kind = "brands" covers carousels whose entries lack a venue block — brand-curated lists ("Popular stores"), restaurant-category tiles, or hero banners. items[] is always present and empty for that kind; brands[].slug is the upstream link target (often a curated list ID like woltmarket-popular-brands:helsinki). The table renders these as a single one-line summary; --query matches against brands[].name as well as venue rows.

wolt top — TopVenues

venues[]: {
venue_id, slug, name,
tagline, top_offer,
rating, delivery_estimate, delivery_fee,
price_range, price_range_scale,
promotions[], badges[], menu_highlights[], wolt_plus
}

# Pagination
count, offset, limit, total_pages, next_offset, page

Same row shape as wolt venues. The flattened slice is bounded by the combined feed payload and the --limit (default 10) before deduplication by venue_id. Brand carousels are excluded.

wolt venues categories — CategoryList

categories[]: { id, name, slug }

# Pagination
count, total, offset, limit, total_pages, next_offset, page

wolt venue <slug> — VenueDetail

venue_id, slug, name, address, currency
rating, delivery_methods, order_minimum

If the restaurant detail endpoint is unavailable, the CLI falls back to the static venue payload and adds a warning.

wolt venue categories <slug> — VenueCategoryList

venue_id: string
loading_strategy: string
categories[]: { id, slug, name, parent_slug, level, leaf, item_refs_count }

# Pagination
count, total, offset, limit, total_pages, next_offset, page

wolt venue menu <slug> (without --query) — VenueMenu

venue_id, wolt_plus
categories[]
items[]: { item_id, name, base_price, discounts }

# Optional
items[].original_price (campaign-adjusted)
items[].option_group_ids (--include-options)
count, offset, limit, total_pages, next_offset, page, sort

wolt venue menu <slug> --query <text> — VenueItemSearchResult

venue_id, venue_slug, query, total
items[]: { item_id, name, category, base_price, discounts, is_sold_out }

# Optional
items[].original_price (upstream pre-discount amount)
items[].option_group_ids (--include-options)
count, offset, limit, total_pages, next_offset, page, sort

When upstream omits the currency, it is normalized from venue metadata. When original_price is present without a promo label, the CLI derives a synthetic discount (e.g. 21% off).

wolt venue hours <slug> — VenueHours

venue_id: string
timezone: string
opening_windows[]

wolt venue item <venue> <item-id> — ItemDetail

item_id, venue_id, name, description, price
option_groups[]
upsell_items[]

price.formatted_amount is normalized from venue metadata when upstream omits the currency. upsell_items[].price follows the same rule.

wolt cart — CartState

basket_id, venue_id, venue_name, venue_slug
selection, currency, total_items
lines[]: {
line_id, item_id, name, count,
options[], price, line_total
}
subtotal, fees, total

wolt cart add|remove|clear — CartMutationResult

mutation: "add" | "remove" | "clear"
total_items: int
total: { amount, formatted_amount }

# Per mutation
add: basket_id, venue_id, line_id, item_name, item_price, item_currency
remove: basket_id, venue_id, line_id, removed_count
clear: basket_ids[], cleared_baskets

wolt checkout — CheckoutPreview

basket_id, venue_id, venue_name, venue_slug
selection
payable_amount
checkout_rows[]
delivery_configs[]
offers
tip_config

Preview-only. The CLI never calls the order placement endpoint.

wolt stats — StatsLaunch

The envelope is emitted on startup, before the command blocks on the HTTP server. JSON / YAML consumers should expect a single envelope followed by the process continuing to run; the server stays up until SIGINT (exit code 130).

stats_dir: string absolute path of the install dir
bundle: {
version: string tag name, e.g. "v0.1.0"
source: "github-release" | "" where the bundle came from
downloaded: bool true if this run pulled it fresh
active_path: string absolute path to the extracted bundle
}
db_path: string absolute path to wolt-history.sqlite
email: string (omitted when --no-sync)
sync: { (omitted when --no-sync)
performed: bool
mode: "full" | "incremental"
pages_fetched, orders_scanned, details_fetched: int
inserted_orders, updated_orders: int
catalog_count, detail_count: int
reached_history_end: bool
duration_ms: int64
stop_reason: "known_purchase" | "checkpoint_reached" (incremental only, omitted on full scan)
}
server: {
url: "http://127.0.0.1:5173"
port: int
pid: int
}