Headless Commerce für agentische LLMs lesbar und zahlbar machen
Käufer werden zu Agenten. Was es braucht, damit ein LLM lesen, unterschreiben und bezahlen kann, ohne dass ein Mensch eingreift, und was Hanzo dafür heute liefert.

Auf dieser Seite
Headless Commerce hat die Storefront vom Motor getrennt, damit jedes Frontend über eine einzige API verkaufen konnte. Dieses Frontend war immer etwas, das ein Mensch angesehen hat: eine Website, eine App, ein Kiosk.
Das nächste Frontend sieht nicht hin. Es liest. Der Käufer wird zum Agenten: ein Programm mit einem Ziel, einem Budget und einer Werkzeugschleife, losgeschickt, um einen Tarif, eine GPU oder eine Zahlungs-API zu finden. Es kauft bei dem, den es verstehen und bezahlen kann, ohne einen Menschen um Hilfe zu bitten. Wenn dein Geschäft eine Person braucht, die eine Seite liest, ein Cookie-Banner wegklickt, eine Bestätigungsmail öffnet oder eine Kartennummer eintippt, nimmt der Agent das nächste Ergebnis.
Das ist die These. Ein Geschäft muss für ein LLM lesbar und transaktionsfähig sein, ohne einen Menschen in der Schleife. Lesbar heißt, der Agent kann erfahren, was du verkaufst, was es kostet und wie man anfängt. Transaktionsfähig heißt, er kann anfangen, bezahlen und die Sache über eine API entgegennehmen, allein.
Das braucht es, Punkt für Punkt, zusammen mit dem, was Hanzo heute ausliefert. Jede Adresse hier unten antwortet ohne Konto, du kannst also jede Aussage selbst prüfen.
Jede Seite als Markdown ausliefern
Ein Agent bezahlt jedes Token, das er liest. Häng auf hanzo.ai .md an die Adresse einer Seite, und du bekommst die Seite als Markdown: hanzo.ai/pricing.md, hanzo.ai/about.md. Jede Seite nennt ihr Gegenstück im Kopf mit <link rel="alternate" type="text/markdown">, damit ein Agent nicht raten muss.
Am 26. Oktober habe ich unsere Agents-Seite auf beide Arten geholt: 528,810 Bytes als HTML, 17,465 als Markdown. Dann nahm ich jede zwölfte URL in unserer Sitemap, 70 von 829, und habe ihr Gegenstück angefordert. Alle 70 kamen als 200 mit text/markdown zurück.
Einen Index veröffentlichen, bei dem ein Agent anfangen kann
Ein Agent, der noch nie von dir gehört hat, braucht eine Adresse, die überall hinführt. Wir veröffentlichen drei.
- hanzo.ai/llms.txt ist eine Klartextkarte der Website. Sie sagt, was Hanzo ist, gibt dann einen Abschnitt "For agents" mit den genauen Schritten zu einem Schlüssel, und listet danach die Seiten, jede in einer Zeile. docs.hanzo.ai/llms.txt tut dasselbe für die Dokumentation.
- api.hanzo.ai/v1 listet jede Fähigkeit, die die API bereitstellt, ohne Schlüssel, und api.hanzo.ai/v1/openapi.json enthält jede Operation mit ihrem Schema. Für den Verkauf enthält der Index eine Fähigkeit
commerce: Checkout, Abos, Rechnungen, Zahlungs-Webhooks und den Storefront-Katalog. - hanzo.ai/.well-known/api-catalog ist die Standardstelle (RFC 9727), an der ein Client zuerst nachsieht. Sie zeigt auf das OpenAPI-Dokument, die Dokumentation und die Statusseite.
Die Crawler mit Absicht hereinlassen
robots.txt ist die erste Datei, die jeder Crawler anfragt. Unsere nennt zwölf KI-Crawler einzeln, darunter GPTBot, ClaudeBot, Claude-User, PerplexityBot und Google-Extended, und erlaubt sie. Sie bekommen dieselben Ausnahmen wie alle anderen: Anmeldung, Konto, Bezahlung und die API-Pfade.
KI-Crawler zu sperren ist eine legitime Entscheidung. Sie zu sperren, weil ein Standardwert das sagte, ist gar keine Entscheidung.
Den Preis zu einem Datenpunkt machen
Agenten vergleichen. Ein Preis in einem Bild, oder hinter einem "contact us"-Button, lässt sich nicht vergleichen. api.hanzo.ai/v1/billing/plans braucht keinen Schlüssel und liefert JSON: Free zu 0, Pro zu 2000 im Monat, Team zu 2500 pro Platz, mit den Grenzen jedes Tarifs daneben. Die Beträge sind in Cent.
Eine Wallet anmelden lassen
Ein Agent hat kein Postfach, kein Telefon und keine Karte. Er hat ein Schlüsselpaar. Deshalb meldet hanzo.id eine Wallet an: einen einmaligen Nonce für die Adresse der Wallet anfordern, die beschriebene Nachricht signieren, die Signatur senden und den Code, der zurückkommt, gegen ein Token tauschen.
Eine Wallet, die Hanzo noch nicht gesehen hat, bekommt ein eigenes Konto und eine eigene Organisation, mit der Wallet als Administrator, im Tarif Free. Das Token gilt sieben Tage. Niemand öffnet eine Mail oder gibt ein Gerät frei.
Ein Aufruf für einen Schlüssel, und ein kleines Guthaben zum Probieren
Mit dem Token liefert POST /v1/account/keys einen Schlüssel sk-live-, der es überdauert. Heb ihn auf; die Dokumentation sagt, er wird nur einmal gezeigt.
Der Tarif Free sind 50 Anfragen am Tag auf zen-free, ohne Karte, und jede Antwort sagt, was noch übrig ist, in x-ratelimit-remaining. Mein erster Aufruf antwortete 200 mit 49 übrig.
Zahlung ohne Mensch: Stablecoins über die API
POST /v1/billing/crypto/deposit nimmt eine Chain, einen Token und einen Betrag und liefert eine Einzahlungsadresse, die 24 Stunden gilt. GET /v1/billing/crypto/options listet, was es annimmt: die Chains Base, Ethereum und Solana, und die Token USDC und USDT.
Ich habe bei der Adresse aufgehört und kein Geld geschickt. Dass das Guthaben gutgeschrieben wird, wenn die Chain bestätigt, steht in unserer Dokumentation, ich habe es nicht selbst ausgeführt. Tarife und Abos bleiben Karten-Checkout im Browser. Was ein Agent von uns braucht, ist Guthaben, und Guthaben hat eine API.
Der ganze Ablauf, in einer Datei
Das ist hanzo.ai/agents#headless, gekürzt. Jede Zeile steht so, wie diese Seite sie ausgibt; ich habe den zweiten Kopfkommentar weggelassen, den Optionsaufruf und die Zeile, die ein Schlüsselpräfix ausgibt. Du brauchst Node 22.18 oder neuer und npm i viem, dann node headless.mts. Ich habe diesen Block gegen die Produktion laufen lassen, mit einer frischen Wallet: ein Token, ein Schlüssel, ein kostenloser Aufruf und eine USDC-Einzahlungsadresse.
// No human required: sign in with a wallet, get a key, call the API, top up in USDC.
// npm i viem · node headless.mts (Node 22.18+; set HANZO_WALLET_KEY to use your own wallet)
import { createHash, randomBytes } from 'node:crypto'
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
const ID = 'https://hanzo.id'
const API = 'https://api.hanzo.ai'
const CLIENT = 'hanzo-ai'
const REDIRECT = 'http://localhost:3000/callback'
const account = privateKeyToAccount((process.env.HANZO_WALLET_KEY as `0x${string}`) ?? generatePrivateKey())
const json = async (r: Response) => {
const body = await r.json()
if (!r.ok || body?.status === 'error') throw new Error(`${r.url} ${r.status} ${JSON.stringify(body)}`)
return body
}
// 1. A one-time challenge for this wallet.
const { data: c } = await json(await fetch(`${ID}/v1/iam/web3/nonce?chain=evm&address=${account.address}`))
// 2. The CAIP-122 message the challenge describes, signed with EIP-191 personal_sign.
const message = [
`${c.domain} wants you to sign in with your Ethereum account:`,
account.address,
'',
...(c.statement ? [c.statement, ''] : []),
`URI: ${c.uri}`,
`Version: ${c.version}`,
`Nonce: ${c.nonce}`,
`Issued At: ${c.issuedAt}`,
...(c.expirationTime ? [`Expiration Time: ${c.expirationTime}`] : []),
].join('\n')
const signature = await account.signMessage({ message })
// 3. Verify: a first-seen wallet gets an account and an organization of its own.
const verifier = randomBytes(32).toString('base64url')
const challenge = createHash('sha256').update(verifier).digest('base64url')
const { data: code } = await json(
await fetch(`${ID}/v1/iam/web3/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clientId: CLIENT, chain: 'evm', scheme: 'secp256k1-eip191', address: account.address, message, signature,
type: 'code', redirectUri: REDIRECT, scope: 'openid profile email', codeChallenge: challenge, codeChallengeMethod: 'S256',
}),
}),
)
// 4. The authorization code for a token.
const token = await json(
await fetch(`${ID}/v1/iam/oauth/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({ grant_type: 'authorization_code', client_id: CLIENT, code, code_verifier: verifier, redirect_uri: REDIRECT }),
}),
)
const bearer = { Authorization: `Bearer ${token.access_token}`, 'Content-Type': 'application/json' }
// 5. A key that outlives the token. Shown once: keep it in your secret store.
const minted = await json(await fetch(`${API}/v1/account/keys`, { method: 'POST', headers: bearer, body: JSON.stringify({ name: 'agent', type: 'secret' }) }))
const key = { Authorization: `Bearer ${minted.key}`, 'Content-Type': 'application/json' }
// 6. A first call, free.
const chat = await fetch(`${API}/v1/chat/completions`, {
method: 'POST', headers: key,
body: JSON.stringify({ model: 'zen-free', messages: [{ role: 'user', content: 'Reply with the single word: ready' }] }),
})
console.log('chat', chat.status, chat.headers.get('x-hanzo-served'), 'free left today:', chat.headers.get('x-ratelimit-remaining'))
console.log((await chat.json()).choices?.[0]?.message?.content)
// 7. Top up in USDC: ask for a deposit address, then send to exactly that address.
console.log(await json(await fetch(`${API}/v1/billing/crypto/deposit`, { method: 'POST', headers: key, body: JSON.stringify({ chain: 'base', token: 'usdc', amountCents: 500 }) })))
x402 kommt, und ist noch nicht da
Über das Aufladen hinaus ist die richtige Form für einen Agenten die Zahlung pro Anfrage. Der Server antwortet 402 Payment Required mit einem Preis, der Client zahlt und versucht es erneut. Das ist x402. Es ist auf unserer API nicht live: noch kein Endpunkt von Hanzo nennt auf diese Weise einen Preis, also behaupte ich es nicht. Bis dahin ist ein über die API aufgeladenes Guthaben die Art, wie ein Agent uns bezahlt.
Warum null Crawler-Fehler zählen
Nichts davon scheitert laut. Ein Agent, der einem Link aus deiner Sitemap in einen 404 folgt, macht kein Ticket auf. Er nimmt das nächste Ergebnis. Behandle einen Crawler-Fehler so, wie ein Laden eine kaputte Kasse behandelt.
Ich habe dieselben 70 Stichprobenseiten mit dem User-Agent-String von ClaudeBot geholt und noch einmal mit dem von Googlebot. Jede hat beide Male 200 geantwortet. Das ist eine Stichprobe, keine Garantie, und ein User-Agent-String ist nicht die eigene Adresse des Crawlers, ich kann dir also nicht zeigen, was die echten Crawler sehen. Mach dasselbe auf deiner Website: hol deine Sitemap mit den Agenten, die du einlädst, und zähl die Antworten, die nicht 200 sind.
Hier waren wir schon einmal
Ich habe dieses Unternehmen 2014 gegründet, als Crowdstart; 2016 haben wir es in Hanzo umbenannt. Unser erster Kunde, SKULLY, hat auf Indiegogo in etwa 45 Stunden $1 million eingesammelt, was TechCrunch die schnellste vollständig finanzierte Kampagne auf Indiegogo nannte. Meiner Darstellung nach war Hanzo von Anfang an KI-nativer Commerce: zuerst unsere eigene Analytik, dann Modelle, die aus den Daten der Unternehmen auf der Plattform lernten. 2017 sind wir zu Techstars gekommen (der Beitrag von jenem Juni), und was wir zu bauen sagten, war intelligenter Commerce.
2020 ist Damon Motorcycles auf der CES gestartet, mit Hanzo an der Kampagne. In 30 Tagen hat die Plattform Motorräder für $8.4M verkauft, bei $15,532 Werbeausgaben, eine Rendite von 541:1. Zielgruppen wurden alle 12 Stunden aus unseren Kundendaten neu aufgebaut, und von KI geschriebene Anzeigengruppen lagen auf Facebook innerhalb von 36 Stunden bei Above Average. Die Fallstudie hat den Rest.
Das waren Maschinen auf der Verkaufsseite, die die Zielgruppen fanden, die kauften, und die Anzeigen schrieben. Als Nächstes kommt die Kaufseite. Dieselbe Schleife wird gleich vom anderen Ende laufen, und dein Geschäft wird von einer Maschine gelesen und bezahlt, oder von einer Maschine übergangen.
Richte deinen Agenten auf hanzo.ai/agents.
Weiterlesen

Hanzo Payments: Unified Payment Processing for Global Commerce
Launching Hanzo Payments — unified payment processing with intelligent routing, fraud detection, and multi-currency support.

Introducing the Hanzo Platform
Crowdstart evolves into Hanzo: a complete commerce platform for the modern era.

Der Router ist das Register
Hanzo Cloud hat keine eingecheckte OpenAPI-Datei. Die lebende Routentabelle ist die Quelle, dreifach projiziert, und ein Bijektionstest lässt den Build scheitern, wenn eine Projektion abweicht. 1,362 Operationen über 963 Pfade, je Prozess zur Anfragezeit erzeugt.
