@nordsym/apiclaw 1.8.6 → 1.8.7
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 +4 -4
- package/apiclaw-README.md +12 -12
- package/convex/_generated/api.d.ts +4 -0
- package/convex/apiKeys.ts +220 -0
- package/convex/directCall.ts +49 -14
- package/convex/email.ts +5 -5
- package/convex/http.ts +598 -40
- package/convex/logs.ts +26 -22
- package/convex/migrateProviderWorkspaces.ts +154 -35
- package/convex/providers.ts +313 -203
- package/convex/schema.ts +50 -1
- package/convex/searchLogs.ts +2 -6
- package/convex/seedPratham.ts +1 -1
- package/convex/spendAlerts.ts +2 -2
- package/convex/stripeActions.ts +1 -1
- package/convex/updateAPIStatus.ts +2 -3
- package/convex/workspaceSettings.ts +136 -0
- package/dist/cli/commands/demo.js +2 -2
- package/dist/cli/commands/doctor.js +1 -1
- package/dist/cli/commands/login.js +1 -1
- package/dist/cli/commands/setup.js +2 -2
- package/dist/discovery.js +1 -1
- package/dist/execute.js +3 -3
- package/dist/index.js +13 -13
- package/dist/ui/errors.js +16 -16
- package/dist/ui/prompts.js +1 -1
- package/email-templates/filestack-provider-outreach.html +1 -1
- package/email-templates/partnership-template.html +1 -1
- package/email-templates/pratham-partnership-draft.html +2 -2
- package/package.json +2 -2
- package/reports/APIClaw-Session-Report-2026-04-05.pdf +0 -0
- package/reports/session-report-2026-04-05.html +433 -0
- package/src/cli/commands/demo.ts +2 -2
- package/src/cli/commands/doctor.ts +1 -1
- package/src/cli/commands/login.ts +1 -1
- package/src/cli/commands/setup.ts +2 -2
- package/src/discovery.ts +1 -1
- package/src/execute.ts +3 -3
- package/src/index.ts +14 -14
- package/src/ui/errors.ts +16 -16
- package/src/ui/prompts.ts +1 -1
- package/convex/adminActivate.d.ts +0 -3
- package/convex/adminActivate.js +0 -47
- package/convex/adminStats.d.ts +0 -9
- package/convex/adminStats.js +0 -280
- package/convex/agents.d.ts +0 -84
- package/convex/agents.js +0 -809
- package/convex/analytics.d.ts +0 -5
- package/convex/analytics.js +0 -167
- package/convex/backfillAnalytics.d.ts +0 -2
- package/convex/backfillAnalytics.js +0 -20
- package/convex/backfillSearchLogs.d.ts +0 -2
- package/convex/backfillSearchLogs.js +0 -29
- package/convex/billing.d.ts +0 -88
- package/convex/billing.js +0 -655
- package/convex/capabilities.d.ts +0 -9
- package/convex/capabilities.js +0 -145
- package/convex/chains.d.ts +0 -68
- package/convex/chains.js +0 -1105
- package/convex/credits.d.ts +0 -25
- package/convex/credits.js +0 -186
- package/convex/crons.d.ts +0 -3
- package/convex/crons.js +0 -17
- package/convex/debugFilestackLogs.d.ts +0 -2
- package/convex/debugFilestackLogs.js +0 -17
- package/convex/debugGetToken.d.ts +0 -2
- package/convex/debugGetToken.js +0 -18
- package/convex/directCall.d.ts +0 -72
- package/convex/directCall.js +0 -627
- package/convex/earnProgress.d.ts +0 -58
- package/convex/earnProgress.js +0 -649
- package/convex/email.d.ts +0 -14
- package/convex/email.js +0 -300
- package/convex/feedback.d.ts +0 -7
- package/convex/feedback.js +0 -227
- package/convex/http.d.ts +0 -3
- package/convex/http.js +0 -1408
- package/convex/inbound.d.ts +0 -2
- package/convex/inbound.js +0 -32
- package/convex/logs.d.ts +0 -48
- package/convex/logs.js +0 -621
- package/convex/migrateFilestack.d.ts +0 -2
- package/convex/migrateFilestack.js +0 -74
- package/convex/migratePartnersProd.d.ts +0 -8
- package/convex/migratePartnersProd.js +0 -165
- package/convex/migratePratham.d.ts +0 -2
- package/convex/migratePratham.js +0 -121
- package/convex/migrateProviderWorkspaces.d.ts +0 -2
- package/convex/migrateProviderWorkspaces.js +0 -55
- package/convex/mou.d.ts +0 -6
- package/convex/mou.js +0 -82
- package/convex/providerKeys.d.ts +0 -31
- package/convex/providerKeys.js +0 -257
- package/convex/providers.d.ts +0 -35
- package/convex/providers.js +0 -922
- package/convex/purchases.d.ts +0 -7
- package/convex/purchases.js +0 -157
- package/convex/ratelimit.d.ts +0 -4
- package/convex/ratelimit.js +0 -91
- package/convex/searchLogs.d.ts +0 -13
- package/convex/searchLogs.js +0 -246
- package/convex/seedAPILayerAPIs.d.ts +0 -7
- package/convex/seedAPILayerAPIs.js +0 -177
- package/convex/seedDirectCallConfigs.d.ts +0 -2
- package/convex/seedDirectCallConfigs.js +0 -324
- package/convex/seedPratham.d.ts +0 -6
- package/convex/seedPratham.js +0 -150
- package/convex/spendAlerts.d.ts +0 -36
- package/convex/spendAlerts.js +0 -380
- package/convex/stripeActions.d.ts +0 -19
- package/convex/stripeActions.js +0 -411
- package/convex/teams.d.ts +0 -21
- package/convex/teams.js +0 -215
- package/convex/telemetry.d.ts +0 -4
- package/convex/telemetry.js +0 -74
- package/convex/updateAPIStatus.d.ts +0 -6
- package/convex/updateAPIStatus.js +0 -40
- package/convex/usage.d.ts +0 -27
- package/convex/usage.js +0 -229
- package/convex/waitlist.d.ts +0 -4
- package/convex/waitlist.js +0 -49
- package/convex/webhooks.d.ts +0 -12
- package/convex/webhooks.js +0 -410
- package/convex/workspaces.d.ts +0 -33
- package/convex/workspaces.js +0 -991
package/dist/ui/errors.js
CHANGED
|
@@ -61,7 +61,7 @@ const errorMeta = {
|
|
|
61
61
|
'npx @nordsym/apiclaw setup --client cursor',
|
|
62
62
|
'npx @nordsym/apiclaw setup --config /path/to/config.json',
|
|
63
63
|
],
|
|
64
|
-
helpUrl: 'https://apiclaw.
|
|
64
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/config-not-found',
|
|
65
65
|
},
|
|
66
66
|
[ErrorCode.PERMISSION_DENIED]: {
|
|
67
67
|
title: 'Permission denied',
|
|
@@ -75,7 +75,7 @@ const errorMeta = {
|
|
|
75
75
|
'sudo npx @nordsym/apiclaw setup',
|
|
76
76
|
'chmod 644 <config-path>',
|
|
77
77
|
],
|
|
78
|
-
helpUrl: 'https://apiclaw.
|
|
78
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/permissions',
|
|
79
79
|
},
|
|
80
80
|
[ErrorCode.INVALID_JSON]: {
|
|
81
81
|
title: 'Invalid JSON in config file',
|
|
@@ -89,7 +89,7 @@ const errorMeta = {
|
|
|
89
89
|
'npx @nordsym/apiclaw restore --list',
|
|
90
90
|
'npx @nordsym/apiclaw restore',
|
|
91
91
|
],
|
|
92
|
-
helpUrl: 'https://apiclaw.
|
|
92
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/invalid-json',
|
|
93
93
|
},
|
|
94
94
|
[ErrorCode.WRITE_FAILED]: {
|
|
95
95
|
title: 'Failed to write config file',
|
|
@@ -99,7 +99,7 @@ const errorMeta = {
|
|
|
99
99
|
'Ensure the config directory exists',
|
|
100
100
|
'Verify write permissions',
|
|
101
101
|
],
|
|
102
|
-
helpUrl: 'https://apiclaw.
|
|
102
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/write-failed',
|
|
103
103
|
},
|
|
104
104
|
[ErrorCode.BACKUP_FAILED]: {
|
|
105
105
|
title: 'Failed to create backup',
|
|
@@ -109,7 +109,7 @@ const errorMeta = {
|
|
|
109
109
|
'Verify write permissions in config directory',
|
|
110
110
|
'Use --no-backup to skip backup (not recommended)',
|
|
111
111
|
],
|
|
112
|
-
helpUrl: 'https://apiclaw.
|
|
112
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/backup-failed',
|
|
113
113
|
},
|
|
114
114
|
[ErrorCode.ALREADY_CONFIGURED]: {
|
|
115
115
|
title: 'Already configured',
|
|
@@ -122,7 +122,7 @@ const errorMeta = {
|
|
|
122
122
|
'npx @nordsym/apiclaw setup --force',
|
|
123
123
|
'npx @nordsym/apiclaw doctor',
|
|
124
124
|
],
|
|
125
|
-
helpUrl: 'https://apiclaw.
|
|
125
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/already-configured',
|
|
126
126
|
},
|
|
127
127
|
[ErrorCode.INVALID_CONFIG]: {
|
|
128
128
|
title: 'Invalid configuration',
|
|
@@ -131,7 +131,7 @@ const errorMeta = {
|
|
|
131
131
|
'Ensure the config follows the MCP specification',
|
|
132
132
|
'Check for required fields like "mcpServers"',
|
|
133
133
|
],
|
|
134
|
-
helpUrl: 'https://apiclaw.
|
|
134
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/invalid-config',
|
|
135
135
|
},
|
|
136
136
|
[ErrorCode.MERGE_CONFLICT]: {
|
|
137
137
|
title: 'Configuration merge conflict',
|
|
@@ -141,7 +141,7 @@ const errorMeta = {
|
|
|
141
141
|
'Use --force to overwrite',
|
|
142
142
|
'Create a backup and try again',
|
|
143
143
|
],
|
|
144
|
-
helpUrl: 'https://apiclaw.
|
|
144
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/merge-conflict',
|
|
145
145
|
},
|
|
146
146
|
[ErrorCode.CLIENT_NOT_FOUND]: {
|
|
147
147
|
title: 'MCP client not found',
|
|
@@ -155,7 +155,7 @@ const errorMeta = {
|
|
|
155
155
|
'npx @nordsym/apiclaw setup --client claude-desktop',
|
|
156
156
|
'npx @nordsym/apiclaw doctor',
|
|
157
157
|
],
|
|
158
|
-
helpUrl: 'https://apiclaw.
|
|
158
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/client-not-found',
|
|
159
159
|
},
|
|
160
160
|
[ErrorCode.UNSUPPORTED_CLIENT]: {
|
|
161
161
|
title: 'Unsupported MCP client',
|
|
@@ -165,7 +165,7 @@ const errorMeta = {
|
|
|
165
165
|
'Use --config to manually specify the config path',
|
|
166
166
|
'Request support at github.com/nordsym/apiclaw',
|
|
167
167
|
],
|
|
168
|
-
helpUrl: 'https://apiclaw.
|
|
168
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/supported-clients',
|
|
169
169
|
},
|
|
170
170
|
[ErrorCode.NETWORK_ERROR]: {
|
|
171
171
|
title: 'Network error',
|
|
@@ -176,10 +176,10 @@ const errorMeta = {
|
|
|
176
176
|
'Check if APIClaw is reachable',
|
|
177
177
|
],
|
|
178
178
|
commands: [
|
|
179
|
-
'curl -I https://apiclaw.
|
|
179
|
+
'curl -I https://apiclaw.cloud',
|
|
180
180
|
'npx @nordsym/apiclaw doctor',
|
|
181
181
|
],
|
|
182
|
-
helpUrl: 'https://apiclaw.
|
|
182
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/network-error',
|
|
183
183
|
},
|
|
184
184
|
[ErrorCode.AUTH_FAILED]: {
|
|
185
185
|
title: 'Authentication failed',
|
|
@@ -189,7 +189,7 @@ const errorMeta = {
|
|
|
189
189
|
'Verify your API key is valid',
|
|
190
190
|
'Setup works without auth - configure credentials later',
|
|
191
191
|
],
|
|
192
|
-
helpUrl: 'https://apiclaw.
|
|
192
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/auth-failed',
|
|
193
193
|
},
|
|
194
194
|
[ErrorCode.UNSUPPORTED_OS]: {
|
|
195
195
|
title: 'Unsupported operating system',
|
|
@@ -198,7 +198,7 @@ const errorMeta = {
|
|
|
198
198
|
'Supported: macOS, Windows 10/11, Linux',
|
|
199
199
|
'Manual setup instructions available',
|
|
200
200
|
],
|
|
201
|
-
helpUrl: 'https://apiclaw.
|
|
201
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/manual',
|
|
202
202
|
},
|
|
203
203
|
[ErrorCode.NODE_VERSION]: {
|
|
204
204
|
title: 'Unsupported Node.js version',
|
|
@@ -211,7 +211,7 @@ const errorMeta = {
|
|
|
211
211
|
'nvm install 18',
|
|
212
212
|
'nvm use 18',
|
|
213
213
|
],
|
|
214
|
-
helpUrl: 'https://apiclaw.
|
|
214
|
+
helpUrl: 'https://apiclaw.cloud/docs/setup/node-version',
|
|
215
215
|
},
|
|
216
216
|
[ErrorCode.UNKNOWN]: {
|
|
217
217
|
title: 'Unknown error',
|
|
@@ -224,7 +224,7 @@ const errorMeta = {
|
|
|
224
224
|
commands: [
|
|
225
225
|
'npx @nordsym/apiclaw setup --verbose',
|
|
226
226
|
],
|
|
227
|
-
helpUrl: 'https://apiclaw.
|
|
227
|
+
helpUrl: 'https://apiclaw.cloud/docs/support',
|
|
228
228
|
},
|
|
229
229
|
};
|
|
230
230
|
/**
|
package/dist/ui/prompts.js
CHANGED
|
@@ -181,7 +181,7 @@ export function showSuccess(configuredClients) {
|
|
|
181
181
|
'Ask your agent: "List available APIs"',
|
|
182
182
|
], 2));
|
|
183
183
|
console.log(colors.secondary('\nNeed help?'));
|
|
184
|
-
console.log(` ${colors.link('https://apiclaw.
|
|
184
|
+
console.log(` ${colors.link('https://apiclaw.cloud/docs/setup')}\n`);
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
187
|
* Show dry-run summary
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
|
|
112
112
|
<!-- CTA -->
|
|
113
113
|
<div style="text-align: center; margin: 32px 0;">
|
|
114
|
-
<a href="https://apiclaw.
|
|
114
|
+
<a href="https://apiclaw.cloud/providers/dashboard" style="display: inline-block; background-color: #ef4444; color: #ffffff; text-decoration: none; padding: 14px 36px; border-radius: 8px; font-weight: 600; font-size: 16px; box-shadow: 0 2px 4px rgba(239,68,68,0.3);">
|
|
115
115
|
View Your Provider Dashboard
|
|
116
116
|
</a>
|
|
117
117
|
<p class="text-muted" style="margin: 12px 0 0 0; font-size: 13px; color: #9ca3af;">
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
<div style="margin-top: 32px; text-align: center; color: #9ca3af; font-size: 12px;">
|
|
106
106
|
<p style="margin: 0;">NordSym AB (559535-5768) • Sweden</p>
|
|
107
107
|
<p style="margin: 4px 0 0 0;">
|
|
108
|
-
<a href="https://apiclaw.
|
|
108
|
+
<a href="https://apiclaw.cloud" style="color: #ef4444; text-decoration: none;">apiclaw.cloud</a> •
|
|
109
109
|
<a href="https://github.com/nordsym/apiclaw" style="color: #ef4444; text-decoration: none;">GitHub</a>
|
|
110
110
|
</p>
|
|
111
111
|
</div>
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
|
|
99
99
|
<!-- CTA -->
|
|
100
100
|
<div style="text-align: center; margin: 32px 0;">
|
|
101
|
-
<a href="https://apiclaw.
|
|
101
|
+
<a href="https://apiclaw.cloud" style="display: inline-block; background-color: #ef4444; color: #ffffff; text-decoration: none; padding: 14px 32px; border-radius: 8px; font-weight: 600; font-size: 16px; box-shadow: 0 2px 4px rgba(239, 68, 68, 0.2);">
|
|
102
102
|
View APIClaw Documentation
|
|
103
103
|
</a>
|
|
104
104
|
</div>
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
<div style="margin-top: 32px; text-align: center; color: #9ca3af; font-size: 12px;">
|
|
131
131
|
<p style="margin: 0;">NordSym AB (559535-5768) • Sweden</p>
|
|
132
132
|
<p style="margin: 4px 0 0 0;">
|
|
133
|
-
<a href="https://apiclaw.
|
|
133
|
+
<a href="https://apiclaw.cloud" style="color: #ef4444; text-decoration: none;">apiclaw.cloud</a> •
|
|
134
134
|
<a href="https://github.com/nordsym/apiclaw" style="color: #ef4444; text-decoration: none;">GitHub</a>
|
|
135
135
|
</p>
|
|
136
136
|
</div>
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nordsym/apiclaw",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.7",
|
|
4
4
|
"description": "The API layer for AI agents. Dashboard + 22K APIs + 18 Direct Call providers. MCP native.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
-
"homepage": "https://apiclaw.
|
|
7
|
+
"homepage": "https://apiclaw.cloud",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/nordsym/apiclaw"
|
|
Binary file
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>APIClaw Session Report — 2026-04-05</title>
|
|
7
|
+
<style>
|
|
8
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
|
|
9
|
+
|
|
10
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
11
|
+
|
|
12
|
+
body {
|
|
13
|
+
font-family: 'Inter', -apple-system, sans-serif;
|
|
14
|
+
background: #0a0a0a;
|
|
15
|
+
color: #e5e5e5;
|
|
16
|
+
line-height: 1.6;
|
|
17
|
+
padding: 60px;
|
|
18
|
+
max-width: 900px;
|
|
19
|
+
margin: 0 auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.header {
|
|
23
|
+
text-align: center;
|
|
24
|
+
padding-bottom: 48px;
|
|
25
|
+
border-bottom: 1px solid #262626;
|
|
26
|
+
margin-bottom: 48px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.header .logo { font-size: 48px; margin-bottom: 12px; }
|
|
30
|
+
.header h1 { font-size: 32px; font-weight: 800; color: #fff; letter-spacing: -0.5px; }
|
|
31
|
+
.header .subtitle { font-size: 14px; color: #737373; margin-top: 8px; font-weight: 500; letter-spacing: 2px; text-transform: uppercase; }
|
|
32
|
+
.header .date { font-size: 13px; color: #525252; margin-top: 16px; }
|
|
33
|
+
|
|
34
|
+
.highlight-box {
|
|
35
|
+
background: linear-gradient(135deg, #ef4444/10, #ef4444/5);
|
|
36
|
+
border: 1px solid #ef4444/30;
|
|
37
|
+
border-radius: 12px;
|
|
38
|
+
padding: 24px 28px;
|
|
39
|
+
margin-bottom: 40px;
|
|
40
|
+
text-align: center;
|
|
41
|
+
}
|
|
42
|
+
.highlight-box p { font-size: 16px; color: #fca5a5; font-weight: 600; }
|
|
43
|
+
.highlight-box .sub { font-size: 13px; color: #a3a3a3; margin-top: 8px; font-weight: 400; }
|
|
44
|
+
|
|
45
|
+
h2 {
|
|
46
|
+
font-size: 20px;
|
|
47
|
+
font-weight: 700;
|
|
48
|
+
color: #fff;
|
|
49
|
+
margin: 40px 0 20px;
|
|
50
|
+
padding-bottom: 10px;
|
|
51
|
+
border-bottom: 1px solid #1a1a1a;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
h3 {
|
|
55
|
+
font-size: 15px;
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
color: #ef4444;
|
|
58
|
+
margin: 28px 0 12px;
|
|
59
|
+
text-transform: uppercase;
|
|
60
|
+
letter-spacing: 1px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
p { font-size: 14px; color: #a3a3a3; margin-bottom: 12px; }
|
|
64
|
+
|
|
65
|
+
.feature-grid {
|
|
66
|
+
display: grid;
|
|
67
|
+
grid-template-columns: 1fr 1fr;
|
|
68
|
+
gap: 16px;
|
|
69
|
+
margin: 20px 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.feature-card {
|
|
73
|
+
background: #141414;
|
|
74
|
+
border: 1px solid #262626;
|
|
75
|
+
border-radius: 10px;
|
|
76
|
+
padding: 20px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.feature-card .num {
|
|
80
|
+
font-size: 11px;
|
|
81
|
+
font-weight: 700;
|
|
82
|
+
color: #ef4444;
|
|
83
|
+
letter-spacing: 2px;
|
|
84
|
+
text-transform: uppercase;
|
|
85
|
+
margin-bottom: 8px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.feature-card h4 {
|
|
89
|
+
font-size: 15px;
|
|
90
|
+
font-weight: 700;
|
|
91
|
+
color: #fff;
|
|
92
|
+
margin-bottom: 6px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.feature-card p { font-size: 12px; color: #737373; margin: 0; }
|
|
96
|
+
|
|
97
|
+
table {
|
|
98
|
+
width: 100%;
|
|
99
|
+
border-collapse: collapse;
|
|
100
|
+
margin: 16px 0;
|
|
101
|
+
font-size: 13px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
th {
|
|
105
|
+
text-align: left;
|
|
106
|
+
padding: 10px 14px;
|
|
107
|
+
background: #141414;
|
|
108
|
+
color: #a3a3a3;
|
|
109
|
+
font-weight: 600;
|
|
110
|
+
font-size: 11px;
|
|
111
|
+
text-transform: uppercase;
|
|
112
|
+
letter-spacing: 1px;
|
|
113
|
+
border-bottom: 1px solid #262626;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
td {
|
|
117
|
+
padding: 10px 14px;
|
|
118
|
+
border-bottom: 1px solid #1a1a1a;
|
|
119
|
+
color: #d4d4d4;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.status-pass {
|
|
123
|
+
color: #4ade80;
|
|
124
|
+
font-weight: 600;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.status-live {
|
|
128
|
+
background: #4ade80/15;
|
|
129
|
+
color: #4ade80;
|
|
130
|
+
padding: 2px 10px;
|
|
131
|
+
border-radius: 20px;
|
|
132
|
+
font-size: 11px;
|
|
133
|
+
font-weight: 600;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
code {
|
|
137
|
+
font-family: 'SF Mono', 'Fira Code', monospace;
|
|
138
|
+
background: #1a1a1a;
|
|
139
|
+
padding: 2px 6px;
|
|
140
|
+
border-radius: 4px;
|
|
141
|
+
font-size: 12px;
|
|
142
|
+
color: #fca5a5;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
pre {
|
|
146
|
+
background: #141414;
|
|
147
|
+
border: 1px solid #262626;
|
|
148
|
+
border-radius: 8px;
|
|
149
|
+
padding: 16px 20px;
|
|
150
|
+
overflow-x: auto;
|
|
151
|
+
margin: 12px 0;
|
|
152
|
+
font-family: 'SF Mono', 'Fira Code', monospace;
|
|
153
|
+
font-size: 12px;
|
|
154
|
+
line-height: 1.5;
|
|
155
|
+
color: #d4d4d4;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.e2e-chain {
|
|
159
|
+
display: flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
gap: 8px;
|
|
163
|
+
padding: 20px;
|
|
164
|
+
margin: 20px 0;
|
|
165
|
+
background: #141414;
|
|
166
|
+
border: 1px solid #262626;
|
|
167
|
+
border-radius: 10px;
|
|
168
|
+
flex-wrap: wrap;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.e2e-chain .node {
|
|
172
|
+
background: #1a1a1a;
|
|
173
|
+
border: 1px solid #333;
|
|
174
|
+
padding: 8px 14px;
|
|
175
|
+
border-radius: 6px;
|
|
176
|
+
font-size: 12px;
|
|
177
|
+
font-weight: 600;
|
|
178
|
+
color: #fff;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.e2e-chain .arrow { color: #ef4444; font-size: 16px; font-weight: 700; }
|
|
182
|
+
|
|
183
|
+
.files-list {
|
|
184
|
+
list-style: none;
|
|
185
|
+
margin: 12px 0;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.files-list li {
|
|
189
|
+
padding: 8px 0;
|
|
190
|
+
border-bottom: 1px solid #1a1a1a;
|
|
191
|
+
font-size: 13px;
|
|
192
|
+
display: flex;
|
|
193
|
+
gap: 12px;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.files-list li code { flex-shrink: 0; }
|
|
197
|
+
.files-list li span { color: #737373; }
|
|
198
|
+
|
|
199
|
+
.footer {
|
|
200
|
+
margin-top: 60px;
|
|
201
|
+
padding-top: 24px;
|
|
202
|
+
border-top: 1px solid #262626;
|
|
203
|
+
text-align: center;
|
|
204
|
+
font-size: 12px;
|
|
205
|
+
color: #525252;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.footer .brand { color: #737373; font-weight: 600; }
|
|
209
|
+
|
|
210
|
+
.badge {
|
|
211
|
+
display: inline-block;
|
|
212
|
+
padding: 3px 10px;
|
|
213
|
+
border-radius: 20px;
|
|
214
|
+
font-size: 11px;
|
|
215
|
+
font-weight: 600;
|
|
216
|
+
}
|
|
217
|
+
.badge-green { background: rgba(74, 222, 128, 0.15); color: #4ade80; }
|
|
218
|
+
.badge-red { background: rgba(239, 68, 68, 0.15); color: #ef4444; }
|
|
219
|
+
.badge-new { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
|
|
220
|
+
|
|
221
|
+
@media print {
|
|
222
|
+
body { background: #fff; color: #1a1a1a; padding: 40px; }
|
|
223
|
+
.feature-card, pre, .e2e-chain { background: #f5f5f5; border-color: #e5e5e5; }
|
|
224
|
+
.feature-card p, p { color: #525252; }
|
|
225
|
+
td { color: #1a1a1a; }
|
|
226
|
+
th { background: #f5f5f5; color: #525252; }
|
|
227
|
+
h2 { border-bottom-color: #e5e5e5; }
|
|
228
|
+
code { background: #f0f0f0; color: #dc2626; }
|
|
229
|
+
.e2e-chain .node { background: #f0f0f0; border-color: #d4d4d4; color: #1a1a1a; }
|
|
230
|
+
}
|
|
231
|
+
</style>
|
|
232
|
+
</head>
|
|
233
|
+
<body>
|
|
234
|
+
|
|
235
|
+
<div class="header">
|
|
236
|
+
<div class="logo">🦞</div>
|
|
237
|
+
<h1>APIClaw Session Report</h1>
|
|
238
|
+
<div class="subtitle">The API Layer for AI Agents</div>
|
|
239
|
+
<div class="date">Session: April 5, 2026 — NordSym AB</div>
|
|
240
|
+
</div>
|
|
241
|
+
|
|
242
|
+
<div class="highlight-box">
|
|
243
|
+
<p>APIClaw is now a live production API gateway.</p>
|
|
244
|
+
<div class="sub">Telegram bot responding via APIClaw. Anthropic OAuth dependency eliminated. E2E proven.</div>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<!-- ========== FEATURES ========== -->
|
|
248
|
+
<h2>What We Built</h2>
|
|
249
|
+
|
|
250
|
+
<div class="feature-grid">
|
|
251
|
+
<div class="feature-card">
|
|
252
|
+
<div class="num">Feature 1</div>
|
|
253
|
+
<h4>Workspace API Keys</h4>
|
|
254
|
+
<p>Generate persistent <code>sk-claw-</code> keys in your workspace. One key, every API. Keys are hashed after creation -- shown once, never stored in plain text.</p>
|
|
255
|
+
</div>
|
|
256
|
+
<div class="feature-card">
|
|
257
|
+
<div class="num">Feature 2</div>
|
|
258
|
+
<h4>Unified Auth Layer</h4>
|
|
259
|
+
<p>All 15+ proxy endpoints upgraded in one change. Accepts <code>Authorization: Bearer sk-claw-...</code> alongside legacy identifier auth. Zero breaking changes.</p>
|
|
260
|
+
</div>
|
|
261
|
+
<div class="feature-card">
|
|
262
|
+
<div class="num">Feature 3</div>
|
|
263
|
+
<h4>Gateway /v1/chat/completions</h4>
|
|
264
|
+
<p>OpenAI-compatible LLM endpoint. Routes to OpenRouter (800+ models). Streaming support. Usage tracking. Standard protocol -- works with any AI tool.</p>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="feature-card">
|
|
267
|
+
<div class="num">Feature 4</div>
|
|
268
|
+
<h4>OpenClaw Integration</h4>
|
|
269
|
+
<p>APIClaw configured as a first-class provider in OpenClaw. Telegram bots now powered entirely by APIClaw gateway. No direct Anthropic key needed.</p>
|
|
270
|
+
</div>
|
|
271
|
+
</div>
|
|
272
|
+
|
|
273
|
+
<!-- ========== E2E CHAIN ========== -->
|
|
274
|
+
<h2>E2E Architecture</h2>
|
|
275
|
+
|
|
276
|
+
<div class="e2e-chain">
|
|
277
|
+
<div class="node">Telegram</div>
|
|
278
|
+
<div class="arrow">→</div>
|
|
279
|
+
<div class="node">OpenClaw Gateway</div>
|
|
280
|
+
<div class="arrow">→</div>
|
|
281
|
+
<div class="node">APIClaw Gateway<br><small style="color:#ef4444">sk-claw-...q6Yd</small></div>
|
|
282
|
+
<div class="arrow">→</div>
|
|
283
|
+
<div class="node">OpenRouter</div>
|
|
284
|
+
<div class="arrow">→</div>
|
|
285
|
+
<div class="node">Claude Sonnet 4.6</div>
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<!-- ========== TEST RESULTS ========== -->
|
|
289
|
+
<h2>E2E Test Results</h2>
|
|
290
|
+
|
|
291
|
+
<table>
|
|
292
|
+
<thead>
|
|
293
|
+
<tr><th>Test</th><th>Result</th><th>Latency</th></tr>
|
|
294
|
+
</thead>
|
|
295
|
+
<tbody>
|
|
296
|
+
<tr>
|
|
297
|
+
<td><code>GET /v1/models</code> on prod</td>
|
|
298
|
+
<td class="status-pass">13 models listed</td>
|
|
299
|
+
<td>--</td>
|
|
300
|
+
</tr>
|
|
301
|
+
<tr>
|
|
302
|
+
<td>Fake key rejection</td>
|
|
303
|
+
<td class="status-pass">401 with error message</td>
|
|
304
|
+
<td>--</td>
|
|
305
|
+
</tr>
|
|
306
|
+
<tr>
|
|
307
|
+
<td><code>sk-claw-</code> → Gateway → OpenRouter → Claude</td>
|
|
308
|
+
<td class="status-pass">Response received</td>
|
|
309
|
+
<td>2.2s</td>
|
|
310
|
+
</tr>
|
|
311
|
+
<tr>
|
|
312
|
+
<td>OpenClaw CLI → APIClaw → Telegram delivery</td>
|
|
313
|
+
<td class="status-pass">"APIClaw e2e works through OpenClaw"</td>
|
|
314
|
+
<td>17.8s</td>
|
|
315
|
+
</tr>
|
|
316
|
+
<tr>
|
|
317
|
+
<td>Telegram DM → bot responds</td>
|
|
318
|
+
<td class="status-pass">Confirmed live by operator</td>
|
|
319
|
+
<td>--</td>
|
|
320
|
+
</tr>
|
|
321
|
+
</tbody>
|
|
322
|
+
</table>
|
|
323
|
+
|
|
324
|
+
<!-- ========== BACKEND DETAIL ========== -->
|
|
325
|
+
<h2>Backend: API Keys</h2>
|
|
326
|
+
|
|
327
|
+
<h3>Schema (convex/schema.ts)</h3>
|
|
328
|
+
<pre>workspaceApiKeys: defineTable({
|
|
329
|
+
workspaceId: v.id("workspaces"),
|
|
330
|
+
key: v.string(),
|
|
331
|
+
keyHash: v.string(), // SHA lookup (raw key not stored)
|
|
332
|
+
keyPrefix: v.string(), // "sk-claw-...last4" for display
|
|
333
|
+
name: v.string(), // user label
|
|
334
|
+
lastUsedAt: v.optional(v.number()),
|
|
335
|
+
createdAt: v.number(),
|
|
336
|
+
revokedAt: v.optional(v.number()),
|
|
337
|
+
})
|
|
338
|
+
.index("by_keyHash", ["keyHash"])
|
|
339
|
+
.index("by_workspaceId", ["workspaceId"])</pre>
|
|
340
|
+
|
|
341
|
+
<h3>Functions (convex/apiKeys.ts)</h3>
|
|
342
|
+
<table>
|
|
343
|
+
<thead><tr><th>Function</th><th>Type</th><th>Purpose</th></tr></thead>
|
|
344
|
+
<tbody>
|
|
345
|
+
<tr><td><code>generateKey</code></td><td>mutation</td><td>Create key, return raw ONCE, store hash only</td></tr>
|
|
346
|
+
<tr><td><code>listKeys</code></td><td>query</td><td>Return prefix + metadata (never raw key)</td></tr>
|
|
347
|
+
<tr><td><code>revokeKey</code></td><td>mutation</td><td>Soft delete with revokedAt timestamp</td></tr>
|
|
348
|
+
<tr><td><code>resolveKey</code></td><td>internalQuery</td><td>Hash lookup for gateway auth</td></tr>
|
|
349
|
+
<tr><td><code>touchKey</code></td><td>mutation</td><td>Update lastUsedAt on each use</td></tr>
|
|
350
|
+
</tbody>
|
|
351
|
+
</table>
|
|
352
|
+
|
|
353
|
+
<!-- ========== GATEWAY DETAIL ========== -->
|
|
354
|
+
<h2>Backend: Gateway</h2>
|
|
355
|
+
|
|
356
|
+
<h3>Auth Resolution (convex/http.ts)</h3>
|
|
357
|
+
<pre>resolveWorkspaceFromRequest(ctx, request)
|
|
358
|
+
1. Authorization: Bearer sk-claw-... → resolveKey → workspaceId
|
|
359
|
+
2. X-APIClaw-Identifier (legacy) → workspaceId
|
|
360
|
+
3. Anonymous → allowed, untracked</pre>
|
|
361
|
+
|
|
362
|
+
<h3>Endpoints</h3>
|
|
363
|
+
<table>
|
|
364
|
+
<thead><tr><th>Endpoint</th><th>Method</th><th>Auth</th><th>Purpose</th></tr></thead>
|
|
365
|
+
<tbody>
|
|
366
|
+
<tr><td><code>/v1/chat/completions</code></td><td>POST</td><td>sk-claw- required</td><td>OpenAI-compatible LLM gateway</td></tr>
|
|
367
|
+
<tr><td><code>/v1/models</code></td><td>GET</td><td>optional</td><td>List available models</td></tr>
|
|
368
|
+
<tr><td><code>/proxy/*</code> (15+ routes)</td><td>POST</td><td>sk-claw- or legacy</td><td>All existing API proxies</td></tr>
|
|
369
|
+
</tbody>
|
|
370
|
+
</table>
|
|
371
|
+
|
|
372
|
+
<!-- ========== OPENCLAW CONFIG ========== -->
|
|
373
|
+
<h2>OpenClaw Configuration</h2>
|
|
374
|
+
|
|
375
|
+
<pre>{
|
|
376
|
+
"models": {
|
|
377
|
+
"providers": {
|
|
378
|
+
"apiclaw": {
|
|
379
|
+
"baseUrl": "https://adventurous-avocet-799.convex.site/v1",
|
|
380
|
+
"apiKey": "sk-claw-...q6Yd",
|
|
381
|
+
"api": "openai-completions",
|
|
382
|
+
"auth": "api-key",
|
|
383
|
+
"models": [
|
|
384
|
+
{ "id": "anthropic/claude-sonnet-4-6", "name": "Claude Sonnet 4.6" },
|
|
385
|
+
{ "id": "anthropic/claude-haiku-3.5", "name": "Claude Haiku 3.5" },
|
|
386
|
+
{ "id": "openai/gpt-4o", "name": "GPT-4o" },
|
|
387
|
+
{ "id": "google/gemini-2.5-pro-preview", "name": "Gemini 2.5 Pro" },
|
|
388
|
+
{ "id": "meta-llama/llama-3.3-70b-instruct", "name": "Llama 3.3 70B" },
|
|
389
|
+
{ "id": "deepseek/deepseek-chat", "name": "DeepSeek Chat" }
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}</pre>
|
|
395
|
+
|
|
396
|
+
<p><strong>Key discovery:</strong> OpenClaw appends <code>/chat/completions</code> to baseUrl. The baseUrl must include <code>/v1</code>.</p>
|
|
397
|
+
|
|
398
|
+
<!-- ========== FILES ========== -->
|
|
399
|
+
<h2>Files Changed</h2>
|
|
400
|
+
|
|
401
|
+
<ul class="files-list">
|
|
402
|
+
<li><code>convex/schema.ts</code> <span>Added workspaceApiKeys table + indexes</span></li>
|
|
403
|
+
<li><code>convex/apiKeys.ts</code> <span class="badge badge-new">NEW</span> <span>Generate, list, revoke, resolve, touch</span></li>
|
|
404
|
+
<li><code>convex/http.ts</code> <span>Unified auth + /v1/chat/completions + /v1/models</span></li>
|
|
405
|
+
<li><code>landing/.../workspace/page.tsx</code> <span>API Keys tab + nav + config snippet</span></li>
|
|
406
|
+
<li><code>~/.openclaw/openclaw.json</code> <span>APIClaw as primary provider, Telegram restored</span></li>
|
|
407
|
+
</ul>
|
|
408
|
+
|
|
409
|
+
<!-- ========== PRODUCTION STATE ========== -->
|
|
410
|
+
<h2>Production State</h2>
|
|
411
|
+
|
|
412
|
+
<table>
|
|
413
|
+
<thead><tr><th>Component</th><th>Status</th><th>Detail</th></tr></thead>
|
|
414
|
+
<tbody>
|
|
415
|
+
<tr><td>Convex prod</td><td><span class="badge badge-green">DEPLOYED</span></td><td>adventurous-avocet-799</td></tr>
|
|
416
|
+
<tr><td>Gateway endpoint</td><td><span class="badge badge-green">LIVE</span></td><td>/v1/chat/completions responding</td></tr>
|
|
417
|
+
<tr><td>Prod API key</td><td><span class="badge badge-green">ACTIVE</span></td><td>sk-claw-...q6Yd ("OpenClaw Production")</td></tr>
|
|
418
|
+
<tr><td>OpenClaw default model</td><td><span class="badge badge-green">ACTIVE</span></td><td>apiclaw/anthropic/claude-sonnet-4-6</td></tr>
|
|
419
|
+
<tr><td>Telegram bots</td><td><span class="badge badge-green">LIVE</span></td><td>4 accounts responding</td></tr>
|
|
420
|
+
<tr><td>Anthropic OAuth</td><td><span class="badge badge-red">ELIMINATED</span></td><td>No longer needed</td></tr>
|
|
421
|
+
<tr><td>Frontend build</td><td><span class="badge badge-green">CLEAN</span></td><td>Next.js + Convex both pass</td></tr>
|
|
422
|
+
</tbody>
|
|
423
|
+
</table>
|
|
424
|
+
|
|
425
|
+
<!-- ========== FOOTER ========== -->
|
|
426
|
+
<div class="footer">
|
|
427
|
+
<p class="brand">NordSym AB (559535-5768)</p>
|
|
428
|
+
<p>APIClaw -- The API Layer for AI Agents</p>
|
|
429
|
+
<p>Session report generated April 5, 2026</p>
|
|
430
|
+
</div>
|
|
431
|
+
|
|
432
|
+
</body>
|
|
433
|
+
</html>
|
package/src/cli/commands/demo.ts
CHANGED
|
@@ -61,7 +61,7 @@ async function convertCurrency(): Promise<void> {
|
|
|
61
61
|
chalk.dim(` No API key needed. Your agent can call this too.\n`)
|
|
62
62
|
);
|
|
63
63
|
console.log(
|
|
64
|
-
chalk.cyan(` Dashboard: https://apiclaw.
|
|
64
|
+
chalk.cyan(` Dashboard: https://apiclaw.cloud/workspace`) + '\n'
|
|
65
65
|
);
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -104,6 +104,6 @@ export async function demoCommand(): Promise<void> {
|
|
|
104
104
|
);
|
|
105
105
|
} catch (err: any) {
|
|
106
106
|
spinner.fail('Demo failed: ' + err.message);
|
|
107
|
-
console.log(chalk.dim('\n Try again or check https://apiclaw.
|
|
107
|
+
console.log(chalk.dim('\n Try again or check https://apiclaw.cloud\n'));
|
|
108
108
|
}
|
|
109
109
|
}
|
|
@@ -174,7 +174,7 @@ async function checkConnectivity(): Promise<CheckResult> {
|
|
|
174
174
|
const convexUrl = process.env.CONVEX_URL || 'https://brilliant-puffin-712.eu-west-1.convex.cloud';
|
|
175
175
|
const candidates = [
|
|
176
176
|
`${apiUrl}/health`,
|
|
177
|
-
'https://apiclaw.
|
|
177
|
+
'https://apiclaw.cloud',
|
|
178
178
|
`${convexUrl.replace('.cloud', '.site')}/workspace/poll`,
|
|
179
179
|
];
|
|
180
180
|
const failures: string[] = [];
|
|
@@ -10,7 +10,7 @@ import chalk from 'chalk';
|
|
|
10
10
|
import { writeSession, readSession, getMachineFingerprint } from '../../session.js';
|
|
11
11
|
|
|
12
12
|
const CONVEX_URL = 'https://adventurous-avocet-799.convex.cloud';
|
|
13
|
-
const APICLAW_URL = 'https://apiclaw.
|
|
13
|
+
const APICLAW_URL = 'https://apiclaw.cloud';
|
|
14
14
|
const POLL_INTERVAL_MS = 2000;
|
|
15
15
|
const MAX_WAIT_MS = 15 * 60 * 1000; // 15 min (magic link TTL)
|
|
16
16
|
|