# Vortex > Vortex tells a buying agent whether a store can actually deliver to its destination, and what the order really costs once it lands there. ## Why this exists - Product search is solved. Delivery is not. Every catalogue will happily return items the buyer can never receive. - Most storefronts serve one country. Measured on real stores: Allbirds and Gymshark publish shipping to exactly one destination, while Kith publishes 197. - The shelf price is the smallest part of a cross-border order. A US$120 item into Brazil lands near US$220 once import tax and state tax are applied. - Ask Vortex before you commit, and report what happened after. Reporting is free, and a claim the merchant's own feed contradicts is stored but never counted. ## Using it, with no human in the loop 1. `POST /v1/identity` with your wallet address and an EIP-191 signature. Free, no account, no human. You get a handle and a bearer token. 2. `GET /v1/find?need=&destination=` — one result per store, and only stores that can deliver there. 3. `GET /v1/feasibility?store=&destination=` when you already have a store in mind. 4. `GET /v1/landed?destination=&item_usd=` before you commit, because the shelf price is not the total. 5. `POST /v1/report` afterwards. Free, re-checked against the merchant's own feed, so a false claim about a competitor never counts. ## Where the answers come from - Shipping reach, currency and accepted cards, read from the `/meta.json` every storefront publishes about itself. - Live price and stock, from the public product feed, parsed into integer micro-USD so no rounding creeps into a comparison. - Price and stock history, appended on change since the day the collector started. This is what makes `history` able to say whether a price is good. - Import rules per destination, versioned with an effective date. Every landed cost names the rule it used. - Freight, from buying agents that reported what they were quoted. Vortex does not create carts on merchant sites to scrape rates. Nothing here is self-reported to Vortex by a merchant, and no ranking position is for sale. ## Prices | Operation | Price (USD) | What it does | | --- | --- | --- | | `capabilities` | free | Return the full machine-readable manifest of Vortex: every operation, its price in USD, its input schema and how to pay. Free. | | `identity.create` | free | Turn a wallet address into a permanent Vortex identity and an API token. Free, and grants a small trial credit. No signup, no email, no human. | | `whoami` | free | Your handle, wallet, balance and usage. Free. | | `credit.deposit` | free | Buy Vortex credit with USDC on Base over x402. One on-chain settlement, then every call is debited off-chain. | | `find` | 0.005000 | Search real storefronts for a product and get back only the ones that can ship to your destination, with live price and stock. Every other product index answers what matches the words; this one answers what matches the words and can be delivered. | | `feasibility` | 0.002000 | Everything Vortex knows about whether one storefront can serve one destination: its published shipping zones, the currency it charges in, the cards it takes, what buyers reported, and whether its reach changed recently. Returns a verdict, not just data. | | `landed` | 0.003000 | Item plus shipping plus import tax plus local tax, itemised, for a destination — and the name and effective date of the tax rule applied. A US$120 item into Brazil lands near US$220; the shelf price is not the number to budget against. | | `history` | 0.002000 | The recorded price and stock series for a product, where today sits against its own record, how often it has gone out of stock, and every change to where its store ships. | | `watch` | 0.005000 | Register standing interest in a product or a store: a price drop below your threshold, a return to stock, or a store that stops shipping to your destination. | | `report` | free | Tell Vortex how a purchase actually went. Free, and checked against the merchant's own feed before it counts — a claim the store contradicts is stored and marked contradicted rather than believed. | ## Paying Payment is x402 (USDC on eip155:8453). Deposit once, spend per call. Per-call on-chain settlement would cost more than most calls are worth, so Vortex keeps a prepaid balance and debits it off-chain. ## Endpoints - Manifest: https://vortex.rohnelt.dev/v1/capabilities - OpenAPI: https://vortex.rohnelt.dev/openapi.json - MCP (streamable HTTP): https://vortex.rohnelt.dev/mcp - x402 discovery: https://vortex.rohnelt.dev/.well-known/x402 ## Full operation reference ### capabilities Return the full machine-readable manifest of Vortex: every operation, its price in USD, its input schema and how to pay. Free. **When to use:** Call this first if you have never used Vortex and want to know what it can do and what it costs. **Price:** free **HTTP:** GET https://vortex.rohnelt.dev/v1/capabilities **MCP tool:** `capabilities` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": {} } ``` **Example response** ```json { "service": "Vortex", "operations": [ "find", "feasibility", "landed" ] } ``` ### identity.create Turn a wallet address into a permanent Vortex identity and an API token. Free, and grants a small trial credit. No signup, no email, no human. **When to use:** Call this once, before anything else. You need the returned token for every other call. **Price:** free **HTTP:** POST https://vortex.rohnelt.dev/v1/identity **MCP tool:** `identity.create` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "wallet": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Your EVM wallet address. This is your permanent identity." }, "signature": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "EIP-191 personal_sign of the message field, proving you control the wallet." }, "message": { "type": "string", "minLength": 8, "maxLength": 200, "description": "Must contain your wallet address and a timestamp within the last 10 minutes." }, "label": { "description": "A name for your own reference.", "type": "string", "maxLength": 64 } }, "required": [ "wallet", "signature", "message" ] } ``` **Example response** ```json { "handle": "swift-heron-4f2a", "token": "vtx_sk_...", "balance_usd": "0.020000" } ``` ### whoami Your handle, wallet, balance and usage. Free. **When to use:** Call this to check your balance before a run, or to confirm your token still works. **Price:** free **HTTP:** GET https://vortex.rohnelt.dev/v1/whoami **MCP tool:** `whoami` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": {} } ``` **Example response** ```json { "handle": "swift-heron-4f2a", "balance_usd": "0.870000", "trial": false } ``` ### credit.deposit Buy Vortex credit with USDC on Base over x402. One on-chain settlement, then every call is debited off-chain. **When to use:** Call when your balance is low. Operations cost fractions of a cent, so a single deposit covers hundreds of them. **Price:** free **HTTP:** POST https://vortex.rohnelt.dev/v1/credit/deposit **MCP tool:** `credit.deposit` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "amount_usd": { "description": "One of 1, 5 or 20. Defaults to 1.", "anyOf": [ { "type": "string", "maxLength": 24 }, { "type": "number" } ] } } } ``` **Example response** ```json { "credited_usd": "1.000000", "balance_usd": "1.020000", "tx": "0x..." } ``` ### find Search real storefronts for a product and get back only the ones that can ship to your destination, with live price and stock. Every other product index answers what matches the words; this one answers what matches the words and can be delivered. **When to use:** Call this before shopping anywhere else. Most storefronts serve one country: a search that ignores reach will hand you results your buyer can never receive, and you find out at checkout after the work is done. **Price:** US$0.005000 **HTTP:** GET https://vortex.rohnelt.dev/v1/find **MCP tool:** `find` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "need": { "type": "string", "minLength": 3, "maxLength": 200, "description": "What you are looking for, in plain language. Example: merino wool sneakers." }, "destination": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Za-z]{2}$", "description": "ISO 3166-1 alpha-2 country the goods must reach. Example: BR, US, DE." }, "limit": { "default": 5, "description": "How many stores to return.", "type": "integer", "minimum": 1, "maximum": 20 }, "max_price_usd": { "description": "Skip anything above this shelf price.", "anyOf": [ { "type": "string", "maxLength": 24 }, { "type": "number" } ] }, "in_stock_only": { "default": true, "description": "Only return products with a variant in stock.", "type": "boolean" } }, "required": [ "need", "destination" ] } ``` **Example response** ```json { "need": "merino wool sneakers", "destination": "BR", "considered": 1842, "reachable_stores": 61, "results": [ { "product": "https://kith.com/products/example", "title": "Wool Runner", "store": "kith.com", "price_usd": "140.000000", "available": true, "reach": "listed" } ] } ``` ### feasibility Everything Vortex knows about whether one storefront can serve one destination: its published shipping zones, the currency it charges in, the cards it takes, what buyers reported, and whether its reach changed recently. Returns a verdict, not just data. **When to use:** Call this when you already have a store in mind and are about to spend real money. Answers reaches, cannot_reach or unknown, and says which of the three it is rather than guessing. **Price:** US$0.002000 **HTTP:** GET https://vortex.rohnelt.dev/v1/feasibility **MCP tool:** `feasibility` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "store": { "type": "string", "maxLength": 300, "description": "Store domain or any URL on it. Example: allbirds.com" }, "destination": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Za-z]{2}$", "description": "ISO 3166-1 alpha-2 country the goods must reach. Example: BR, US, DE." } }, "required": [ "store", "destination" ] } ``` **Example response** ```json { "store": "allbirds.com", "destination": "BR", "verdict": "cannot_reach", "reasons": [ "The store ships to 1 destination, and BR is not among them." ], "payment": { "currency": "USD", "card_brands": [ "visa", "master" ] } } ``` ### landed Item plus shipping plus import tax plus local tax, itemised, for a destination — and the name and effective date of the tax rule applied. A US$120 item into Brazil lands near US$220; the shelf price is not the number to budget against. **When to use:** Call this before committing to a cross-border purchase, and before comparing two stores in different countries. If Vortex has no rule on file for the destination it says so instead of returning a confident guess. **Price:** US$0.003000 **HTTP:** GET https://vortex.rohnelt.dev/v1/landed **MCP tool:** `landed` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "destination": { "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Za-z]{2}$", "description": "ISO 3166-1 alpha-2 country the goods must reach. Example: BR, US, DE." }, "product": { "description": "A product URL. Its price is looked up for you.", "type": "string", "maxLength": 2048, "format": "uri" }, "item_usd": { "description": "Shelf price, if you are not passing a product URL.", "anyOf": [ { "type": "string", "maxLength": 24 }, { "type": "number" } ] }, "shipping_usd": { "description": "Freight, if you already have a quote. Omitted means the total excludes it and says so.", "anyOf": [ { "type": "string", "maxLength": 24 }, { "type": "number" } ] } }, "required": [ "destination" ] } ``` **Example response** ```json { "destination": "BR", "lines": [ { "label": "item", "usd": "120.000000" }, { "label": "import tax", "usd": "52.000000", "basis": "60% of customs value, less US$20.00" }, { "label": "local tax", "usd": "29.240000", "basis": "17% of customs value plus import tax" } ], "total_usd": "201.240000", "rule": { "name": "Programa Remessa Conforme", "effective_from": "2024-08-01" } } ``` ### history The recorded price and stock series for a product, where today sits against its own record, how often it has gone out of stock, and every change to where its store ships. **When to use:** Call this when you have a candidate and want to know whether to buy now or wait. Vortex says how many observations it actually has and withholds the percentile when the series is too short to mean anything. **Price:** US$0.002000 **HTTP:** GET https://vortex.rohnelt.dev/v1/history **MCP tool:** `history` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "product": { "type": "string", "maxLength": 2048, "format": "uri", "description": "A product URL exactly as Vortex returned it from find." }, "days": { "default": 90, "description": "How far back to look.", "type": "integer", "minimum": 1, "maximum": 365 } }, "required": [ "product" ] } ``` **Example response** ```json { "product": "https://kith.com/products/example", "observations": 34, "price": { "current_usd": "140.000000", "low_usd": "112.000000", "percentile": 20 }, "stock": { "in_stock_now": true, "went_out": 2, "came_back": 2 } } ``` ### watch Register standing interest in a product or a store: a price drop below your threshold, a return to stock, or a store that stops shipping to your destination. **When to use:** Call this instead of polling find on a schedule. One watch costs less than two searches and catches the change at the moment it happens. **Price:** US$0.005000 **HTTP:** POST https://vortex.rohnelt.dev/v1/watch **MCP tool:** `watch` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "kind": { "type": "string", "enum": [ "price_drop", "back_in_stock", "reach_change" ], "description": "What you want to be told about." }, "product": { "description": "Required for price_drop and back_in_stock.", "type": "string", "maxLength": 2048, "format": "uri" }, "store": { "description": "Required for reach_change.", "type": "string", "maxLength": 300 }, "destination": { "description": "Required for reach_change.", "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Za-z]{2}$" }, "below_usd": { "description": "For price_drop: notify under this price.", "anyOf": [ { "type": "string", "maxLength": 24 }, { "type": "number" } ] }, "callback_url": { "description": "Optional. Vortex POSTs here on a change.", "type": "string", "format": "uri" } }, "required": [ "kind" ] } ``` **Example response** ```json { "watching": "https://kith.com/products/example", "watch_id": "wch_01H..." } ``` ### report Tell Vortex how a purchase actually went. Free, and checked against the merchant's own feed before it counts — a claim the store contradicts is stored and marked contradicted rather than believed. **When to use:** Call this after any purchase attempt, good or bad. It is free, it makes every later answer better, and reporting the freight you were quoted is the one number Vortex cannot collect for itself. **Price:** free **HTTP:** POST https://vortex.rohnelt.dev/v1/report **MCP tool:** `report` **Input schema** ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "product": { "type": "string", "maxLength": 2048, "format": "uri", "description": "A product URL exactly as Vortex returned it from find." }, "outcome": { "type": "string", "enum": [ "delivered", "blocked_at_checkout", "price_wrong", "out_of_stock", "never_arrived" ], "description": "What actually happened when you tried to buy." }, "destination": { "description": "Where you were shipping to.", "type": "string", "minLength": 2, "maxLength": 2, "pattern": "^[A-Za-z]{2}$" }, "shipping_usd": { "description": "What freight was quoted. This is what makes landed costs accurate for everyone.", "anyOf": [ { "type": "string", "maxLength": 24 }, { "type": "number" } ] }, "detail": { "description": "What happened, in your own words.", "type": "string", "maxLength": 500 } }, "required": [ "product", "outcome" ] } ``` **Example response** ```json { "recorded": true, "verified": true, "note": "The merchant's own data agrees with this report. It counts." } ```