Skip to content

docs: Exa integration page (agent-driven API-credit purchases via card delegation) - #266

Merged
robindoble merged 5 commits into
mainfrom
feat/exa-integration-page
Aug 3, 2026
Merged

docs: Exa integration page (agent-driven API-credit purchases via card delegation)#266
robindoble merged 5 commits into
mainfrom
feat/exa-integration-page

Conversation

@robindoble

@robindoble robindoble commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

What

Adds integrations/exa.mdx to the Integrations section, between OpenClaw and BuildShip, detailing the Exa partnership: agents autonomously buy and top up Exa API keys ($7/purchase) via the x402 card-delegation scheme.

Because the page enters docs.json navigation, Mintlify automatically serves it as .md (for agent ingestion) and lists it in the generated llms.txt — no manual index edits needed.

Why

Exa's own integration doc still teaches the retired create-on-the-fly delegation shape (rejected by the backend for current-version API keys since the #2392 rollout in nvm-monorepo), so agents following it dead-end at token mint. This page is the canonical, current-SDK reference on our side; Exa will be asked to align theirs separately.

Content notes

  • Codeless format: prose contracts + SDK method-name anchors; the package's bundled TypeScript definitions are stated as the authoritative call reference. No embedded code samples to drift.
  • Both delegation branches covered with explicit agent steering: owner-created delegation (discovered via getPurchasingPower(), preferred) and programmatic createDelegation fallback (with card-selection caveat and budget/duration sizing).
  • Key acquisition documented both ways: embedded auth/cli login flow and manual dashboard.

Validation

Every claim on the page is runtime-verified. Content was blind-tested on 2026-08-02/03 by cold agents (fresh context, this page + a live API key only, latest SDK 1.10.0, newly created key): both branches completed real $7 purchases first try with zero failed calls, including a settle through an agent-created delegation. The embedded login flow was executed end to end on live as well.

🤖 Generated with Claude Code

… card delegation)

New integrations/exa.mdx between OpenClaw and BuildShip: the Exa partnership
page detailing how agents buy and top up Exa API keys with x402 card
delegation. Codeless format (prose contracts + SDK method anchors; the
package typings are the call reference). Content blind-validated end to end
with real purchases on both branches (owner-created delegation via discovery,
and programmatic createDelegation fallback) on a fresh API key + latest SDK.

Mintlify auto-serves the page as .md and auto-lists it in llms.txt via the
docs.json navigation entry.
@robindoble
robindoble requested a review from a team as a code owner August 3, 2026 12:23
Copilot AI review requested due to automatic review settings August 3, 2026 12:23
@mintlify

mintlify Bot commented Aug 3, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Nevermined 🟢 Ready View Preview Aug 3, 2026, 12:24 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

…verification

The embed-session flow is documented on the staging agentic-instructions
surface; live-environment support is unconfirmed beyond route existence.
Re-add once verified on prod.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Mintlify integration page documenting how agents can autonomously purchase/top up Exa API credits using Nevermined’s x402 card-delegation flow, and wires the page into the Integrations navigation.

Changes:

  • Added integrations/exa.mdx describing the Exa plan, prerequisites, purchase contract, and troubleshooting for agent-driven purchases.
  • Updated docs.json to include the new Exa page in the “Protocols & Partners” integrations group.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
integrations/exa.mdx New integration doc for Exa’s x402 card-delegation purchase flow and operational guidance.
docs.json Adds Exa to the Integrations navigation so the page is discoverable.
Suppressed comments (1)

integrations/exa.mdx:76

  • The troubleshooting entries for ERR_PACKAGE_PATH_NOT_EXPORTED and the deprecated environment option are currently broader/more specific than what the rest of the docs describe. Aligning these to the documented behavior (subpath import + deprecation warning when environment is provided) will reduce confusion for readers.
| A delegation you spent from disappears from `getPurchasingPower()` | It is exhausted. Inspect it with `listDelegations()`; create or top up a delegation to continue. |
| Exa search returns `402` with `NO_MORE_CREDITS` | The Exa key's credits are spent. Repeat the purchase flow to top up the same key. |

Comment thread integrations/exa.mdx

## The flow

