Webhooks & Integration
Reference for Stripe webhook events, payload handling, idempotency, rate limits across all 26 API routes, and integration points for CLI and MCP.
Reference for Stripe webhook events, integration points, and rate limits across all API routes.
Stripe webhooks
MyClaude listens for Stripe events at a single endpoint:
POST /api/stripe/webhooksThis endpoint is exempt from CSRF origin checks and Bearer token auth. It authenticates exclusively via Stripe webhook signature verification.
Handled events
| Event | Action |
|---|---|
checkout.session.completed | Creates order, updates product stats, credits XP to buyer and seller |
charge.refunded | Marks order as refunded, reverses seller revenue and stats, notifies seller |
account.updated | Updates seller stripeOnboarded status when charges_enabled becomes true |
All other event types are acknowledged with 200 and silently ignored.
Webhook security
Signature verification
Every incoming webhook is verified using stripe.webhooks.constructEvent() with the STRIPE_WEBHOOK_SECRET. Requests with missing or invalid signatures receive 400 and are not processed.
Request arrives
|
v
Extract stripe-signature header
|
v
constructEvent(body, signature, secret)
|-- Invalid --> 400 (no retry)
|-- Valid --> Process eventIdempotency
Order creation uses the Stripe session ID as the Firestore document ID. This guarantees idempotency:
- First delivery: transaction creates the order document
- Retry delivery: transaction reads the existing document, detects duplicate, skips creation
- No duplicate orders, no duplicate stat increments
The check runs inside a Firestore transaction, so concurrent webhook retries are also safe.
Atomic order creation
The checkout.session.completed handler executes a single Firestore transaction that atomically:
- Creates the
orders/{sessionId}document - Increments
products/{id}.stats.purchaseCount - Increments
users/{sellerId}.stats.totalRevenueandstats.totalSales, adds 50 XP - Increments
users/{buyerId}.stats.productsBought, adds 10 XP
If any step fails, the entire transaction rolls back. Stripe receives 503, which triggers automatic retry with exponential backoff.
Price verification
The webhook handler re-reads the product price from Firestore and cross-checks against session.amount_total. If a price change occurred between checkout creation and webhook delivery, the discrepancy is logged but the order is still created using Stripe's authoritative amount (what was actually charged).
Platform fee is recalculated server-side at 8% of the actual charged amount -- never from client metadata.
Refund handling
The charge.refunded handler:
- Looks up the order by
stripePaymentIntentId - Runs an atomic transaction: sets
status: "refunded", decrements seller revenue and sales count, decrements buyer purchase count - Creates a notification in the seller's
notificationssubcollection (fire-and-forget, outside transaction)
Already-refunded orders are skipped (idempotent).
Integration points
CLI (myclaude)
The myclaude CLI communicates with dedicated API routes optimized for terminal output.
| CLI command | API route | Auth |
|---|---|---|
myclaude search | GET /api/cli/products/search | None |
myclaude publish | POST /api/cli/products/create | Required |
myclaude whoami | GET /api/cli/auth/profile | Required |
All CLI commands support a --json flag for machine-readable output, suitable for piping into jq or downstream scripts.
MCP server
MyClaude exposes tools via Model Context Protocol for agent integration. Agents can search products, read metadata, and trigger installations through MCP tool calls. See the MCP Tool Schemas reference for the full tool catalog.
Docs A-Surface
Requests to /docs.md or /docs/{slug}.md are rewritten to return raw Markdown content from the documentation system. This enables AI agents to fetch docs context without parsing HTML.
Rate limits
All routes are rate-limited per IP address within a 60-second window. Two strategies exist:
| Strategy | On limit exceeded | On limiter failure |
|---|---|---|
| Standard | 429 | Fail-open (allows request) |
| Strict | 429 | Fail-closed (503) |
Complete rate limit table
| Route | Method | Limit | Strategy | Auth |
|---|---|---|---|---|
/stripe/checkout | POST | 10/min | Strict | Required |
/stripe/connect | POST | 5/min | Strict | Required |
/stripe/webhooks | POST | -- | -- | Stripe signature |
/stripe/callback | GET | -- | -- | Redirect |
/products/download | POST | 30/min | Strict | Required |
/products/upload | POST | 10/min | Strict | Required |
/products/scan | POST | 10/min | Strict | Required |
/products/like | POST | 30/min | Strict | Required |
/products/reviews | GET | 30/min | Standard | Optional |
/products/reviews | POST | 5/min | Strict | Required |
/products/self-approve | POST | 20/min | Strict | Required |
/users/update-profile | POST | 5/min | Strict | Required |
/users/follow | POST | 30/min | Strict | Required |
/users/delete-account | DELETE | 1/min | Strict | Required |
/reports | POST | 10/min | Strict | Required |
/messages | GET | 60/min | Standard | Required |
/messages | POST | 20/min | Strict | Required |
/messages/{id} | GET | 60/min | Standard | Required |
/admin/products/{id}/approve | POST | 10/min | Strict | Admin |
/admin/products/{id}/remove | POST | 10/min | Strict | Admin |
/admin/reports | GET | 30/min | Standard | Admin |
/admin/reports/{id}/resolve | POST | 10/min | Strict | Admin |
/admin/users/{id}/ban | POST | 5/min | Strict | Admin |
/cli/products/search | GET | 30/min | Standard | None |
/cli/auth/profile | GET | 30/min | Standard | Required |
/cli/products/create | POST | 5/min | Strict | Required |
Rate limit response
When a rate limit is exceeded, the API returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 42
{
"error": "Too many requests"
}The Retry-After header indicates seconds until the window resets.
Error codes
All API errors follow a consistent JSON format:
{
"error": "Human-readable error message"
}| Status | Meaning | Common causes |
|---|---|---|
400 | Bad Request | Missing parameters, invalid metadata, business rule violation |
401 | Unauthorized | Missing or expired Bearer token |
403 | Forbidden | Insufficient permissions, banned user, CSRF origin mismatch |
404 | Not Found | Resource does not exist or is unpublished |
409 | Conflict | Duplicate purchase, duplicate review, username taken |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Unexpected failure |
503 | Service Unavailable | Dependency down, or strict rate limiter failure |
For the full error taxonomy, see /specs/error-codes.yaml in the repository.
Related pages
- API Overview -- Base URL, auth model, endpoint groups
- Payments API -- Checkout and Connect endpoint details
- Security Model -- Architecture-level security controls
- MCP Tool Schemas -- Agent integration reference
- Self-Hosting -- Deployment and webhook configuration
Self-Hosting
Deploy your own MyClaude marketplace instance with Firebase, Stripe Connect, Cloudflare R2, and Vercel or a standalone Node.js server.
Design System Reference
Complete reference for MyClaude's design system: color tokens, typography scale, surfaces, glow shadows, motion, z-index, spacing, component inventory, and the token-only enforcement policy.