Files
zeekay ac64d5d7dd Folds say one line: every first screen keeps its heading and a single lede
The owner's spec for a landing page is the models bento's: monochrome, the
words left and the art right, no extra prose. The folds carried two to four
sentences under each heading, and some a claim, a lede and a list besides.
Each now says one line: ProductLanding the tagline where a page states one
(the lede still describes it to search), a claim alone where the claim is
the line (/payments, /treasury, /zap, the extension), and elsewhere the
sentence that says what the thing is. /philosophy's two points, /dns' claim
that repeated its title, /calculator's capabilities line and the
Spare clauses on /research and /learn go.
2026-10-30 06:42:40 -07:00

160 lines
6.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { Code2, MessageSquare, Boxes, Binary, Waypoints, ShieldCheck } from 'lucide-react'
import { Page, PageHero, Section, CardGrid, Prose, type CardItem } from '@/components/marketing/page-kit'
import { AgentPrompt } from '@/components/product/AgentPrompt'
import { Related } from '@/components/product/Related'
import { product } from '@/lib/product'
import { KEYS } from '@/components/home/nav-data'
import { Action } from '@hanzo/ui/marketing'
import { Steps } from '@/components/preview/steps'
import { phrase } from '@hanzo/i18n'
import { useI18n } from '@hanzo/i18n/react'
/** What the agent prompt and the closing block read, off the one table that
* holds a product's name, route, audited command and docs page. */
const PRODUCT = product('api')
const ENDPOINTS: CardItem[] = [
{
title: '/v1/chat/completions',
meta: 'POST',
description: phrase(
'A completion from any model your organization can reach, streamed or buffered. Model ids come from the catalog, so the list is a request rather than a page in the docs.',
),
},
{
title: '/v1/models',
meta: 'GET',
description: phrase(
'What your organization may call right now — the models we serve plus any provider account you have connected, with their identifiers.',
),
},
{
title: '/v1/embeddings',
meta: 'POST',
description: phrase('Vectors for search, retrieval and clustering, from the same key and the same bill as generation.'),
},
{
title: '/v1/agents',
meta: 'GET · POST',
description: phrase(
'Define an agent once, run it by reference, and read its runs afterwards. The definition lives here, so everything that runs it runs the same one.',
),
},
{
title: '/v1/billing/balance · /v1/billing/usage',
meta: 'GET',
description: phrase(
'What is left, and what was spent. Usage is recorded per call and attributed to the organization on the token, so a bill can be traced back to the request that caused it.',
),
},
{
title: '/v1/tools',
meta: 'GET',
description: phrase(
'The tools your organization can call. An agent picks from this list, and so can you — it is the same catalog either way.',
),
},
]
const CONCEPTS: CardItem[] = [
{
icon: ShieldCheck,
title: phrase('One key, one bill'),
description: phrase(
'A single key authenticates every endpoint, and usage meters to the organization it belongs to. Spend is attributed in one place instead of once per service.',
),
},
{
icon: Waypoints,
title: phrase('Identity is the gateway’s to state'),
description: phrase(
'Every request passes a gateway that throws away the identity headers a client sent and writes them again from the verified token. Nothing downstream has to wonder whether an org id came from a token or from a curl flag.',
),
},
{
icon: Binary,
title: phrase('Generated, not hand-written'),
description: phrase(
'The clients come from the OpenAPI document this API serves, and their method names are its operation ids. A client is checkable against a release rather than against somebody’s memory.',
),
},
]
export default function ApiPage() {
const { t } = useI18n()
return (
<Page>
<PageHero
eyebrow="API"
icon={Code2}
title={t('One API for models, agents and tools')}
lede={t('Every Hanzo capability answers under one base URL, behind one key.')}
visual={<Steps title="https://api.hanzo.ai" icon={<Code2 size={12} color="currentColor" />} steps={ENDPOINTS.map((e) => ({ title: `${e.meta} ${e.title}`, body: t(e.description) }))} />}
>
<Action href={KEYS} fill>
{t('Get an API key, free')}
</Action>
<Action href="https://docs.hanzo.ai/docs/openapi/">{t('OpenAPI Reference ↗')}</Action>
</PageHero>
{PRODUCT && <AgentPrompt product={PRODUCT} />}
<Section title={t('Base URL')}>
<Prose>
<p>
<strong>https://api.hanzo.ai/v1</strong>
</p>
<p>
{t('Authenticate with a bearer token: {header}. Keys are created and revoked in the {console}, and revoking one there is what stops it working.', {
header: <strong>Authorization: Bearer &lt;your key&gt;</strong>,
console: <a href={KEYS}>{t('console')}</a>,
})}
</p>
<p>
{t('Every route lives under {v1}, and every service answers on the same host — there is no second base URL to configure and no v2 waiting to break the first one. Rate limits are applied per caller and across the edge as a whole; a rejected request comes back as a {status} with a {retry} rather than a dropped connection.', {
v1: <strong>/v1</strong>,
status: <strong>429</strong>,
retry: <strong>Retry-After</strong>,
})}
</p>
</Prose>
</Section>
<Section title={t('Core endpoints')} lede={t('A few of the ones people reach for first. Every parameter and error shape is in the reference.')}>
{/* An endpoint's path and method stay as written; what it does is read in the reader's language. */}
<CardGrid items={ENDPOINTS.map((e) => ({ ...e, description: t(e.description) }))} columns={2} />
</Section>
<Section title={t('How it fits together')}>
<CardGrid items={CONCEPTS.map((c) => ({ ...c, title: t(c.title), description: t(c.description) }))} columns={3} />
</Section>
<Section title={t('Next')}>
<CardGrid
columns={2}
items={[
{
icon: MessageSquare,
title: t('API reference'),
description: t('Every endpoint, parameter and response shape.'),
// `/docs/api` answers 200 as a `Moved` stub — noindex, meta
// refresh — so the link goes where its canonical points.
href: 'https://docs.hanzo.ai/docs/openapi/',
},
{
icon: Boxes,
title: t('Getting started'),
description: t('An empty project to a first call that works.'),
href: 'https://docs.hanzo.ai/docs/quickstart',
},
]}
/>
</Section>
{PRODUCT && <Related product={PRODUCT} />}
</Page>
)
}