@nordsym/apiclaw 1.3.3 → 1.3.4

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,525 @@
1
+ # PRD: Agent-First Onboarding & Billing
2
+
3
+ **Version:** 1.0
4
+ **Date:** 2026-02-28
5
+ **Author:** Symbot + Gustav
6
+ **Status:** Draft
7
+
8
+ ---
9
+
10
+ ## Executive Summary
11
+
12
+ APIClaw är för agenter. Onboarding ska därför drivas av agenter, inte människor.
13
+
14
+ Agenten registrerar sin ägare via email → magic link → workspace aktivt → autobahn.
15
+
16
+ Inga API-nycklar att kopiera. Inga dashboards att navigera. Agenten fixar allt.
17
+
18
+ ---
19
+
20
+ ## Problem Statement
21
+
22
+ **Idag:**
23
+ 1. Människa måste skapa konto manuellt
24
+ 2. Människa måste kopiera API-nyckel
25
+ 3. Människa måste konfigurera agenten
26
+ 4. Friktion vid varje steg
27
+
28
+ **Dessutom:**
29
+ - Direct Call kostar NordSym pengar
30
+ - Ingen revenue-modell aktiv
31
+ - Abuse-risk utan identifiering
32
+
33
+ ---
34
+
35
+ ## Solution Overview
36
+
37
+ ### Core Concept: Agent-First Onboarding
38
+
39
+ ```
40
+ Agent försöker använda APIClaw
41
+
42
+
43
+ Inget workspace?
44
+
45
+
46
+ Agent: register_owner("email@example.com")
47
+
48
+
49
+ Magic link skickas
50
+
51
+
52
+ Människa klickar
53
+
54
+
55
+ Workspace aktivt
56
+
57
+
58
+ Agent kör fritt
59
+ ```
60
+
61
+ ### Billing Model: Free Tier → Pay-as-you-go
62
+
63
+ ```
64
+ Tier 1: Anonymous → 10 calls/dag (IP-limited)
65
+ Tier 2: Free Account → 50 calls totalt
66
+ Tier 3: Paid → Unlimited, metered billing
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Detailed Design
72
+
73
+ ### 1. Workspace Model
74
+
75
+ Ett **workspace** är:
76
+ - Kopplat till en email (ägaren)
77
+ - Kan ha flera agenter
78
+ - Har en usage-räknare
79
+ - Har en betalmetod (efter free tier)
80
+
81
+ ```typescript
82
+ // Convex schema addition
83
+ workspaces: defineTable({
84
+ email: v.string(),
85
+ passwordHash: v.optional(v.string()), // Optional, for dashboard login
86
+ status: v.string(), // "pending" | "active" | "suspended"
87
+ tier: v.string(), // "anonymous" | "free" | "paid"
88
+ usageCount: v.number(),
89
+ usageLimitReached: v.boolean(),
90
+ stripeCustomerId: v.optional(v.string()),
91
+ createdAt: v.number(),
92
+ updatedAt: v.number(),
93
+ })
94
+ .index("by_email", ["email"])
95
+ .index("by_stripeCustomerId", ["stripeCustomerId"]),
96
+
97
+ // Agent sessions (local token → workspace)
98
+ agentSessions: defineTable({
99
+ workspaceId: v.id("workspaces"),
100
+ sessionToken: v.string(), // Stored in ~/.apiclaw/session
101
+ fingerprint: v.string(), // MCP client info
102
+ lastUsedAt: v.number(),
103
+ createdAt: v.number(),
104
+ })
105
+ .index("by_sessionToken", ["sessionToken"])
106
+ .index("by_workspaceId", ["workspaceId"]),
107
+
108
+ // Magic links
109
+ workspaceMagicLinks: defineTable({
110
+ email: v.string(),
111
+ token: v.string(),
112
+ sessionFingerprint: v.optional(v.string()), // Link back to requesting agent
113
+ expiresAt: v.number(),
114
+ usedAt: v.optional(v.number()),
115
+ createdAt: v.number(),
116
+ })
117
+ .index("by_token", ["token"])
118
+ .index("by_email", ["email"]),
119
+ ```
120
+
121
+ ### 2. New MCP Tools
122
+
123
+ #### `register_owner`
124
+
125
+ Agent requests workspace creation for their owner.
126
+
127
+ ```typescript
128
+ {
129
+ name: "register_owner",
130
+ description: "Register your owner's email to create a workspace. A magic link will be sent.",
131
+ inputSchema: {
132
+ type: "object",
133
+ properties: {
134
+ email: {
135
+ type: "string",
136
+ description: "Owner's email address"
137
+ }
138
+ },
139
+ required: ["email"]
140
+ }
141
+ }
142
+
143
+ // Response
144
+ {
145
+ status: "magic_link_sent",
146
+ message: "Magic link sent to gustav@nordsym.com. Waiting for confirmation...",
147
+ workspaceId: "pending_abc123"
148
+ }
149
+ ```
150
+
151
+ #### `check_workspace_status`
152
+
153
+ Agent checks if workspace is active.
154
+
155
+ ```typescript
156
+ {
157
+ name: "check_workspace_status",
158
+ description: "Check if your workspace is active and ready to use.",
159
+ inputSchema: {
160
+ type: "object",
161
+ properties: {}
162
+ }
163
+ }
164
+
165
+ // Response (pending)
166
+ {
167
+ status: "pending",
168
+ message: "Waiting for owner to click magic link.",
169
+ email: "gus***@nordsym.com"
170
+ }
171
+
172
+ // Response (active)
173
+ {
174
+ status: "active",
175
+ tier: "free",
176
+ usageRemaining: 47,
177
+ workspaceId: "ws_abc123"
178
+ }
179
+
180
+ // Response (limit_reached)
181
+ {
182
+ status: "limit_reached",
183
+ message: "Free tier exhausted. Owner needs to add payment method.",
184
+ upgradeUrl: "https://apiclaw.com/upgrade?ws=abc123"
185
+ }
186
+ ```
187
+
188
+ #### `remind_owner`
189
+
190
+ Send reminder if owner hasn't clicked magic link.
191
+
192
+ ```typescript
193
+ {
194
+ name: "remind_owner",
195
+ description: "Send a reminder email to your owner to complete registration.",
196
+ inputSchema: {
197
+ type: "object",
198
+ properties: {}
199
+ }
200
+ }
201
+
202
+ // Response
203
+ {
204
+ status: "reminder_sent",
205
+ message: "Reminder sent. You can send another in 10 minutes."
206
+ }
207
+ ```
208
+
209
+ ### 3. Session Management
210
+
211
+ #### Local Session Storage
212
+
213
+ When workspace is activated, agent receives a session token:
214
+
215
+ ```
216
+ ~/.apiclaw/session
217
+ {
218
+ "sessionToken": "sess_abc123xyz",
219
+ "workspaceId": "ws_abc123",
220
+ "email": "gustav@nordsym.com",
221
+ "createdAt": 1709110800000
222
+ }
223
+ ```
224
+
225
+ #### Session Flow
226
+
227
+ ```
228
+ Agent starts MCP server
229
+
230
+
231
+ Read ~/.apiclaw/session
232
+
233
+ ┌────┴────┐
234
+ │ │
235
+ Exists Missing
236
+ │ │
237
+ ▼ ▼
238
+ Validate Anonymous mode
239
+ with API (10 calls/day)
240
+
241
+ ┌─┴─┐
242
+ │ │
243
+ Valid Invalid
244
+ │ │
245
+ ▼ ▼
246
+ Use Delete &
247
+ prompt for
248
+ register_owner
249
+ ```
250
+
251
+ ### 4. Magic Link Flow
252
+
253
+ #### Email Template
254
+
255
+ ```
256
+ Subject: Activate your APIClaw workspace
257
+
258
+ An AI agent wants to connect to your APIClaw workspace.
259
+
260
+ Click below to activate:
261
+
262
+ [Activate Workspace]
263
+
264
+ This link expires in 1 hour.
265
+
266
+ ---
267
+ If you didn't expect this email, you can safely ignore it.
268
+ ```
269
+
270
+ #### Click Handler (apiclaw.com/auth/verify)
271
+
272
+ ```
273
+ 1. Validate token (not expired, not used)
274
+ 2. Check if workspace exists for email
275
+ - Yes: Activate session, link agent
276
+ - No: Show "Set password (optional)" form, create workspace
277
+ 3. Mark magic link as used
278
+ 4. Create agent session
279
+ 5. Redirect to success page
280
+ 6. Agent polling detects activation → continues
281
+ ```
282
+
283
+ ### 5. Billing Integration
284
+
285
+ #### Free Tier Exhaustion Flow
286
+
287
+ ```
288
+ Agent: call_api("send_sms", {...})
289
+
290
+
291
+ Check workspace.usageCount
292
+
293
+ ┌────┴────┐
294
+ │ │
295
+ < 50 >= 50
296
+ │ │
297
+ ▼ ▼
298
+ Execute Check tier
299
+ │ │
300
+ │ ┌────┴────┐
301
+ │ │ │
302
+ │ "free" "paid"
303
+ │ │ │
304
+ │ ▼ ▼
305
+ │ Block Execute
306
+ │ │
307
+ │ ▼
308
+ │ Send email to owner:
309
+ │ "Add payment to continue"
310
+ │ │
311
+ │ ▼
312
+ │ Return error to agent:
313
+ │ {
314
+ │ error: "usage_limit_reached",
315
+ │ message: "Free tier exhausted",
316
+ │ upgradeUrl: "https://..."
317
+ │ }
318
+ ```
319
+
320
+ #### Stripe Integration
321
+
322
+ ```typescript
323
+ // When owner adds payment method
324
+ 1. Create Stripe Customer (if not exists)
325
+ 2. Attach PaymentMethod
326
+ 3. Update workspace.tier = "paid"
327
+ 4. Set up metered billing:
328
+ - Stripe Price: "API Calls" (usage-based)
329
+ - Report usage daily via Stripe Billing Meter
330
+
331
+ // Monthly invoice
332
+ - Stripe automatically generates invoice
333
+ - Sum of all usage for the period
334
+ - Charges saved payment method
335
+ ```
336
+
337
+ ### 6. Rate Limiting (Abuse Prevention)
338
+
339
+ | Action | Limit | Window |
340
+ |--------|-------|--------|
341
+ | `register_owner` | 3 | per hour per IP |
342
+ | `remind_owner` | 1 | per 10 minutes |
343
+ | Anonymous API calls | 10 | per day per IP |
344
+ | Free tier API calls | 50 | lifetime |
345
+ | Paid tier API calls | 1000 | per minute |
346
+
347
+ ### 7. Dashboard (apiclaw.com/dashboard)
348
+
349
+ Minimal dashboard for workspace owners:
350
+
351
+ ```
352
+ ┌─────────────────────────────────────────────────┐
353
+ │ APIClaw Dashboard │
354
+ │ │
355
+ │ Workspace: gustav@nordsym.com │
356
+ │ Tier: Free (47/50 calls remaining) │
357
+ │ │
358
+ │ [Upgrade to Paid →] │
359
+ │ │
360
+ │ ───────────────────────────────────────────── │
361
+ │ │
362
+ │ Connected Agents: │
363
+ │ ┌─────────────────────────────────────────┐ │
364
+ │ │ Claude Desktop (MacBook Air) │ │
365
+ │ │ Last used: 2 minutes ago │ │
366
+ │ │ Calls: 3 [Revoke] │ │
367
+ │ └─────────────────────────────────────────┘ │
368
+ │ │
369
+ │ ───────────────────────────────────────────── │
370
+ │ │
371
+ │ Usage This Month: │
372
+ │ ├── SMS (46elks): 12 calls ($0.48) │
373
+ │ ├── Search (Brave): 31 calls ($0.00) │
374
+ │ └── LLM (OpenRouter): 4 calls ($0.12) │
375
+ │ │
376
+ │ Total: $0.60 │
377
+ │ │
378
+ └─────────────────────────────────────────────────┘
379
+ ```
380
+
381
+ ---
382
+
383
+ ## Implementation Plan
384
+
385
+ ### Phase 1: Core Onboarding (Week 1)
386
+
387
+ - [ ] Convex schema: workspaces, agentSessions, workspaceMagicLinks
388
+ - [ ] MCP tools: register_owner, check_workspace_status
389
+ - [ ] Magic link email (via Resend)
390
+ - [ ] Verify endpoint (apiclaw.com/auth/verify)
391
+ - [ ] Local session storage (~/.apiclaw/session)
392
+ - [ ] Session validation in call_api
393
+
394
+ ### Phase 2: Billing (Week 2)
395
+
396
+ - [ ] Stripe Customer creation
397
+ - [ ] Payment method collection (apiclaw.com/upgrade)
398
+ - [ ] Usage tracking per workspace
399
+ - [ ] Free tier enforcement (50 calls)
400
+ - [ ] Metered billing setup
401
+ - [ ] "Limit reached" email
402
+
403
+ ### Phase 3: Dashboard (Week 3)
404
+
405
+ - [ ] Dashboard UI (apiclaw.com/dashboard)
406
+ - [ ] Magic link login
407
+ - [ ] View connected agents
408
+ - [ ] Revoke agent sessions
409
+ - [ ] Usage breakdown
410
+ - [ ] Billing history
411
+
412
+ ### Phase 4: Polish (Week 4)
413
+
414
+ - [ ] Rate limiting
415
+ - [ ] Reminder emails
416
+ - [ ] Error handling improvements
417
+ - [ ] Documentation update
418
+ - [ ] npm publish with new tools
419
+
420
+ ---
421
+
422
+ ## Success Metrics
423
+
424
+ | Metric | Target (Month 1) |
425
+ |--------|------------------|
426
+ | Workspaces created | 50 |
427
+ | Agents connected | 100 |
428
+ | Free → Paid conversion | 10% |
429
+ | Monthly revenue | $500 |
430
+
431
+ ---
432
+
433
+ ## Open Questions
434
+
435
+ 1. **Pricing per call?**
436
+ - Option A: Flat rate (e.g., $0.01/call regardless of provider)
437
+ - Option B: Pass-through + margin (provider cost + 20%)
438
+ - Recommendation: Option B for transparency
439
+
440
+ 2. **Anonymous tier - keep or remove?**
441
+ - Pro: Lower friction for testing
442
+ - Con: Abuse vector, complicates logic
443
+ - Recommendation: Keep, but very limited (10 calls/day)
444
+
445
+ 3. **Password requirement?**
446
+ - Current: Optional (magic link always works)
447
+ - Alternative: Required after first login
448
+ - Recommendation: Keep optional
449
+
450
+ ---
451
+
452
+ ## Appendix: Email Templates
453
+
454
+ ### Magic Link Email
455
+
456
+ ```
457
+ Subject: Activate your APIClaw workspace
458
+
459
+ Hi,
460
+
461
+ An AI agent wants to use APIClaw on your behalf. Click below to activate your workspace:
462
+
463
+ [Activate Workspace]
464
+
465
+ Once activated, your agent can:
466
+ • Send SMS via 46elks/Twilio
467
+ • Search the web via Brave
468
+ • Generate speech via ElevenLabs
469
+ • And 8 more providers...
470
+
471
+ Your first 50 API calls are free.
472
+
473
+ This link expires in 1 hour.
474
+
475
+
476
+ APIClaw
477
+ The API layer for AI agents
478
+ ```
479
+
480
+ ### Free Tier Exhausted Email
481
+
482
+ ```
483
+ Subject: Your APIClaw free tier is exhausted
484
+
485
+ Hi,
486
+
487
+ Your AI agent has used all 50 free API calls.
488
+
489
+ To continue, add a payment method:
490
+
491
+ [Add Payment Method]
492
+
493
+ Pay-as-you-go pricing:
494
+ • SMS: $0.04/message
495
+ • Search: Free (included)
496
+ • LLM: From $0.001/call
497
+ • Full pricing: apiclaw.com/pricing
498
+
499
+
500
+ APIClaw
501
+ ```
502
+
503
+ ### Agent Connected Email
504
+
505
+ ```
506
+ Subject: New agent connected to your workspace
507
+
508
+ Hi,
509
+
510
+ A new AI agent just connected to your APIClaw workspace:
511
+
512
+ Device: Claude Desktop (MacBook Air)
513
+ Time: February 28, 2026, 10:15 AM CET
514
+
515
+ If this wasn't you, revoke access immediately:
516
+
517
+ [View Connected Agents]
518
+
519
+
520
+ APIClaw
521
+ ```
522
+
523
+ ---
524
+
525
+ *PRD created 2026-02-28 by Symbot*
@@ -14,7 +14,8 @@
14
14
  "next": "^14.2.0",
15
15
  "react": "^18.2.0",
16
16
  "react-dom": "^18.2.0",
17
- "recharts": "^3.7.0"
17
+ "recharts": "^3.7.0",
18
+ "stripe": "^20.4.0"
18
19
  },
19
20
  "devDependencies": {
20
21
  "@types/node": "^20",
@@ -924,7 +925,7 @@
924
925
  "version": "20.19.33",
925
926
  "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz",
926
927
  "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==",
927
- "dev": true,
928
+ "devOptional": true,
928
929
  "license": "MIT",
929
930
  "dependencies": {
930
931
  "undici-types": "~6.21.0"
@@ -2539,6 +2540,23 @@
2539
2540
  "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==",
2540
2541
  "license": "MIT"
2541
2542
  },
2543
+ "node_modules/stripe": {
2544
+ "version": "20.4.0",
2545
+ "resolved": "https://registry.npmjs.org/stripe/-/stripe-20.4.0.tgz",
2546
+ "integrity": "sha512-F/aN1IQ9vHmlyLNi3DkiIbyzQb6gyBG0uYFd/VrEVQSc9BLtlgknPUx0EvzZdBMRLFuRaPFIFd7Mxwtg7Pbwzw==",
2547
+ "license": "MIT",
2548
+ "engines": {
2549
+ "node": ">=16"
2550
+ },
2551
+ "peerDependencies": {
2552
+ "@types/node": ">=16"
2553
+ },
2554
+ "peerDependenciesMeta": {
2555
+ "@types/node": {
2556
+ "optional": true
2557
+ }
2558
+ }
2559
+ },
2542
2560
  "node_modules/styled-jsx": {
2543
2561
  "version": "5.1.1",
2544
2562
  "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
@@ -2763,7 +2781,7 @@
2763
2781
  "version": "6.21.0",
2764
2782
  "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
2765
2783
  "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
2766
- "dev": true,
2784
+ "devOptional": true,
2767
2785
  "license": "MIT"
2768
2786
  },
2769
2787
  "node_modules/unicode-trie": {
@@ -16,7 +16,8 @@
16
16
  "next": "^14.2.0",
17
17
  "react": "^18.2.0",
18
18
  "react-dom": "^18.2.0",
19
- "recharts": "^3.7.0"
19
+ "recharts": "^3.7.0",
20
+ "stripe": "^20.4.0"
20
21
  },
21
22
  "devDependencies": {
22
23
  "@types/node": "^20",