Three on-ramps. One writer.
Ounie accounts hit REST with a bearer token. Assistants — including the Ounie AI Team — connect over MCP. Agents with no account at all pay per call in USDC on Base. All three run the same generator, the same guards, and the same refusals.
Semantic search always returns neighbours, so a subject with no coverage still yields pages. Every retrieved page must actually name your subject or it is dropped, and nothing surviving means there is no article — refunded in full, or on x402 refused before the payment settles. A subject with no content words at all (“how it works”) cannot be checked and is refused free, before any price is quoted.
Any [[slug]] the model emits that was not in the retrieved set is deleted from the text. An invented source cannot reach a reader, even as a broken marker.
A draft can pass both checks above and still lean on two pages out of twenty: fluent, perfectly cited, and grounded in a sliver of your material. Measured on the real task, one common model cited four of sixty supplied sources. So the finished piece has to draw on a reasonable spread of what survived the anchor, or it is thin — and thin is never billed.
Authorization: Bearer <key> on any endpoint, or append ?api_key=<key> when your client cannot set headers. Cookie sessions work on the same routes.Minted at /dashboard/api-keys. Reads, lists, exports and shares. It cannot write, because writing reads your private Ounie brain and a per-app key carries no ounie.com credential to forward.
Your ounie.com developer key, once you enable fleet access in ounie.com settings. This is the one that grounds writing: it is forwarded upstream as the Bearer for retrieval. Same wallet, same limits.
A short balance is a 402 carrying required_credits, balance_credits and buy_credits_url. An agent can never overdraw.
/api/articles— Write an article{ "topic": "how our refund window works",
"brain_ids": ["…"],
"angle": "why we changed it in March",
"audience": "support leads",
"length": "standard",
"include_faq": true }Bills 15 credits. Needs a session or the ounie_live_ master key. Returns articleId, wordCount, citations, anchored/dropped counts and gaps.
/api/articles— List yoursFree.
/api/outline— Plan it first{ "topic": "…", "brain_ids": ["…"], "length": "long" }Bills 3 credits. Same gates, one model call.
/api/articles/{id}— The full payloadFree. Sections, citations, gaps, internal links, JSON-LD, markdown, and both source lists.
/api/articles/{id}/sections/{sectionId}— Rewrite one section{ "instruction": "shorter, and lead with the exception" }Bills 2 credits. Re-retrieves live rather than replaying a stored copy of your brain.
/api/articles/{id}/sections/{sectionId}— Edit a section by hand{ "heading": "…", "body": "…" }Free.
/api/articles/{id}/share— Preview linkFree. DELETE the same path to revoke — the page is served no-store, so a revoke is immediate.
/api/articles/{id}/export?format=markdown|html|json— DownloadFree.
/api/articles/{id}— DeleteFree. Cascades sections.
POST /api/x402/article
{
"topic": "how our refund window works",
"source_text": "…your material, 200+ chars…",
"mode": "article", // or "outline"
"length": "standard",
"include_faq": false
}
→ 402 { x402Version, accepts: [{ scheme: "exact",
network: "base", maxAmountRequired, payTo,
asset, extra: { name: "USD Coin", version: "2" } }] }
Sign the EIP-3009 authorization, resend with
X-Payment: <base64>, and the article comes back.- A request that cannot succeed is refused for free. A malformed payload, source_text under the minimum, or a subject with no anchorable words returns 4xx with no quote in the body. You are never asked to sign for a guaranteed failure.
- Verify, run, then settle. Thin material and low coverage are caught after your payment is verified and before it settles, so nothing moves on chain and your signed authorization simply goes unused.
- All or nothing. A settlement must match the quote exactly, so a piece that comes back materially shorter than its own plan is retried once and then returned as
402 partial_deliverywithout settling. There is no partial charge on this rail because there is no refund on this rail. - No account means no hosted preview and no stored copy — the response is the whole deliverable.
- Priced from the credit table at 1.2×: 15 credits →
180,000atomic USDC. The price is computed from your payload and quoted in the 402, never hardcoded.
// GET /api/articles/{id}
{
"article": {
"title", "slug", "meta_description", "dek", "pull_quote",
"outline": [{ "heading", "purpose", "sourceSlugs", "covered" }],
"sections": [{ "position", "heading", "body", "citations" }],
"faq": [{ "question", "answer" }],
"gaps": ["what these sources do not cover"],
"citations": [{ "brainId", "slug", "title", "url" }],
"internal_links":[{ "anchorText", "slug", "title", "url" }],
"json_ld", "faq_json_ld", "word_count", "markdown",
// the anchor's own verdict, so the relevance call is
// inspectable rather than something you take on trust
"sources_used": [{ "slug", "title", "matched_terms" }],
"sources_dropped_off_topic":[{ "slug", "title", "matched_terms" }]
},
"share_url": null
}internal_links is anchor text plus the source page behind it. We do not know the URLs on your site and will not invent them — it is a suggestion you map in a minute, and saying so is more useful than a plausible-looking link that 404s.
/api/mcp, legacy SSE at /api/sse.https://articles.ounie.com/api/mcp ?api_key=art_live_…
The Ounie AI Team passes its key in the URL because its manual MCP entries cannot set static headers. Everything else should use the Authorization header.
503 upstream_unavailable — no quote on the x402 rail, no reserve on the credit rail, nothing charged. It recovers on its own within a few minutes of the engine coming back.