tixbit 0.1.1 → 0.1.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.
package/README.md CHANGED
@@ -1,8 +1,25 @@
1
1
  # tixbit
2
2
 
3
- Search events, view seatmaps, browse listings, and buy tickets on [TixBit](https://tixbit.com) — from the terminal, your code, or an AI agent.
3
+ Search events, view seatmaps, browse listings, get browser checkout links, and purchase through MPP on [TixBit](https://www.tixbit.com) — from the terminal, your code, or an AI agent.
4
4
 
5
- No API key required.
5
+ No command requires a TixBit developer API key. Public discovery and links need no credentials. Purchases require user-approved payment; selling requires user sign-in and seller access.
6
+
7
+ ### User authorization, not API keys
8
+
9
+ Run `tixbit auth` for public browser sign-in and wallet setup links. This command does not create a CLI session. Open the returned TixBit sign-in page, then complete checkout or selling in your browser. Do not copy browser cookies or bearer tokens.
10
+
11
+ The public service currently has no supported browser-to-CLI seller session exchange. Website sign-in therefore does not unlock seller API calls from this CLI. Checkout discovery also does not expose the merchant identity needed for automatic Link shared-payment-token authorization. The CLI does not guess it or invent a login endpoint.
12
+
13
+ For wallet setup, use [official Link onboarding](https://link.com/agents): install `@stripe/link-cli` and run `link-cli onboard`. This requires your Link account, not a developer API key. It does not by itself authorize this CLI to charge TixBit. Browser checkout is the normal path until automatic authorization is supported; MPP remains available with your wallet.
14
+
15
+ | Operation | Required user authorization |
16
+ |---|---|
17
+ | Search, browse, listings, quote, seatmap, URL, checkout link | None |
18
+ | `buy` quote | Buyer email via `--email` or optional `TIXBIT_EMAIL` |
19
+ | Browser purchase | Sign in and approve the final payment in the browser |
20
+ | MPP `purchase` | Your mppx wallet, buyer email, confirmation, total cap, recovery UUID |
21
+ | Automatic Link payment | User-approved payment credential from an authorized integration |
22
+ | Seller API | Signed-in user credential and seller access |
6
23
 
7
24
  ## Install
8
25
 
@@ -26,7 +43,7 @@ npm install tixbit
26
43
  tixbit search "Taylor Swift"
27
44
  tixbit search "Hawks" --state GA --size 5
28
45
  tixbit search --city "New York" --category nba-basketball
29
- tixbit search --start-date 2025-06-01 --end-date 2025-06-30
46
+ tixbit search --league NBA --parking exclude
30
47
  ```
31
48
 
32
49
  ### Browse local events
@@ -39,80 +56,109 @@ tixbit browse --lat 33.749 --lng -84.388 --category CONCERT
39
56
  ### Get ticket listings
40
57
 
41
58
  ```sh
42
- tixbit listings 4BKJMDZ
43
- tixbit listings 4BKJMDZ --size 5 --sort asc
59
+ tixbit listings <event-id>
60
+ tixbit listings <event-id> --size 5 --sort asc
44
61
  ```
45
62
 
46
63
  ### Buy tickets
47
64
 
48
65
  ```sh
49
66
  # Get a checkout link for a listing
50
- tixbit checkout P2JO5OBX --quantity 2
51
- ```
52
-
67
+ tixbit checkout <listing-id> --quantity 2
68
+
69
+ # Or pay from an agent/terminal with MPP
70
+ npx mppx account create
71
+ tixbit purchase <listing-id> \
72
+ --quantity 2 \
73
+ --email buyer@example.com \
74
+ --confirm --max-price 300.00 \
75
+ --idempotency-key 11111111-1111-4111-8111-111111111111 \
76
+ --json
53
77
  ```
54
- 🎟 Checkout Link
55
78
 
56
- Listing: P2JO5OBX
57
- Section: 214 Row E
58
- Price: $23.80 × 2 = $47.60
59
- Quantity: 2
79
+ `checkout` remains link-only: it creates a `https://www.tixbit.com/checkout/process` URL for browser completion. `purchase` is the separate public MPP machine surface. It uses the official `mppx` client to answer the server's HTTP 402 challenge and currently selects the Tempo one-time charge rail configured by the server.
60
80
 
61
- https://tixbit.com/checkout/process?listing=P2JO5OBX&quantity=2
81
+ `--email` is always required and is never inferred from git or local account state. If a request times out or returns `pending` or `manual_review_required`, reuse the same idempotency key and follow the returned `action`; do not start another payment.
62
82
 
63
- Open the link above in your browser to complete checkout.
64
- ```
83
+ ### Live inventory, Stripe Link, and seller commands
65
84
 
66
- ### View venue seatmap
85
+ These additions require a build of this PR or a later authorized package release. The existing registry package is still named `tixbit`; this PR does not publish it.
67
86
 
68
87
  ```sh
69
- tixbit seatmap 4BKJMDZ
70
- tixbit seatmap 4BKJMDZ --section 214
88
+ # Refreshed listings, not a reservation. Fails if live freshness is unavailable.
89
+ tixbit quote <eventId> --page 1 --size 100
90
+
91
+ # Buyer email is explicit; no API key or payment credential is needed.
92
+ tixbit buy <listingId> --quantity 2 --max-price 300.00 --email buyer@example.com
93
+
94
+ # Without payment authorization, returns a browser checkout handoff.
95
+ # No payment is sent; review and approve the final total in the browser.
96
+ tixbit buy <listingId> --quantity 2 --max-price 300.00 --email buyer@example.com --confirm
97
+
98
+ # Without a signed-in integration, returns browser sign-in and seller links.
99
+ tixbit sell list
71
100
  ```
72
101
 
102
+ A handoff returns `success: false`, `status: "authorization_required"`, and exit code 2. It is not a completed purchase, listing, or CLI login. The CLI cap is not transferred to browser checkout; review and approve the final total there.
103
+
104
+ ### Optional advanced integrations
105
+
106
+ Authorized applications may supply a user-approved Link payment credential or a signed-in seller's Privy access token. Optional `TIXBIT_LINK_TOKEN` and `TIXBIT_ACCESS_TOKEN` injection is for these integrations only, not normal onboarding. Neither is a TixBit API key, and no developer or infrastructure key can replace user authorization. Never pass credentials in arguments, log them, or extract them from browser storage. Seller integrations use `tixbit sell create --confirm < listing.json`.
107
+
108
+ `--max-price` is the total USD charge ceiling including ticket fees, not a per-ticket price or a bid. Link checkout sends `maxAmountCents` in both POST requests and refuses payment unless the quote advertises `maxAmountCentsSupported: true`. Payment requires a public checkout deployment that advertises and enforces the total cap. The backend rechecks its actual charge before payment. Link currently accepts only 4-12 alphanumeric listing IDs. Native `sl_UUID` listings are not supported by this payment backend; use link-only `checkout` for browser completion instead.
109
+
110
+ No Link payment request is automatically retried. An uncertain Link response returns `status: "unknown"` and requires reconciliation with TixBit support and Stripe Link before another attempt. A successful payment response is not a guarantee of completed ticket delivery. No negotiation API or command is provided.
111
+
112
+ Seller JSON uses the existing web API schema. Example after seller approval:
113
+
114
+ ```json
115
+ {"externalEventId":"AbCd12","section":"GA","quantity":2,"generalAdmission":true,"priceCents":10000,"termsAccepted":true}
73
116
  ```
74
- 🏟 State Farm Arena
75
- NBA - Atlanta Hawks
76
- Capacity: 18,118
77
117
 
78
- ── ⬇ Lower Level (100s) ──
79
- 101 102 103 ... 122
118
+ `priceCents` is the seller's per-ticket asking price, unlike the buyer's total cap. Optional fields include `row`, `seatNumbers`, `faceValueCents`, `assetPaths`, `disclosures`, and `notes`; the server validates them and enforces seller access. Creation requires both `--confirm` and `termsAccepted: true`. Submission is not a claim that the listing is live. After uncertain creation, inspect `sell list` before retrying.
80
119
 
81
- ── ⬆ Upper Level (200s) ──
82
- 201 202 203 ▸214◂ ... 227S
120
+ MPP `purchase` retains the official mppx path but now requires `--confirm`, `--max-price`, and an explicit `--idempotency-key` before wallet loading. Its challenge hook checks the pathUSD atomic amount before any credential is created, rejects unknown assets/recurring intents, and permits only one payment challenge. The cap covers the ticket charge; network fees, if any, are managed separately by the wallet. SDK callers who inject their own `paymentFetch` own its authorization policy: use `assertMppChallenge` in `onChallenge` as shown below and get user approval before calling `purchaseTickets`. Do not register credential-producing event handlers that bypass this hook.
83
121
 
84
- 📍 Section 214: right side
122
+ ### View venue seatmap
85
123
 
86
- Total sections: 142
124
+ ```sh
125
+ tixbit seatmap <event-id>
126
+ tixbit seatmap <event-id> --section <section-name>
87
127
  ```
88
128
 
89
129
  ### JSON output (for agents / scripting)
90
130
 
91
- Every command supports `--json` for machine-readable output:
131
+ Every command now emits JSON by default, including help, version, parser errors, and request errors. `--json` remains accepted. Successful discovery results keep their existing fields and add `success: true`. Exit codes: 0 for success, 1 for invalid input/request failure, 2 for a non-final or unsuccessful result.
92
132
 
93
- > Event IDs are normalized to public external IDs (e.g. `36PB9ZN`) — internal provider prefixes are stripped from SDK/CLI results.
133
+ > Event and listing IDs are case-sensitive. Copy the full ID from discovery. The SDK no longer changes case, strips prefixes, or repairs whitespace in purchase IDs.
94
134
 
95
135
  ```sh
96
136
  tixbit search "concert" --state NY --json
97
- tixbit listings 4BKJMDZ --json
98
- tixbit seatmap 4BKJMDZ --json
99
- tixbit checkout P2JO5OBX --quantity 2 --json
137
+ tixbit listings <event-id> --json
138
+ tixbit seatmap <event-id> --json
139
+ tixbit checkout <listing-id> --quantity 2 --json
140
+ tixbit purchase <listing-id> --quantity 2 --email buyer@example.com --confirm --max-price 300.00 --idempotency-key <uuid-v4> --json
100
141
  ```
101
142
 
102
143
  ### All commands
103
144
 
104
145
  | Command | Description |
105
146
  |---|---|
147
+ | `auth` | Public browser sign-in and wallet setup; no CLI session is created |
106
148
  | `search [query]` | Search events by keyword, city, state, category, or date |
107
149
  | `browse` | Browse upcoming events near a location |
108
150
  | `listings <eventId>` | Get available ticket listings for an event |
109
151
  | `checkout <listingId>` | Get a checkout link to buy tickets |
152
+ | `purchase <listingId>` | Buy a selected listing through MPP with explicit confirmation and total cap |
153
+ | `quote <eventId>` | Refresh live listings, with freshness metadata |
154
+ | `buy <listingId>` | Quote or confirm a capped Stripe Link purchase |
155
+ | `sell list` / `sell create` | Use the existing gated seller API |
110
156
  | `seatmap <eventId>` | Show the venue seating chart with all sections |
111
157
  | `url <slug>` | Print the TixBit event page URL |
112
158
 
113
159
  ## SDK
114
160
 
115
- Use the client programmatically in any Node.js 20+ project:
161
+ Use the client programmatically in a supported Node.js project:
116
162
 
117
163
  ```ts
118
164
  import { TixBitClient } from "tixbit";
@@ -126,22 +172,34 @@ const { events } = await tixbit.searchEvents({
126
172
  size: 5,
127
173
  });
128
174
 
175
+ const event = events[0];
176
+ if (!event) throw new Error("No matching events");
177
+
178
+ // Get public event detail
179
+ const detail = await tixbit.getEvent(event.external_event_id);
180
+
129
181
  // Get listings
130
182
  const { listings } = await tixbit.getListings({
131
- eventId: events[0].external_event_id,
183
+ eventId: event.external_event_id,
132
184
  });
133
185
 
186
+ const listing = listings[0];
187
+ if (!listing) throw new Error("No available listings");
188
+
189
+ // Get current public details for one listing
190
+ const listingDetail = await tixbit.getListing(listing.id);
191
+
134
192
  // Create a checkout link
135
193
  const checkout = tixbit.createCheckoutLink({
136
- listingId: listings[0].id,
194
+ listingId: listingDetail.listing.id,
137
195
  quantity: 2,
138
196
  });
139
197
  console.log(checkout.url);
140
- // → "https://tixbit.com/checkout/process?listing=P2JO5OBX&quantity=2"
198
+ // Open this TixBit URL in a browser to complete checkout.
141
199
 
142
200
  // View seatmap
143
201
  const seatmap = await tixbit.getSeatmap({
144
- eventId: events[0].external_event_id,
202
+ eventId: event.external_event_id,
145
203
  });
146
204
  console.log(seatmap.venue_name); // "State Farm Arena"
147
205
  console.log(seatmap.section_names); // ["101", "102", ...]
@@ -153,8 +211,42 @@ const nearby = await tixbit.browse({
153
211
  });
154
212
 
155
213
  // Event URL
156
- const url = tixbit.eventUrl("4BKJMDZ");
157
- // → "https://tixbit.com/events/4BKJMDZ"
214
+ const url = tixbit.eventUrl(event.external_event_id);
215
+ ```
216
+
217
+ ### SDK machine purchase
218
+
219
+ Wire the official `mppx` client into `paymentFetch`. The private payment key stays in the mppx account/keychain or `MPPX_PRIVATE_KEY`; it is never passed to TixBit SDK configuration.
220
+
221
+ ```ts
222
+ import { TixBitClient, assertMppChallenge } from "tixbit";
223
+ import { Mppx, tempo } from "mppx/client";
224
+ import { resolveAccount } from "mppx/cli";
225
+
226
+ const account = await resolveAccount();
227
+ const payments = Mppx.create({
228
+ methods: [tempo({ account })],
229
+ polyfill: false,
230
+ maxPaymentRetries: 1,
231
+ onChallenge: async (challenge) => {
232
+ assertMppChallenge(challenge, 30000); // approved TOTAL, in USD cents
233
+ return undefined;
234
+ },
235
+ });
236
+ const tixbit = new TixBitClient({
237
+ paymentFetch: (input, init) => payments.fetch(input, init),
238
+ });
239
+
240
+ const result = await tixbit.purchaseTickets({
241
+ listingId: "LISTING123",
242
+ quantity: 2,
243
+ email: "buyer@example.com",
244
+ idempotencyKey: "11111111-1111-4111-8111-111111111111",
245
+ });
246
+
247
+ console.log(JSON.stringify(result, null, 2));
248
+ // fulfilled: { status, orderReference, receiptUrl, order, ... }
249
+ // recovery: { status: "pending" | "manual_review_required", action, ... }
158
250
  ```
159
251
 
160
252
  ## API Reference
@@ -163,9 +255,12 @@ const url = tixbit.eventUrl("4BKJMDZ");
163
255
 
164
256
  | Option | Type | Default |
165
257
  |---|---|---|
166
- | `baseUrl` | `string` | `https://tixbit.com` |
258
+ | `baseUrl` | `string` | `https://www.tixbit.com` |
167
259
  | `timeoutMs` | `number` | `15000` |
168
- | `apiKey` | `string` | — |
260
+ | `paymentEndpoint` | `string` | `https://mcp.tixbit.com/api/purchase`; canonical endpoint or loopback QA only |
261
+ | `paymentFetch` | `typeof fetch` | Fetch used for MPP; supply the official `mppx.fetch` |
262
+
263
+ All public TixBit SDK operations require no TixBit API key. MPP payment credentials are handled by the configured payment client and are sent only in the standard payment authorization header.
169
264
 
170
265
  ### `searchEvents(params?)`
171
266
 
@@ -175,10 +270,23 @@ const url = tixbit.eventUrl("4BKJMDZ");
175
270
  | `city` | `string` | City name |
176
271
  | `state` | `string` | 2-letter state code |
177
272
  | `category` | `string` | Category slug (e.g. `nba-basketball`) |
273
+ | `league` | `string` | League abbreviation |
274
+ | `categoryEventType` | `string` | `SPORT`, `CONCERT`, `THEATER`, or `ALL` |
275
+ | `performerId` | `string` | Public performer ID |
276
+ | `venueId` | `string` | Public venue ID |
277
+ | `parkingFilter` | `string` | `exclude`, `only`, or `include` |
278
+ | `nearLat` / `nearLng` | `number` | Coordinates for manual location filtering |
279
+ | `locationMode` | `string` | `inferred`, `manual`, or `none` |
178
280
  | `startDate` | `string` | ISO date — events on/after |
179
281
  | `endDate` | `string` | ISO date — events on/before |
180
282
  | `page` | `number` | Page number (default: 1) |
181
- | `size` | `number` | Results per page (default: 25) |
283
+ | `size` | `number` | Results per page, max 200 (default: 25) |
284
+
285
+ The result includes normalized events plus `page`, `size`, nullable `total`/`totalPages`, `hasNext`, `hasPrev`, and `totalExact` pagination metadata.
286
+
287
+ ### `getEvent(eventId)`
288
+
289
+ Returns the sanitized public event detail for an external event ID or event slug.
182
290
 
183
291
  ### `browse(params?)`
184
292
 
@@ -189,20 +297,37 @@ const url = tixbit.eventUrl("4BKJMDZ");
189
297
  | `latitude` | `number` | Latitude |
190
298
  | `longitude` | `number` | Longitude |
191
299
  | `categoryEventType` | `string` | `SPORT`, `CONCERT`, `THEATER`, or `ALL` |
300
+ | `page` | `number` | Page number (default: 1) |
192
301
  | `size` | `number` | Number of results (default: 18) |
302
+ | `query` | `string` | Optional free-text query |
303
+ | `category` | `string` | Category slug |
304
+ | `league` | `string` | League abbreviation |
305
+ | `context` | `string` | `homepage`, `events`, or `category` |
306
+ | `recommendation` | `string` | `upcoming` or `trending` |
307
+ | `parkingFilter` | `string` | `exclude`, `only`, or `include` |
308
+
309
+ The result preserves the public browse endpoint's `total`, `totalExact`, `hasMore`, `page`, `pageSize`, and optional `degraded` metadata.
193
310
 
194
311
  ### `getListings(params)`
195
312
 
196
313
  | Param | Type | Description |
197
314
  |---|---|---|
198
315
  | `eventId` | `string` | External event ID |
199
- | `size` | `number` | Page size (default: 50) |
316
+ | `size` | `number` | Page size, max 100 (default: 50) |
200
317
  | `page` | `number` | Page number (default: 1) |
201
318
  | `orderByDirection` | `string` | `asc` or `desc` by price |
319
+ | `includeAll` | `boolean` | Request all available listings |
320
+ | `refresh` | `boolean` | Bypass cached listings for this request |
321
+
322
+ The result includes cache state, freshness, expiry, and pagination metadata when returned by the public endpoint.
323
+
324
+ ### `getListing(listingId)`
325
+
326
+ Returns one sanitized public listing and any public disclosures for it.
202
327
 
203
328
  ### `createCheckoutLink(params)`
204
329
 
205
- Create a checkout URL for a listing. The user opens this in a browser to complete their purchase on tixbit.com.
330
+ Create a checkout URL for a listing. The user opens this in a browser to review and complete the purchase on TixBit. This link-only method is unchanged by machine checkout.
206
331
 
207
332
  | Param | Type | Description |
208
333
  |---|---|---|
@@ -211,28 +336,58 @@ Create a checkout URL for a listing. The user opens this in a browser to complet
211
336
 
212
337
  Returns `{ url, listingId, quantity }`.
213
338
 
339
+ ### `purchaseTickets(params)`
340
+
341
+ Purchase a selected listing and quantity through the public MPP endpoint. TixBit prepares inventory and determines the listing price, currency, fees, and final amount on the server before issuing the challenge.
342
+
343
+ | Param | Type | Description |
344
+ |---|---|---|
345
+ | `listingId` | `string` | Listing ID selected from current listings |
346
+ | `quantity` | `number` | Number of tickets (1–8) |
347
+ | `email` | `string` | Required buyer email; normalized and validated before the request |
348
+ | `name` | `string` | Optional buyer/recipient name |
349
+ | `idempotencyKey` | `string` | Unguessable UUID v4 retry/recovery identity; generated when omitted |
350
+
351
+ Returns agent-readable JSON with `status`, `idempotencyKey`, `orderReference`, `receiptUrl` when available, optional server-authoritative `order`, and an `action` for non-final states. Network ambiguity resolves to `pending` instead of claiming failure.
352
+
353
+ ### Agent SDK methods
354
+
355
+ - `quoteListings(params: GetListingsParams)` requests refreshed listings and requires live freshness. It preserves the existing listings result shape.
356
+ - `buyTickets({ listingId, quantity, email, maxAmountCents, confirm?, sharedPaymentToken? })` quotes by default. `confirm: true` requires a Link token and server cap support. It never retries a payment; ambiguous outcomes return `success: false`, `status: "unknown"`, and a recovery action.
357
+ - `getAuthorizationInfo()` returns public browser sign-in and wallet setup links without creating a CLI session.
358
+ - `listSellerListings(accessToken?)` reads the gated seller API, or returns browser sign-in guidance when no user credential is supplied.
359
+ - `createSellerListing(body, accessToken, confirm)` requires `confirm === true` and explicit `termsAccepted: true`. The web API remains the seller schema and access authority.
360
+ - `assertMppChallenge(challenge, maxAmountCents)` rejects unsupported or over-cap MPP challenges. Use it before credential creation in an official mppx `onChallenge` hook, not after `paymentFetch` returns.
361
+
214
362
  ### `getSeatmap(params)`
215
363
 
216
364
  | Param | Type | Description |
217
365
  |---|---|---|
218
366
  | `eventId` | `string` | External event ID |
219
367
 
220
- Returns venue info, section list, zone groupings, absolute asset URLs (`background_image`, `coordinates_url`), and per-section `shape_path` data for overlay rendering.
368
+ Returns venue info, section list, zone groupings, first-party asset URLs (`background_image`, `coordinates_url`), and per-section `shape_path` data for overlay rendering.
221
369
 
222
370
  ### `eventUrl(slugOrId)`
223
371
 
224
- Returns the full URL to the event page on tixbit.com.
372
+ Returns the full URL to the event page on `www.tixbit.com`.
225
373
 
226
374
  ## Environment Variables
227
375
 
228
376
  | Variable | Description | Default |
229
377
  |---|---|---|
230
- | `TIXBIT_BASE_URL` | Override the TixBit URL | `https://tixbit.com` |
231
- | `TIXBIT_API_KEY` | API key (reserved for future use) | — |
378
+ | `TIXBIT_BASE_URL` | Discovery URL; credential requests accept only the canonical origin or loopback QA | `https://www.tixbit.com` |
379
+ | `TIXBIT_EMAIL` | Optional alternative to `buy --email` | none |
380
+ | `TIXBIT_LINK_TOKEN` | Optional advanced integration: user-approved Link credential; never an argument | none |
381
+ | `TIXBIT_ACCESS_TOKEN` | Optional advanced integration: signed-in seller user credential, not an API key | none |
382
+ | `TIXBIT_PAYMENT_URL` | Canonical MPP endpoint or loopback QA URL; no credentials, query, fragment, or redirects | `https://mcp.tixbit.com/api/purchase` |
383
+ | `MPPX_PRIVATE_KEY` | Optional mppx account source; prefer the OS keychain | mppx keychain |
232
384
 
233
385
  ## Requirements
234
386
 
235
- - Node.js 20+
387
+ - Runtime/tooling range: Node.js `^20.19.0 || >=22.12.0`
388
+ - CI compatibility matrix: Node.js 20.19, 22, 24, and 26
389
+
390
+ Node.js 20 is end-of-life and remains in CI only as a compatibility floor. Node.js 22 and 24 are LTS releases; Node.js 26 is the current release line.
236
391
 
237
392
  ## License
238
393