Handled with the Nevermined Payments SDK (`npm install @nevermined-io/payments`; the package is ESM-only; in a fresh npm project set `"type": "module"` in `package.json`, or the import fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`). The package's bundled TypeScript definitions are the authoritative call reference for every method named below. For broader context, start from the [Payments overview](/products/payments/overview) and the [documentation index](https://nevermined.ai/docs/llms.txt).
Comment thread integrations/exa.mdx

1. **Initialize** the SDK with your Nevermined API key only (`Payments.getInstance({ nvmApiKey })`). The environment is derived from the key prefix; do not pass an `environment` option.
2. **Find the delegation to pay with**; see [Getting a delegation](#getting-a-delegation) below.
3. **Mint the x402 access token** for the Exa plan ID via `payments.x402.getX402AccessToken`, using the `nvm:card-delegation` scheme and referencing the delegation by ID (`delegationConfig: { delegationId }`). No agentId is needed for this flow: the method's arguments are `(planId, agentId?, tokenOptions?)`, so pass the plan ID, `undefined`, and the token options. Tokens cannot create delegations on the fly; the delegation must exist first.

@aaitor aaitor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. This is a well-built, codeless integration page and it holds up under verification: I checked every SDK-shaped claim against the @nevermined-io/payments source and the core purchase flow is accurate end to end. Two MEDIUM tightenings and one LOW confirmation below — none blocks merge, but the environment-warning troubleshooting row (L74) is worth correcting because it currently trains an agent to ignore a signal that is actually actionable.

What I verified against the SDK (local payments, v1.9.0 — PR tested 1.10.0)

  • getX402AccessToken(planId, agentId?, tokenOptions?) — exact match (src/x402/token.ts:64); the "pass planId, undefined, token options" instruction is correct.
  • Scheme nvm:card-delegation → maps to provider stripe (src/common/types.ts:514); default scheme is nvm:erc4337, so passing it explicitly (as the page says) is required. ✓
  • createDelegation payload — provider: "stripe" ✓, currency: "usd" ✓ (the JSDoc example uses usdc for erc4337; the page correctly uses usd for card), spendingLimitCents/durationSecs are number on write ✓.
  • Budget-fields-as-strings on read ✓ (DelegationSummary.remainingBudgetCents/amountSpentCents/spendingLimitCents: string), transactionCount: number ✓. The write-number/read-string split is a subtle detail the page gets right.
  • getPurchasingPower() excludes exhausted delegations — confirmed: it calls listDelegations({ accessible: true }), which returns only Active/non-expired/with-budget (src/x402/delegation-api.ts:151,161). ✓
  • nvmApiKey-only init with environment derived from key prefix ✓ (PaymentOptions.environment is @deprecated, src/common/types.ts:15).
  • payment-signature header ✓ (matches project convention, not deprecated X-402).

Verification I ran

  • gh pr view/diff/checks — CI green (2/2, Mintlify preview 🟢).
  • Read all 3 changed files at head (exa.mdx new, docs.json nav, solutions/api-providers.mdx link swaps); nav order confirmed openclaw → exa → buildship.
  • Cross-checked ~12 specific SDK claims against payments source (citations above). Base is main, no PR chain to trace.
  • Over-engineering / leanness pass: lean already, ship — 0 net-removable lines. The exhausted-delegation fact repeats across three sections, but that aids the cold-agent-lands-mid-page use case the page is written for; not debt.
  • solutions/api-providers.mdx L386 swaps Exa's external .md mirror (a real-provider example) for the internal guide. Slight pedagogical downgrade for that section, but the right call given Exa's mirror teaches the retired shape — no change needed.

Copilot's suppressed comment (L76 troubleshooting alignment) is low-value; not echoing it.

Comment thread integrations/exa.mdx
|---|---|
| Token mint fails: `Required token-generation input is missing or incomplete (HTTP 402)` | The mint referenced no existing delegation (e.g., legacy create-on-the-fly `delegationConfig` with card details). Create or discover a delegation first and pass `delegationConfig: { delegationId }`. |
| `ERR_PACKAGE_PATH_NOT_EXPORTED` on import | The SDK is ESM-only. Set `"type": "module"` in `package.json` or use `.mts`. |
| Console warning: `The 'environment' option is deprecated…` even though you never passed it | Known SDK issue; harmless. The environment is derived from your key prefix. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM — this row is inaccurate on the SDK source I can see, and "harmless" is the wrong framing.

The deprecation warning is gated (src/api/base-payments.ts:132):

if (options.environment && !environmentOptionDeprecationWarned) {  console.warn("[DEPRECATED] The 'environment' option is deprecated…") }

It fires only when environment is actually passed — never "even though you never passed it". If an agent sees this warning, something is still passing environment (a wrapper, scaffold, or copied example), and the fix is to remove it — not to ignore it as a "known SDK issue". Documenting a correct, actionable signal as harmless trains agents to suppress it.

I'm on v1.9.0 locally; the PR tested 1.10.0. Two options:

  1. If 1.10.0 genuinely fires this with no environment passed, that's an SDK regression worth a payments issue — link it here rather than calling it "harmless".
  2. Otherwise, correct the row:
Suggested change
| Console warning: `The 'environment' option is deprecated…` even though you never passed it | Known SDK issue; harmless. The environment is derived from your key prefix. |
| Console warning: `The 'environment' option is deprecated…` | Something is still passing the deprecated `environment` option (a wrapper or copied example). Remove it — the environment is derived from your key prefix. |

Comment thread integrations/exa.mdx
[Exa](https://exa.ai) accepts autonomous payments through Nevermined's [x402 card-delegation](/specs/x402-card-delegation) scheme. An agent holding a Nevermined API key mints an x402 access token against the Exa plan and exchanges it at Exa's purchase endpoint for a working Exa API key. Repeat purchases top up the same key.

<Info>
Exa's Nevermined plan ID:<br />`27800462147494506865542649899724877617306579171265399959488097895839186996870`<br />The purchase is for API credits, not for a single search request. \$7 covers roughly 1,000 standard searches; see [Exa pricing](https://exa.ai/pricing) for current rates.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM — state the environment this plan ID belongs to. Plan IDs are per-environment (live vs sandbox are separate backends), and Payments derives the environment from the API key prefix (getEnvironmentFromApiKey). A cold agent — exactly the page's stated test persona — handed a sandbox-prefixed key will mint against this live plan ID, the plan won't resolve, and the resulting error isn't in the troubleshooting table, so it dead-ends silently.

The flow charges a real $7, so it's inherently a live-key flow — just say so. One line in this <Info> block, e.g.:

This plan and purchase run on live; use a live-prefixed Nevermined API key.

And optionally a troubleshooting row for the mismatch (plan-not-found / wrong environment → check the key is live-prefixed).

Comment thread integrations/exa.mdx

## Verifying charges

Use `payments.delegation.listDelegations()` to inspect spend per delegation (`amountSpentCents`, `transactionCount`, status). Fully spent delegations are marked `Exhausted` and no longer appear in `getPurchasingPower()` results; purchasing power lists only delegations that can still pay.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOW — confirm the literal Exhausted status value. The structural claim is verified (exhausted delegations drop out of getPurchasingPower() — it filters on accessible: true). But Exhausted as a specific status string isn't in the SDK (DelegationSummary.status is an untyped string; the only enumerated statuses the SDK documents are Active/Revoked on payment methods), so it's backend-emitted and I can't confirm the exact casing/wording from source. Since you runtime-verified this, just double-check Exhausted matches what listDelegations() actually returns byte-for-byte — a reader will string-match on it.

@robindoble
robindoble merged commit c8c1532 into main Aug 3, 2026
2 checks passed
@robindoble
robindoble deleted the feat/exa-integration-page branch August 3, 2026 12:51
@robindoble

Copy link
Copy Markdown
Contributor Author

Follow-ups on the review comments, all landed:

  • L74 (environment warning): your read of the gate is right, and the 1.10.0 behavior is confirmed as a regression rather than a doc error: dist/payments.js passes environment: this.environmentName into its own sub-API constructors, tripping the gate you quoted with nothing caller-supplied (reproduced by four independent clean-room integrations). Filed as environment deprecation warning fires even when the caller never passes the option (1.10.0) payments#416 with the root cause and suggested fix. The troubleshooting row is reworded in docs(exa): review revisions from #266 #268 to be actionable (remove the option) with the self-firing case linked to the issue instead of called harmless.
  • L10 (live plan): added in docs(exa): review revisions from #266 #268: the Info block now states the plan runs on live with a live-prefixed key, plus a wrong-environment troubleshooting row for the sandbox-key dead end.
  • L66 (Exhausted): confirmed byte-exact. Both runtime validation runs captured status: "Exhausted" verbatim from listDelegations() after spending a delegation to zero (delegations cd44e933… and 1982b78c…, 2026-08-02/03).

Copilot's two: the ESM error reproduces on the main package import (not only the /express subpath) in four clean-room runs, so the page's claim stands; and "cannot create delegations on the fly" reflects current backend behavior for current-version API keys (#2392 in nvm-monorepo), so the stale text is in specs/x402-card-delegation.mdx, which is worth aligning separately.

🤖 Generated with Claude Code

robindoble added a commit that referenced this pull request Aug 3, 2026
- State the plan runs on live and needs a live-prefixed key (Info block)
- Reword the environment-warning troubleshooting row: actionable when the
  option is passed; link payments#416 for the 1.10.0 self-firing case
- Add a wrong-environment troubleshooting row (sandbox key vs live plan)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants