@ovra/ts-sdk 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +84 -426
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,496 +1,154 @@
1
- # Ovra TypeScript SDK
1
+ # Ovra SDK for TypeScript
2
2
 
3
- [![NPM version](https://img.shields.io/npm/v/@ovra/ts-sdk.svg)](https://www.npmjs.com/package/@ovra/ts-sdk)
4
- [![NPM downloads](https://img.shields.io/npm/dm/@ovra/ts-sdk.svg)](https://www.npmjs.com/package/@ovra/ts-sdk)
3
+ [![npm](https://img.shields.io/npm/v/@ovra/ts-sdk.svg)](https://www.npmjs.com/package/@ovra/ts-sdk)
4
+ [![downloads](https://img.shields.io/npm/dm/@ovra/ts-sdk.svg)](https://www.npmjs.com/package/@ovra/ts-sdk)
5
+ [![types](https://img.shields.io/npm/types/@ovra/ts-sdk.svg)](https://www.npmjs.com/package/@ovra/ts-sdk)
5
6
 
6
- The official TypeScript SDK for the [Ovra API](https://getovra.com) — payment
7
- infrastructure for AI agents. Issue virtual Visa cards, declare and approve
8
- spending intents, settle payments under signed mandates, and reconcile from
9
- the same typed surface.
7
+ The Ovra SDK for TypeScript provides access to the [Ovra API](https://getovra.com)
8
+ — payment infrastructure for AI agents from server-side TypeScript or JavaScript.
10
9
 
11
- **Version: `0.5.0`** — fully bound to the `/v1/*` API. Regenerated
12
- from `apps/api/openapi.json`; releases ship manually for now (see
13
- [Publishing](#publishing) below — auto-publish is wired but pending
14
- on GH Actions billing). See the repo
15
- [CHANGELOG](https://github.com/ovra/ovra/blob/main/CHANGELOG.md) for the
16
- v0 → v1 migration notes.
10
+ ## Documentation
17
11
 
18
- **0.4.0 is a breaking release.** The `/v1/credentials/*` and
19
- `/v1/authorization-grants/*` rails were removed (alongside MCP
20
- `ovra_pay`); the AP2 agentic-commerce buy is now the canonical payment
21
- flow. The `ovra.credentials` namespace is gone — use
22
- `ovra.agenticCommerce.{search, buy, getOrder, listOrders, verifyOrder,
23
- refundOrder}` instead. See "Agentic Commerce surface" below.
12
+ Full documentation lives at **[app.getovra.com/docs/quickstart](https://app.getovra.com/docs/quickstart)**.
13
+ Error reference at **[app.getovra.com/docs/errors](https://app.getovra.com/docs/errors)**.
24
14
 
25
- ## Install
15
+ ## Installation
26
16
 
27
17
  ```sh
28
18
  npm install @ovra/ts-sdk
29
19
  ```
30
20
 
31
- Requirements: Node.js 20+, or any runtime with `fetch` (Bun, Deno,
32
- Cloudflare Workers, Vercel Edge).
33
-
34
- ## Quickstart
35
-
36
- Grab an API key at [getovra.com/dashboard](https://getovra.com/dashboard) →
37
- Settings → API keys, then drop straight into the canonical **one-call buy**:
21
+ ## Getting started
38
22
 
39
23
  ```ts
40
24
  import { Ovra } from "@ovra/ts-sdk";
41
25
 
42
- const ovra = new Ovra({ apiKey: process.env.OVRA_API_KEY! });
26
+ const ovra = new Ovra({
27
+ apiKey: process.env.OVRA_API_KEY!, // sk_test_… in sandbox, sk_live_… in prod
28
+ });
43
29
 
44
- // `ovra.pay()` wraps the AP2 agentic-commerce buy — DPAN mint + the
45
- // 4-mandate AP2 chain + capture + receipt in one round-trip. Amount is
46
- // EUR (decimal); the SDK converts to cents on the wire.
47
30
  const result = await ovra.pay({
48
- agentId: "agt_…", // an active agent in your workspace
49
- offerId: "off_…", // catalog offer id (see ovra.agenticCommerce.search)
50
- merchant: "Notion",
51
- amount: 79.0, // €79.00
52
- purpose: "Monthly Notion Team Plan renewal",
31
+ agentId: "agt_…",
32
+ offerId: "aic_openai-1000",
33
+ merchant: "OpenAI",
34
+ amount: 10.0,
35
+ purpose: "Top up OpenAI credits",
53
36
  });
54
37
 
55
38
  if (result.status === "completed") {
56
- console.log(result.orderId, result.order.authorization.network_auth_code);
57
- } else {
58
- console.error("buy failed:", result.reason);
39
+ console.log(result.orderId); // cmo_…
40
+ console.log(result.order.amount); // { amount: 1000, currency: "eur" }
41
+ console.log(result.order.authorization.network_auth_code); // "000123"
59
42
  }
60
43
  ```
61
44
 
62
- Prefer the raw operation? Same call, different envelope shape:
45
+ `ovra.pay()` declares the intent, runs the policy gate, debits the wallet,
46
+ mints the DPAN, signs the 4-mandate AP2 chain, captures with the merchant,
47
+ and returns the order envelope in a single round-trip.
63
48
 
64
- ```ts
65
- const { data: order } = await ovra.agenticCommerce.buy({
66
- body: {
67
- agent_id: "agt_…",
68
- offer_id: "off_…",
69
- purpose: "Monthly Notion Team Plan renewal",
70
- },
71
- });
72
- console.log(order.order_id, order.status);
73
- ```
49
+ Need the lower-level primitives (custom approval UI, manual intent, raw
50
+ generated operations)? See [app.getovra.com/docs/quickstart](https://app.getovra.com/docs/quickstart).
74
51
 
75
- Need the lower-level intent / checkout pipeline (custom approval UI,
76
- out-of-band capture)? The primitives are still here:
52
+ ## Requirements
77
53
 
78
- ```ts
79
- // 1. Provision an agent. `policy` is required — fetch one via
80
- // `ovra.policies.list()`. `profile.purpose` is required.
81
- const { data: agent } = await ovra.agents.create({
82
- body: {
83
- name: "Notion Buyer",
84
- policy: "po_…",
85
- profile: { purpose: "Monthly Notion Team Plan renewal" },
86
- },
87
- });
88
-
89
- // 2. Declare a spending intent (`agent`, not `agent_id`).
90
- const { data: intent } = await ovra.intents.create({
91
- body: {
92
- agent: agent.id,
93
- merchant: "Notion",
94
- amount: { amount: 7900, currency: "eur" }, // €79.00
95
- purpose: "Monthly Notion Team Plan renewal",
96
- },
97
- });
98
-
99
- // 3. Approve the intent (production: this comes from the human
100
- // approving in the dashboard or a passkey assertion).
101
- await ovra.intents.approve({ path: { id: intent.id } });
102
-
103
- // 4. Execute the checkout — `intent` + `target_url` (the merchant URL
104
- // the DPAN will be submitted to) are both required.
105
- const { data: result } = await ovra.checkout.execute({
106
- body: {
107
- intent: intent.id,
108
- target_url: "https://www.notion.so/checkout",
109
- },
110
- });
111
-
112
- console.log(result.transaction_id, result.status);
113
- ```
114
-
115
- Amounts on the wire are integers in the currency's minor units
116
- (`amount: 7900` = €79.00). Card PAN / CVV are **never** returned — only
117
- `last4` and a tokenized DPAN reach your code.
54
+ Node.js 20+, or any runtime with global `fetch` (Bun, Deno, Cloudflare
55
+ Workers, Vercel Edge).
118
56
 
119
57
  ## Authentication
120
58
 
121
- The constructor accepts any Ovra credential prefix. Pick the smallest scope
122
- that fits the call site.
59
+ The constructor accepts any Ovra credential prefix. Pick the smallest
60
+ scope that fits the call site.
123
61
 
124
- | Prefix | What it is | Use when |
125
- | ------------------- | ---------------------- | ------------------------------------------------------------------- |
126
- | `sk_live_…` | Full workspace key | Server-side production code that needs to mint/rotate/manage. |
127
- | `sk_test_…` | Full key, sandbox mode | Local dev and CI; `livemode: false` on every response. |
128
- | `rk_…` / `rk_test_…` | Restricted key | Read + scoped writes; blocked from key, webhook, billing, policy mutations. Safe to embed in less-trusted runtimes. |
129
- | `at_…` | Agent token | Scoped to one agent with a hard spend cap. The credential you ship to an agent runtime. |
62
+ | Prefix | What | Use when |
63
+ | -------------- | --------------------- | ------------------------------------------------------------------------------ |
64
+ | `sk_live_…` | Full live key | Server-side prod code that mints / rotates / manages. |
65
+ | `sk_test_…` | Full sandbox key | Local dev + CI. Every envelope returns `livemode: false`. |
66
+ | `rk_…` | Restricted key | Read + scoped writes. Blocked from keys / webhooks / billing / policies. |
67
+ | `at_…` | Agent token | Bound to one agent with a hard spend cap. Safe to ship to an agent runtime. |
130
68
 
131
69
  ```ts
132
70
  const ovra = new Ovra({
133
71
  apiKey: process.env.OVRA_API_KEY!,
134
- // Sent as the `X-Ovra-Client-App` header on every request — used for
135
- // analytics and to help support trace issues back to your integration.
136
- appInfo: { name: "AcmeCRM", version: "1.4.2" },
72
+ appInfo: { name: "AcmeCRM", version: "1.4.2" }, // X-Ovra-Client-App
137
73
  });
138
74
 
139
- // Best-effort scope hint derived from the key prefix useful for
140
- // dev-time logging only; the server is the source of truth.
141
- // sk_* → "full" | rk_* → "restricted" | at_* → "agent"
142
- console.log(ovra.keyScope);
75
+ // Dev-time scope hint (not enforced server is the source of truth):
76
+ console.log(ovra.keyScope); // "full" | "restricted" | "agent" | "unknown"
143
77
  ```
144
78
 
145
- Test-mode keys produce objects with `livemode: false`; live keys produce
146
- `livemode: true`. Whenever the API is deployed against the sandbox card
147
- issuer, **every** response is `livemode: false` regardless of key — the
148
- whole workspace is sandbox until the real issuer ships.
149
-
150
- ## Money
151
-
152
- Money is `{ amount, currency }` everywhere on the wire. `amount` is an
153
- integer in minor units; `currency` is a three-letter ISO code lowercased.
154
-
155
- | Display | Wire value |
156
- | ------------ | ----------------------------------------- |
157
- | €50.00 | `{ amount: 5000, currency: "eur" }` |
158
- | €0.99 | `{ amount: 99, currency: "eur" }` |
159
- | £1,234.56 | `{ amount: 123456, currency: "gbp" }` |
160
- | ¥1,000 (JPY) | `{ amount: 1000, currency: "jpy" }` (JPY has no minor units; treat the integer as the whole-yen amount.) |
161
-
162
- Floats and decimal strings are rejected at the validation layer. There is
163
- no implicit unit conversion — what you send is what gets compared against
164
- the policy.
165
-
166
- ## Timestamps
167
-
168
- Every timestamp is an ISO 8601 string in the `created` field
169
- (`"2026-05-25T18:04:16Z"`). The legacy `created_at` / `createdAt` / epoch
170
- millis variants are gone.
171
-
172
79
  ## Errors
173
80
 
174
- API errors throw a typed subclass of `OvraError`. Branch on type, status,
175
- or preferred `code`:
81
+ Errors are typed exceptions per category branch on `e.code` (machine-
82
+ readable), show `e.message` to humans, link to `e.docUrl` from your own UI.
176
83
 
177
84
  ```ts
178
- import {
179
- Ovra,
180
- OvraError,
181
- OvraNotFoundError,
182
- OvraRateLimitError,
183
- } from "@ovra/ts-sdk";
85
+ import { OvraError } from "@ovra/ts-sdk";
184
86
 
185
87
  try {
186
- await ovra.cards.get({ path: { id: "crd_…" } });
187
- } catch (err) {
188
- if (err instanceof OvraNotFoundError) {
189
- // 404 — card doesn't exist or isn't yours
190
- } else if (err instanceof OvraRateLimitError) {
191
- // 429 — back off and retry
192
- } else if (err instanceof OvraError && err.code === "E_POLICY_DENIED") {
193
- // policy gate refused the spend; `err.message` is the human string,
194
- // `err.param` points at the offending body field if any.
195
- } else {
196
- throw err;
88
+ await ovra.pay({ agentId, offerId, merchant, amount });
89
+ } catch (e) {
90
+ if (!(e instanceof OvraError)) throw e;
91
+ switch (e.code) {
92
+ case "E_INSUFFICIENT_FUNDS": return topUpAndRetry();
93
+ case "E_POLICY_LIMIT_EXCEEDED": return showLimits(e.message);
94
+ case "E_OFFER_EXPIRED": return refreshOffer();
95
+ case "E_FSM_INVALID_TRANSITION": return refetchOrder();
96
+ default: return reportError(e.message, e.docUrl);
197
97
  }
198
98
  }
199
99
  ```
200
100
 
201
- On the wire, every error body matches the v1 envelope:
202
-
203
- ```json
204
- {
205
- "error": {
206
- "type": "policy_error",
207
- "code": "E_POLICY_DENIED",
208
- "message": "Spend exceeds the configured policy limit.",
209
- "param": "amount",
210
- "doc_url": "https://docs.getovra.com/errors/E_POLICY_DENIED",
211
- "request_id": "req_…",
212
- "status": 403
213
- }
214
- }
215
- ```
216
-
217
- The thrown `OvraError` flattens that envelope onto the instance —
218
- `err.type`, `err.code`, `err.message`, `err.param`, `err.docUrl`,
219
- `err.requestId`, `err.status`. Branch on `err.code` — it's typed,
220
- ~50 canonical values, stable across releases. Never parse `err.message`
221
- — it's a human string and may change.
101
+ Every envelope carries `code`, `type`, `message`, `param`, `docUrl`,
102
+ `requestId`, `status`. Full reference: [app.getovra.com/docs/errors](https://app.getovra.com/docs/errors).
222
103
 
223
104
  ## Idempotency
224
105
 
225
- Mutating requests (`POST`, `PATCH`, `DELETE`) require an `Idempotency-Key`
226
- header. **The SDK auto-mints a fresh UUID per call**, so retries through
227
- the built-in retry policy are safe by default. Override per-call when you
228
- want explicit deduplication across processes:
106
+ Every mutating call is idempotent by default — the SDK mints a UUID
107
+ `Idempotency-Key` per logical operation and reuses it across retries.
108
+ Replays inside the 24h dedup window return the original response with
109
+ `X-Idempotent-Replayed: true`. Pass your own key for cross-process dedup:
229
110
 
230
111
  ```ts
231
- await ovra.transfers.create({
232
- headers: { "Idempotency-Key": "transfer-2026-q2-invoice-4711" },
233
- body: {
234
- from_wallet: "wal_…",
235
- to_beneficiary: "ben_…",
236
- amount: { amount: 250000, currency: "eur" },
237
- },
112
+ await ovra.intents.create({
113
+ body: { agent: "agt_…", merchant: "Notion", amount: { amount: 7900, currency: "eur" }, purpose: "…" },
114
+ headers: { "Idempotency-Key": "your-stable-key" },
238
115
  });
239
116
  ```
240
117
 
241
- Re-sending the same key + identical body returns the original response.
242
- Re-sending the same key with a *different* body returns
243
- `E_IDEMPOTENCY_CONFLICT` (HTTP 409). An in-flight collision returns
244
- `E_IDEMPOTENCY_IN_FLIGHT`.
118
+ ## MCP server
245
119
 
246
- ## Pagination
247
-
248
- Every list method is cursor-paginated and returns the canonical envelope
249
- directly — the SDK auto-strips hey-api's outer `{data, request, response}`
250
- wrapper for any `list*` call so you get the list shape verbatim:
251
-
252
- ```ts
253
- const page1 = await ovra.cards.list({ query: { limit: 50 } });
254
- // ^? { object: "list", data: Card[], has_more, next_cursor, url }
255
-
256
- for (const card of page1.data) {
257
- console.log(card.id, card.last4);
258
- }
259
-
260
- if (page1.has_more) {
261
- const page2 = await ovra.cards.list({
262
- query: { limit: 50, starting_after: page1.next_cursor! },
263
- });
264
- }
265
- ```
266
-
267
- Or use the `paginate` helper to iterate the full set:
268
-
269
- ```ts
270
- import { paginate } from "@ovra/ts-sdk";
271
-
272
- for await (const card of paginate(
273
- (args) => ovra.cards.list({ query: args }),
274
- { limit: 50 },
275
- )) {
276
- console.log(card.id, card.last4);
277
- }
278
- ```
279
-
280
- The wire envelope (what `page1` deserializes to):
120
+ Want to call Ovra from Claude / Cursor / any MCP client? The same surface
121
+ ships as [`@ovra/mcp`](https://www.npmjs.com/package/@ovra/mcp) (10 tools).
122
+ Add to `.mcp.json`:
281
123
 
282
124
  ```json
283
125
  {
284
- "object": "list",
285
- "data": [ /* … */ ],
286
- "has_more": true,
287
- "next_cursor": "card_01HE…",
288
- "url": "/v1/cards"
289
- }
290
- ```
291
-
292
- ## Retries
293
-
294
- Connection errors and 5xx / 429 / 408 responses retry automatically with
295
- jittered exponential backoff (500 ms → 4 s, 30 s wall-clock budget).
296
- Tune or disable per-client:
297
-
298
- ```ts
299
- const ovra = new Ovra({
300
- apiKey: "…",
301
- retry: { maxRetries: 5, maxElapsedMs: 60_000 },
302
- // or: retry: false
303
- });
304
- ```
305
-
306
- ## Agentic Commerce surface
307
-
308
- The AP2 sandbox is the canonical buy pipeline as of 0.4.0. Catalog
309
- discovery, the buy orchestrator, and the UCP-shaped order envelope
310
- (line_items / fulfillment / adjustments / totals / permalink_url) all
311
- live under `ovra.agenticCommerce`:
312
-
313
- ```ts
314
- // Browse the 10-vertical catalog
315
- const offers = await ovra.agenticCommerce.search({
316
- body: { vertical: "saas-subscriptions", query: { merchant: "notion", plan: "team" } },
317
- });
318
-
319
- // One-call buy — mints DPAN + signs the 4-mandate AP2 chain + captures.
320
- // The route reads `agent_id`, `offer_id`, `purpose`, optional `card_id`
321
- // + `intent_id`. Amount + merchant are derived from the offer.
322
- const order = await ovra.agenticCommerce.buy({
323
- body: {
324
- agent_id: "agt_…",
325
- offer_id: "off_…",
326
- purpose: "Monthly Notion Team Plan renewal",
327
- },
328
- });
329
-
330
- // Re-verify the AP2 chain against the cached mandate set
331
- const check = await ovra.agenticCommerce.verifyOrder({
332
- path: { order_id: order.data.order_id },
333
- });
334
-
335
- // UCP-conformant refund — append to adjustments, debit totals, flip
336
- // status to REFUNDED (full) or COMPENSATED (partial)
337
- await ovra.agenticCommerce.refundOrder({
338
- path: { order_id: order.data.order_id },
339
- body: { amount_cents: 7900, reason: "customer cancelled" },
340
- });
341
- ```
342
-
343
- ## Resource coverage
344
-
345
- `Ovra` binds every `/v1/*` resource as an ergonomic namespace —
346
- 33 namespaces, 141 operations total, all of them auto-typed from the
347
- generated client. Listed by domain:
348
-
349
- ### Money
350
-
351
- - `wallets` — `list`, `create`, `get`, `update`, `delete`
352
- - `transfers` — `list`, `create`, `get`
353
- - `beneficiaries` — `list`, `create`, `get`, `update`, `delete`
354
- - `refunds` — `list`, `create`, `get`
355
- - `paymentRequests` — `list`, `create`, `get`, `cancel`
356
- - `ledgerEntries` — `list`, `get` (double-entry ledger, read-only)
357
- - `billing` — `getSubscription`, `createSubscription`,
358
- `createPortalSession`, `getPaymentMethod`, `setupPaymentMethod`,
359
- `fundWallet`, `getSepaInstructions`, `getBalance`, `collectOverage`
360
- - `invoices` — `list`, `get`
361
-
362
- ### Agents & spending
363
-
364
- - `agents` — `list`, `create`, `get`, `update`, `delete`, `freeze`,
365
- `unfreeze`, `getByExternalId`
366
- - `cards` — `list`, `create`, `get`, `update`, `freeze`, `unfreeze`,
367
- `close`, `rotate`
368
- - `intents` — `list`, `create`, `get`, `approve`, `deny`, `cancel`,
369
- `issueCredentials`, `confirmPayment`
370
- - `transactions` — `list`, `get` (read-only)
371
- - `checkout` — `execute`, `confirm`
372
- - `agenticCommerce` — `listVerticals`, `search`, `getOffer`,
373
- `getMerchantJwk`, `buy`, `listOrders`, `getOrder`, `verifyOrder`,
374
- `refundOrder`
375
- - `runs` — `create`, `get`
376
- - `outcomes` — `list`, `create`, `get`
377
- - `forecast` — `get`
378
- - `pay()` — one-call buy convenience wrapper around
379
- `agenticCommerce.buy`
380
-
381
- ### Compliance & governance
382
-
383
- - `policies` — `list`, `create`, `get`, `update`, `delete`, `apply`
384
- - `approvalPolicies` — `create`, `get`, `update`, `delete`
385
- - `disputes` — `list`, `create`, `get`, `resolve`, `listEvidence`,
386
- `addEvidence` (nested per-dispute)
387
- - `disputeEvidence` — `list`, `create` (standalone file uploads)
388
- - `riskEvents` — `list`, `listViolations`, `listFraudAlerts`,
389
- `updateFraudAlert`, `getAgentRisk`, `unfreezeAgent`, `getConfig`,
390
- `updateConfig`, `getSummary`
391
- - `auditEvents` — `list`, `get`, `verifyChain` (tamper-evident)
392
- - `accessEvents` — `list`, `get`
393
- - `metrics` — `list`
394
-
395
- ### Identity & access
396
-
397
- - `customers` — `me`, `create`, `get`, `update`
398
- - `apiKeys` — `list`, `create`, `get`, `delete` (requires `sk_*` scope)
399
- - `delegations` — `list`, `create`, `get`, `delete` (mint `at_*` tokens)
400
- - `passkeys` — `list`, `revoke`
401
- - `merchantCategories` — `list`, `get` (MCC lookup)
402
-
403
- ### Webhooks & notifications
404
-
405
- - `webhooks` — `list`, `create`, `get`, `update`, `delete`,
406
- `rotateSecret`, `ping`, `listDeliveries`
407
- - `notifications` — `list`, `unreadCount`, `markRead`, `markAllRead`
408
- (user-scoped — token credential, not `sk_*`)
409
- - `pushSubscriptions` — `getVapidPublicKey`, `register`, `delete`
410
- (Web Push for the approve PWA)
411
-
412
- ### Scope requirements
413
-
414
- Most write namespaces require an `sk_*` workspace key. The following
415
- will 403 with a restricted (`rk_*`) or agent (`at_*`) token:
416
-
417
- - `apiKeys.*`, `delegations.create|delete`, `webhooks.*` mutations,
418
- `policies.*` mutations, `approvalPolicies.*`, `billing.*` mutations,
419
- `riskEvents.updateConfig|unfreezeAgent`, `customers.create|update`
420
-
421
- Reads on those surfaces are allowed with `rk_*`. `notifications`,
422
- `pushSubscriptions`, and `passkeys` are user-scoped — they want a
423
- session credential, not a workspace key.
424
-
425
- ### Plan requirements
426
-
427
- A handful of namespaces are gated on the workspace's billing plan and
428
- will throw `E_PLAN_UPGRADE_REQUIRED` (HTTP 402) or
429
- `E_PERMISSION_DENIED` (HTTP 403) on Starter:
430
-
431
- - **Business plan or higher** — `auditEvents.*`, `metrics.*`,
432
- `riskEvents.*`, `delegations.*`
433
-
434
- Catch the error and surface the upgrade prompt:
435
-
436
- ```ts
437
- try {
438
- await ovra.auditEvents.list();
439
- } catch (err) {
440
- if (err instanceof OvraError && err.code === "E_PLAN_UPGRADE_REQUIRED") {
441
- // route the user to getovra.com/dashboard/billing
126
+ "mcpServers": {
127
+ "ovra": {
128
+ "command": "npx",
129
+ "args": ["-y", "@ovra/mcp"],
130
+ "env": { "OVRA_API_KEY": "sk_test_…" }
131
+ }
442
132
  }
443
133
  }
444
134
  ```
445
135
 
446
- ### Tree-shaking
447
-
448
- Prefer raw functions over the class? Every operation is also exported
449
- from `@ovra/ts-sdk/api`:
450
-
451
- ```ts
452
- import { listApiKeys } from "@ovra/ts-sdk/api";
453
- const keys = await listApiKeys({ query: { limit: 10 } });
454
- ```
455
-
456
- The full inventory is in `apps/api/openapi.json` (single source of
457
- truth — the SDK is regenerated from it on every release).
458
-
459
- ## Publishing
460
-
461
- > **Status (2026-05-28):** auto-publish via
462
- > `.github/workflows/sdk-publish.yaml` is wired correctly but
463
- > **currently blocked at the runner-allocation step** — the GitHub
464
- > account has a billing issue ("recent account payments have failed
465
- > or your spending limit needs to be increased"). All workflow runs
466
- > exit in ~3-5 s before the YAML steps start. Until billing is
467
- > restored, every release ships via the manual script below; both
468
- > `0.4.0` and `0.4.1` were published this way.
136
+ ## Resource coverage
469
137
 
470
- Manual release flow (single command runs regen + build + version
471
- check + `npm publish`):
138
+ 33 typed namespacesagents, cards, wallets, intents, transactions,
139
+ agentic-commerce (search / buy / order / refund / verify), policies,
140
+ delegations, customers, disputes, webhooks, audit, billing, and 20 more.
141
+ Generated functions for every operation are also accessible as raw exports.
472
142
 
473
- ```sh
474
- # Bump packages/sdk/package.json version first (semver: patch / minor / major)
475
- pnpm --filter @ovra/ts-sdk version patch --no-git-tag-version
476
-
477
- # Then publish (refuses if local <= remote, or if git tree is dirty)
478
- pnpm run publish:sdk # or: pnpm --filter @ovra/ts-sdk run publish-manual
479
- pnpm run publish:sdk:dry # dry-run (no upload, full pipeline otherwise)
480
- ```
143
+ See the [API reference](https://app.getovra.com/docs/errors) for the full
144
+ list with scope and plan requirements.
481
145
 
482
- The script lives at `scripts/publish-sdk.sh`. Requirements: logged in
483
- to npm as a publisher on the `@ovra` scope (`npm login`), clean git
484
- tree, local version strictly greater than the version currently on
485
- npm.
146
+ ## Support
486
147
 
487
- Once GH Actions billing is restored, every push to `main` that
488
- touches `apps/api/openapi.json`, `packages/sdk/src/**`,
489
- `packages/sdk/openapi-ts.config.ts`, or `packages/sdk/package.json`
490
- will regenerate, bump (patch), and publish automatically — the
491
- workflow is already in place.
148
+ - Documentation: [app.getovra.com/docs/quickstart](https://app.getovra.com/docs/quickstart)
149
+ - Issues: [github.com/ovra/ovra/issues](https://github.com/ovra/ovra/issues)
150
+ - Email: support@getovra.com
492
151
 
493
152
  ## License
494
153
 
495
- Commercialsee [LICENSE](./LICENSE). The Ovra service requires a paid
496
- subscription.
154
+ UNLICENSEDinternal use only until the public release lands.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ovra/ts-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Official TypeScript SDK for the Ovra API — payment infrastructure for AI agents.",
5
5
  "author": "Ovra",
6
6
  "license": "SEE LICENSE IN LICENSE",