Skip to content

Commit f3370da

Browse files
AEGISclaude
andcommitted
docs: add API key, billing guides and update getting-started for OAuth signup
Add API key management guide covering generation, validation, rotation, and revocation (closes #8). Add billing & subscription docs covering Stripe checkout, customer portal, tier management, and webhook lifecycle (closes #9). Update getting-started to document OAuth signup flow and remove waitlist references (closes #10). Confirm pricing reflects $29/mo Pro tier across all pages (closes #7). Add cross-links from platform and ecosystem pages to the new guides. Closes #7, #8, #9, #10 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1c629af commit f3370da

5 files changed

Lines changed: 526 additions & 4 deletions

File tree

src/content/docs/api-keys.md

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
---
2+
title: "API Key Management"
3+
description: "Generate, validate, rotate, and revoke API keys for programmatic access to Stackbilt services."
4+
section: "platform"
5+
order: 10
6+
color: "#f59e0b"
7+
tag: "10"
8+
---
9+
10+
# API Key Management
11+
12+
API keys provide programmatic access to Stackbilt services without requiring an interactive OAuth session. Use them for CI/CD pipelines, backend integrations, MCP clients, and automated workflows.
13+
14+
## Key Prefixes
15+
16+
Stackbilt uses prefixed keys to identify the key type and scope:
17+
18+
| Prefix | Service | Description |
19+
|--------|---------|-------------|
20+
| `ea_` | edge-auth | General-purpose API keys issued through edge-auth |
21+
| `sb_live_` | Stackbilder | Production keys for the Stackbilder platform |
22+
| `sb_test_` | Stackbilder | Test/sandbox keys for development |
23+
| `imgf_` | img-forge | Image generation API keys |
24+
25+
All key types are validated through edge-auth's centralized identity layer.
26+
27+
## Generating a Key
28+
29+
### Via the REST API
30+
31+
```
32+
POST https://auth.stackbilt.dev/api-keys
33+
```
34+
35+
Requires an authenticated session. The response includes the raw key **once** -- store it securely, as it cannot be retrieved again.
36+
37+
**Request body:**
38+
39+
```json
40+
{
41+
"orgId": "org_stackbilt",
42+
"projectId": "prop_stackbilder",
43+
"label": "CI/CD Pipeline",
44+
"scopes": ["ai:invoke", "read"]
45+
}
46+
```
47+
48+
| Field | Type | Required | Description |
49+
|-------|------|----------|-------------|
50+
| `orgId` | string | Yes | Organization the key belongs to |
51+
| `projectId` | string | No | Scope to a specific project (recommended) |
52+
| `tenantId` | string | No | Scope to a specific tenant |
53+
| `label` | string | No | Human-readable name for the key |
54+
| `scopes` | string[] | No | Permission scopes (default: all scopes) |
55+
56+
**Response (`201 Created`):**
57+
58+
```json
59+
{
60+
"key": "ea_abc123...xyz",
61+
"keyId": "uuid",
62+
"prefix": "ea_abc123"
63+
}
64+
```
65+
66+
### Via RPC (Service Binding)
67+
68+
Other Stackbilt services call the `generateApiKey` RPC method on the `EdgeAuthEntrypoint`:
69+
70+
```typescript
71+
const result = await env.AUTH_SERVICE.generateApiKey({
72+
userId: "user-id",
73+
name: "MCP Access Key",
74+
});
75+
// result.key — raw key (store securely)
76+
// result.id — key ID for management operations
77+
```
78+
79+
## Using a Key
80+
81+
Include the key in the `Authorization` header:
82+
83+
```bash
84+
curl -X GET https://auth.stackbilt.dev/api-keys?org_id=org_stackbilt \
85+
-H "Authorization: Bearer ea_your_key_here"
86+
```
87+
88+
For img-forge, the `X-API-Key` header is also accepted:
89+
90+
```bash
91+
curl -X POST https://imgforge.stackbilt.dev/v2/generate \
92+
-H "X-API-Key: imgf_your_key_here" \
93+
-H "Content-Type: application/json" \
94+
-d '{"prompt": "A mountain landscape"}'
95+
```
96+
97+
## Validation
98+
99+
API key validation is constant-time and uses SHA-256 hashing. The system:
100+
101+
1. Extracts the key prefix (first 11 characters)
102+
2. Looks up the key row by prefix
103+
3. Performs constant-time hash verification via Web Crypto
104+
4. Checks expiration and revocation status
105+
5. Returns the key's scopes, org, project, and tenant bindings
106+
107+
**Validation response shape:**
108+
109+
```json
110+
{
111+
"valid": true,
112+
"keyId": "uuid",
113+
"userId": "user-id or null",
114+
"orgId": "org_stackbilt",
115+
"projectId": "prop_stackbilder or null",
116+
"tenantId": "tenant-id or null",
117+
"scopes": ["ai:invoke", "read"],
118+
"rateLimit": {
119+
"limit": 1000,
120+
"remaining": 998,
121+
"resetAt": 1234567890
122+
}
123+
}
124+
```
125+
126+
Invalid, revoked, or expired keys receive a uniform 403 denial with no distinguishing information. This prevents key enumeration and timing attacks.
127+
128+
## Listing Keys
129+
130+
```
131+
GET https://auth.stackbilt.dev/api-keys?org_id=org_stackbilt
132+
```
133+
134+
Returns all active (non-revoked) keys for the organization. Raw key values are never returned -- only the prefix is shown.
135+
136+
**Response:**
137+
138+
```json
139+
[
140+
{
141+
"id": "uuid",
142+
"prefix": "ea_abc1234",
143+
"label": "CI/CD Pipeline",
144+
"scopes": ["ai:invoke", "read"],
145+
"projectId": "prop_stackbilder",
146+
"lastUsedAt": "2026-04-01T12:00:00Z",
147+
"createdAt": "2026-03-15T09:00:00Z"
148+
}
149+
]
150+
```
151+
152+
## Revoking a Key
153+
154+
```
155+
DELETE https://auth.stackbilt.dev/api-keys/:keyId
156+
```
157+
158+
Revocation is a soft delete -- the key row is marked `revoked = 1` and immediately stops validating. Revoked keys cannot be un-revoked; generate a new key instead.
159+
160+
```bash
161+
curl -X DELETE https://auth.stackbilt.dev/api-keys/key-uuid \
162+
-H "Authorization: Bearer ea_your_admin_key"
163+
```
164+
165+
**Response:**
166+
167+
```json
168+
{
169+
"success": true
170+
}
171+
```
172+
173+
## Rotation
174+
175+
To rotate a key:
176+
177+
1. Generate a new key with the same scopes and project binding
178+
2. Update your application configuration to use the new key
179+
3. Verify the new key works by making a test request
180+
4. Revoke the old key
181+
182+
There is no atomic rotation endpoint -- this two-step process ensures zero downtime. Both keys remain valid until the old one is explicitly revoked.
183+
184+
For img-forge keys, the gateway provides an atomic rotation endpoint:
185+
186+
```
187+
POST https://imgforge.stackbilt.dev/v2/tenants/:id/rotate
188+
```
189+
190+
This invalidates the current key and returns a new one in a single request.
191+
192+
## Scope Reference
193+
194+
| Scope | Description |
195+
|-------|-------------|
196+
| `ai:invoke` | Call MCP tools and scaffold endpoints |
197+
| `read` | Read flows, images, and project data |
198+
| `generate` | Create image generation jobs (img-forge) |
199+
200+
When no scopes are specified at creation, the key inherits all scopes available to the creating user's role.
201+
202+
## Access Control
203+
204+
API key operations are governed by edge-auth's policy engine:
205+
206+
- **Creating org-wide keys** (no `projectId`) requires org admin role or a service principal. Project-scoped keys or member-role users cannot mint org-wide keys.
207+
- **Creating project-scoped keys** requires at least member access to the project's org.
208+
- **Revoking keys** requires access to the key's org (and project, if project-scoped).
209+
- **Listing keys** requires read access to the org.
210+
211+
All API key operations are audit-logged with risk level, principal identity, and outcome.
212+
213+
## Security
214+
215+
- Keys are hashed with SHA-256 before storage. Raw keys exist only in memory during generation and in the creation response.
216+
- Validation uses constant-time comparison to prevent timing attacks.
217+
- All denied requests return a uniform 403 response -- the system does not distinguish between nonexistent keys, revoked keys, and unauthorized access.
218+
- `last_used_at` is updated on each successful validation for monitoring.
219+
- Keys can optionally carry an `expires_at` timestamp for automatic expiration.

0 commit comments

Comments
 (0)