@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.
- package/convex/_generated/api.d.ts +6 -0
- package/convex/billing.ts +341 -0
- package/convex/email.ts +276 -0
- package/convex/http.ts +154 -0
- package/convex/schema.ts +43 -0
- package/convex/workspaces.ts +663 -0
- package/dist/index.js +387 -4
- package/dist/index.js.map +1 -1
- package/dist/session.d.ts +29 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +87 -0
- package/dist/session.js.map +1 -0
- package/docs/PRD-agent-first-billing.md +525 -0
- package/landing/package-lock.json +21 -3
- package/landing/package.json +2 -1
- package/landing/src/app/api/stripe/webhook/route.ts +178 -0
- package/landing/src/app/api/workspace-auth/magic-link/route.ts +84 -0
- package/landing/src/app/api/workspace-auth/session/route.ts +73 -0
- package/landing/src/app/api/workspace-auth/verify/route.ts +57 -0
- package/landing/src/app/auth/verify/page.tsx +292 -0
- package/landing/src/app/dashboard/layout.tsx +22 -0
- package/landing/src/app/dashboard/page.tsx +692 -0
- package/landing/src/app/dashboard/verify/page.tsx +108 -0
- package/landing/src/app/login/page.tsx +204 -0
- package/landing/src/app/upgrade/page.tsx +288 -0
- package/landing/src/lib/stats.json +14 -15
- package/landing/src/middleware.ts +50 -0
- package/landing/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/index.ts +434 -4
- package/src/session.ts +103 -0
|
@@ -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
|
-
"
|
|
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
|
-
"
|
|
2784
|
+
"devOptional": true,
|
|
2767
2785
|
"license": "MIT"
|
|
2768
2786
|
},
|
|
2769
2787
|
"node_modules/unicode-trie": {
|