clawskills-mcp 0.2.0 → 0.3.0

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.
@@ -185,7 +185,7 @@ const REQUIRED_SECTIONS = [
185
185
  const KNOWN_SKILLS = [
186
186
  "asana", "dynamics365", "figma", "github", "hubspot",
187
187
  "jira", "monday", "salesforce", "servicenow", "zendesk",
188
- "slack",
188
+ "slack", "stripe",
189
189
  ];
190
190
  describe("real skills", () => {
191
191
  let skills;
package/package.json CHANGED
@@ -1,7 +1,29 @@
1
1
  {
2
2
  "name": "clawskills-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server exposing ClawSkills API integration skill docs to AI agents",
5
+ "license": "MIT",
6
+ "author": "ClawSkills Contributors",
7
+ "homepage": "https://github.com/Shanksg/clawskills#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Shanksg/clawskills.git"
11
+ },
12
+ "keywords": [
13
+ "mcp",
14
+ "claude",
15
+ "ai",
16
+ "integration",
17
+ "api",
18
+ "skill",
19
+ "salesforce",
20
+ "hubspot",
21
+ "jira",
22
+ "zendesk",
23
+ "slack",
24
+ "crm",
25
+ "saas"
26
+ ],
5
27
  "type": "module",
6
28
  "bin": {
7
29
  "clawskills-mcp": "dist/index.js"
package/skills/INDEX.md CHANGED
@@ -21,6 +21,7 @@ A curated library of integration skill documents for the most common SaaS platfo
21
21
  | GitHub | [github/skill.md](./github/skill.md) | Engineering, DevOps | Source control, PRs, CI/CD automation via REST + GraphQL |
22
22
  | Figma | [figma/skill.md](./figma/skill.md) | Design, Product, DevOps | Design file inspection, asset export, webhooks, design-to-dev handoff |
23
23
  | Slack | [slack/skill.md](./slack/skill.md) | All teams | Real-time messaging, notifications, event-driven automation via Web API |
24
+ | Stripe | [stripe/skill.md](./stripe/skill.md) | Engineering, Finance, RevOps | Payments, subscriptions, refunds, webhooks, and Connect for platforms |
24
25
 
25
26
  ---
26
27
 
@@ -180,6 +181,20 @@ A curated library of integration skill documents for the most common SaaS platfo
180
181
 
181
182
  ---
182
183
 
184
+ ### Stripe → [skill.md](./stripe/skill.md)
185
+ 1. Create a PaymentIntent for a one-time charge and confirm with Stripe.js
186
+ 2. Save a card for future off-session charges (SetupIntent → attach PaymentMethod)
187
+ 3. Create a recurring subscription (Customer + Price + Subscription)
188
+ 4. Launch a hosted Checkout Session and fulfil on `checkout.session.completed`
189
+ 5. Issue a full or partial refund
190
+ 6. Handle a failed subscription payment: notify customer, update payment method, retry invoice
191
+ 7. Receive and verify webhooks (Stripe-Signature HMAC-SHA256 verification)
192
+ 8. Stripe Connect: create a connected account, generate onboarding link, destination charge
193
+ 9. List all charges for a customer with cursor pagination
194
+ 10. Cancel a subscription at period end
195
+
196
+ ---
197
+
183
198
  ## Common Cross-Tool Patterns
184
199
 
185
200
  These scenarios span multiple skill docs — reference both tools:
@@ -197,6 +212,9 @@ These scenarios span multiple skill docs — reference both tools:
197
212
  | Bug report → GitHub issue + PR | Zendesk / ServiceNow | GitHub | Auto-create issue, label, assign; link ticket ID in body |
198
213
  | Design ready → engineering task | Figma | Jira / Asana / GitHub | `DEV_MODE_STATUS_UPDATE` webhook → create/update issue with frame link |
199
214
  | Asset pipeline | Figma | S3 / CDN | `FILE_VERSION_UPDATE` webhook → export frames as PNG, upload to storage |
215
+ | Payment succeeded → CRM deal closed | Stripe | Salesforce / HubSpot | `payment_intent.succeeded` webhook → update deal stage to Closed Won |
216
+ | Subscription cancelled → support ticket | Stripe | Zendesk / Jira | `customer.subscription.deleted` → create ticket for churn review |
217
+ | Invoice paid → project provisioned | Stripe | Asana / Monday.com | `invoice.paid` webhook → create onboarding project or board item |
200
218
 
201
219
  ---
202
220
 
@@ -215,6 +233,7 @@ These scenarios span multiple skill docs — reference both tools:
215
233
  | GitHub | Fine-grained PAT or GitHub App installation token | Bearer token | Per-resource permissions (contents, issues, pull_requests, etc.) |
216
234
  | Figma | Personal Access Token (PAT) or OAuth 2.0 | `X-Figma-Token` (PAT) / `Authorization: Bearer` (OAuth) | Granular scopes: `file_content:read`, `webhooks:write`, etc. |
217
235
  | Slack | Bot token (OAuth 2.0 app install) | `xoxb-...` Bearer token | Per-method scopes: `chat:write`, `channels:read`, `users:read`, etc. |
236
+ | Stripe | Secret API key or Restricted key | `Authorization: Bearer sk_live_...` | Per-resource scopes on restricted keys (None / Read / Write) |
218
237
 
219
238
  ---
220
239
 
@@ -233,10 +252,11 @@ These scenarios span multiple skill docs — reference both tools:
233
252
  | GitHub | PAT: 5,000/hr · GitHub App: 5k–12.5k/hr · Enterprise Cloud: 15,000/hr · Secondary: 900 pts/min, 80 create/min | 1 hour (primary) + sliding (secondary) | `x-ratelimit-remaining` / `x-ratelimit-reset`; 403 or 429 |
234
253
  | Figma | Starter: 10/min (T1), 25/min (T2) · Professional: 15/min (T1), 50/min (T2) · Org: 20/min (T1), 100/min (T2) | Per minute (leaky bucket) | `Retry-After` / `X-Figma-Rate-Limit-Type` / `X-Figma-Plan-Tier` |
235
254
  | Slack | Tier 1: 1/min · Tier 2: 20/min · Tier 3: 50/min · Tier 4: 100/min · `chat.postMessage`: 1/sec/channel sub-limit | Per method per workspace | HTTP 429 + `Retry-After` header (seconds) |
255
+ | Stripe | Live: **100 req/sec** · Sandbox: **25 req/sec** · Search: 20/sec | Per account | HTTP 429 + `Stripe-Rate-Limited-Reason` header |
236
256
 
237
257
  ---
238
258
 
239
- *Last updated: 2026-02-26 (Slack skill added) | See [ROADMAP.md](./ROADMAP.md) for versioning and governance details.*
259
+ *Last updated: 2026-03-01 (Stripe skill added) | See [ROADMAP.md](./ROADMAP.md) for versioning and governance details.*
240
260
 
241
261
  ### API version reference (as of 2026-02-22)
242
262
 
@@ -253,3 +273,4 @@ These scenarios span multiple skill docs — reference both tools:
253
273
  | GitHub | REST API + GraphQL v4 | Pin `X-GitHub-Api-Version: 2022-11-28`; fine-grained PATs recommended |
254
274
  | Figma | REST API v1 / Webhooks V2 | Path-based versioning (`/v1/`, `/v2/`); `files:read` scope deprecated — use granular scopes |
255
275
  | Slack | Web API (no versioned path) | Always check `ok` field (HTTP 200 even on errors); `files.upload` deprecated — use `files.getUploadURLExternal` |
276
+ | Stripe | `2026-02-25.clover` | Pin with `Stripe-Version` header; amounts in smallest currency unit (cents); never log raw card data |
package/skills/ROADMAP.md CHANGED
@@ -12,229 +12,152 @@ This skill set enables end-to-end automation and integration across the most com
12
12
 
13
13
  ---
14
14
 
15
- ## Prioritization Framework
15
+ ## Current state (as of 2026-03-01)
16
16
 
17
- Each skill/recipe is scored on five dimensions (1–5 each):
17
+ ### What's shipped
18
18
 
19
- | Dimension | Description |
20
- |-----------|-------------|
21
- | **Impact** | Business value if automated (revenue, hours saved, error reduction) |
22
- | **Frequency** | How often the workflow runs daily/weekly |
23
- | **Complexity** | Inverse score — simpler = higher priority for Phase 1 |
24
- | **Risk** | Inverse score — lower risk of data loss/compliance issue = higher priority |
25
- | **Dependencies** | Whether other workflows or skills depend on this one being stable first |
19
+ | Layer | Status |
20
+ |-------|--------|
21
+ | **11 skill docs** — Monday.com, Salesforce, Jira, Dynamics 365, HubSpot, ServiceNow, Zendesk, Asana, GitHub, Figma, Slack | ✅ Live |
22
+ | **MCP server** — `clawskills-mcp` v0.2.3 on npm; `list_skills`, `get_skill`, `search_skills` | ✅ Live |
23
+ | **CI pipeline** — build + test on every push/PR via `ci.yml` | ✅ Live |
24
+ | **Release automation** — `release.yml` workflow_dispatch → bump, tag, npm publish via OIDC | ✅ Live |
25
+ | **Test suite** — Vitest unit tests + real-skills validation (required sections, ≥5 KB, all 11 tools) | ✅ Live |
26
+ | **Public repo readiness** — MIT license, `.gitignore`, full `package.json` metadata | ✅ Ready |
26
27
 
27
- **Priority score = (Impact × 2) + (Frequency × 1.5) + Complexity + Risk + Dependencies**
28
+ ### Content coverage by original phase
28
29
 
29
- Phases are ordered by descending average priority score within a theme.
30
+ | Phase | Theme | Status |
31
+ |-------|-------|--------|
32
+ | Phase 1 — Foundation (Auth + Core CRUD) | Auth flows, basic CRUD, retry patterns | ✅ Complete — all 11 tools |
33
+ | Phase 2 — High-Frequency Workflows | 6–12 recipes per tool | ✅ Complete — all 11 tools |
34
+ | Phase 3 — Event-Driven & Real-Time | Webhook setup, signature verification, event handling | ✅ Complete — all 11 tools |
35
+ | Phase 4 — Bulk & Advanced Operations | Batch APIs, large-volume patterns | ⚠️ Partial — documented for most tools; not all have >500-record examples |
36
+ | Phase 5 — Cross-Tool Orchestration | Multi-system recipes spanning 2+ tools | ❌ Not started — patterns listed in INDEX.md but no dedicated recipes |
30
37
 
31
38
  ---
32
39
 
33
- ## Phased Plan
34
-
35
- ### Phase 1 — Foundation: Auth + Core CRUD (Weeks 1–4)
40
+ ## Next development phase
36
41
 
37
- **Theme:** Get the basics right. Every subsequent skill depends on reliable authentication and basic object manipulation.
42
+ ### Priority 1 — Content expansion: 3 new skills
38
43
 
39
- **Deliverables:**
40
- - All 8 `skill.md` files: Authentication & Permissions section fully validated against live environments
41
- - Core CRUD recipes for each tool (Create, Read by ID, Update, List/Search)
42
- - Error handling playbook (auth errors, 429s, 5xx retries)
43
- - Shared retry/backoff library or pattern documented
44
+ Each new skill follows the 11-section template, lives on a `skill/<name>` branch, and is validated by CI before merge.
44
45
 
45
- **Cross-tool dependencies:**
46
- - OAuth 2.0 / token management pattern established first (applies to Salesforce JWT, Dynamics Azure AD, HubSpot Private Apps, Jira API Token, Asana PAT/OAuth, Zendesk API Token, ServiceNow OAuth, Monday token)
47
- - Secret storage convention agreed (env vars, vault reference) before any recipe is productionized
46
+ | Skill | Why | Key areas to cover |
47
+ |-------|-----|--------------------|
48
+ | **Stripe** | Most common payments API; revenue-critical workflows missing from current library | Webhooks (event types + signature), Checkout Sessions, subscriptions, refunds, idempotency keys, Connect (multi-account) |
49
+ | **Notion** | Knowledge base + lightweight PM; high demand for doc/wiki automation | Pages API, Databases + filters + sorts, Blocks API (rich text), Search, cursor pagination |
50
+ | **Linear** | Fast-growing engineering tool, increasingly replacing Jira at startups | Issues, Projects, Teams, Cycles, GraphQL API, webhooks, OAuth + PAT auth |
48
51
 
49
- **Acceptance criteria:**
50
- - [ ] Each tool: auth flow documented end-to-end with working curl example
51
- - [ ] Each tool: create + read + update recipe tested against sandbox/dev environment
52
- - [ ] 429 rate-limit retry returns success within 3 attempts for all tools
53
- - [ ] No credentials stored in code or logs
52
+ **Order:** Stripe → Notion → Linear (payments coverage is the biggest gap).
54
53
 
55
- **Definition of done:** A developer unfamiliar with any given tool can authenticate and perform a basic CRUD operation in under 30 minutes using only the skill doc.
54
+ **Acceptance criteria for each:**
55
+ - [ ] All 11 required sections present (CI enforces)
56
+ - [ ] `Last validated:` date in header
57
+ - [ ] Auth section has working `curl` example tested against sandbox/dev environment
58
+ - [ ] At least 8 recipes with request/response examples
59
+ - [ ] Rate limits verified against official docs
60
+ - [ ] INDEX.md and README.md updated
56
61
 
57
62
  ---
58
63
 
59
- ### Phase 2 — High-Frequency Workflows (Weeks 5–10)
64
+ ### Priority 2 — Freshness CI pipeline (the moat)
60
65
 
61
- **Theme:** The top 5 daily workflows per tool, covering the scenarios that save the most manual effort.
66
+ A weekly automated check that skill docs aren't stale and that key API patterns still work.
62
67
 
63
- **Deliverables:**
64
- - Monday.com: Intake form → item creation, status sync, approval tracking
65
- - Salesforce: Lead capture & dedup, opportunity stage update, activity logging (Task/Event)
66
- - Jira: Ticket creation from external event, JQL search + triage, workflow transition with required fields
67
- - Dynamics 365: Contact/Account upsert, opportunity pipeline update, activity logging
68
- - HubSpot: Contact/Company sync, Deal stage update, Engagement logging (call/email/note)
69
- - ServiceNow: Incident create from alert, state transition + work notes, assignment group routing
70
- - Zendesk: Ticket creation, status/priority update, internal note vs public reply
71
- - Asana: Task creation in project/section, status update, comment/story append
68
+ **Phase A — Staleness detection (low-effort, high-value):**
69
+ - Parse `Last validated:` date from each `skill.md` header
70
+ - Flag any doc older than 90 days in CI output
71
+ - Open a GitHub issue automatically when a doc exceeds the threshold
72
+ - Deliverable: `.github/workflows/freshness.yml` (weekly cron, `0 9 * * 1`) + `scripts/check-freshness.ts`
72
73
 
73
- **Cross-tool dependencies:**
74
- - Phase 1 auth foundation must be stable
75
- - Dedup/idempotency patterns (Phase 1) applied to all create recipes
74
+ **Phase B — Live smoke tests (medium-effort, highest-value — the real moat):**
75
+ - For each tool, maintain a minimal test that hits: auth endpoint + one read
76
+ - Run weekly against sandbox environments using stored credentials (GitHub Secrets)
77
+ - Failure creates a doc-review issue with the tool name and failing assertion
78
+ - Candidates to start with: Jira (`/rest/api/3/myself`), GitHub (`/user`), HubSpot (`/crm/v3/objects/contacts?limit=1`)
76
79
 
77
80
  **Acceptance criteria:**
78
- - [ ] Each recipe has a validated request/response example
79
- - [ ] Pagination tested to >1 page of results
80
- - [ ] Incremental sync (updated_since / cursor) demonstrated for at least one search per tool
81
- - [ ] Dedup logic documented and tested (same input twice = no duplicate record)
82
-
83
- **Definition of done:** Each recipe can be executed end-to-end by an automation builder without consulting external docs.
81
+ - [ ] Weekly cron runs without manual intervention
82
+ - [ ] A PR that backdates a `Last validated:` date beyond 90 days fails the staleness check
83
+ - [ ] Smoke test failure creates an issue and does not block `main` CI (it's a separate workflow)
84
84
 
85
85
  ---
86
86
 
87
- ### Phase 3 — Event-Driven & Real-Time (Weeks 11–15)
87
+ ### Priority 3 — Distribution
88
88
 
89
- **Theme:** Replace polling with push. Webhooks and event triggers for real-time automation.
90
-
91
- **Deliverables:**
92
- - Monday.com: Webhook setup, column-change events, item-status triggers
93
- - Salesforce: Platform Events / Change Data Capture (CDC) basics; Outbound Messaging for simpler cases
94
- - Jira: Webhook registration (UI + API), issue-updated event structure, filtering by project/type
95
- - Dynamics 365: Webhooks via Plugin Registration Tool / Azure Service Bus; OData notifications
96
- - HubSpot: Webhook subscriptions, event types (contact.creation, deal.propertyChange), signature verification
97
- - ServiceNow: Outbound REST + Business Rules as webhook equivalent; Flow Designer basics
98
- - Zendesk: Webhook + Trigger setup, event payload structure, signature validation (X-Zendesk-Webhook-Signature)
99
- - Asana: Webhook registration, X-Hook-Secret handshake, event filtering
100
-
101
- **Cross-tool dependencies:**
102
- - Phase 2 update recipes required (webhooks trigger updates cross-system)
103
- - Shared webhook receiver pattern: signature verification, deduplication by event ID, idempotent handler
104
-
105
- **Acceptance criteria:**
106
- - [ ] Each tool: webhook registered, test event fired, handler receives and validates payload
107
- - [ ] Signature verification implemented and tested (reject tampered payload)
108
- - [ ] Idempotent event handler: same event delivered twice = processed once
109
- - [ ] Retry/dead-letter behavior documented per tool
110
-
111
- **Definition of done:** End-to-end event flow demonstrated: source system change → webhook delivery → target system update, with no polling.
89
+ | Channel | Status | Next action |
90
+ |---------|--------|-------------|
91
+ | GitHub (public) | Ready to flip | Make repo public |
92
+ | npm (`clawskills-mcp`) | ✅ Live — v0.2.3 | Maintain via `release.yml` |
93
+ | MCP registry listings | Not submitted | Submit to glama.ai, mcp.so, smithery.ai after public launch |
94
+ | Docs website | Planned | Mintlify — fastest path to SEO-friendly browsable docs |
95
+ | Lane A vs B | TBD | Revisit after first traction signals from public launch |
112
96
 
113
97
  ---
114
98
 
115
- ### Phase 4 — Bulk & Advanced Operations (Weeks 16–20)
116
-
117
- **Theme:** Scale up. Handle large datasets, bulk operations, and complex cross-tool orchestration.
99
+ ### Priority 4 — Complete Phase 4 & 5 gaps
118
100
 
119
- **Deliverables:**
120
- - Salesforce: Bulk API v2 (CSV ingest), SOQL aggregate queries, Composite API for multi-step
121
- - HubSpot: Batch create/update/read (up to 100 per batch), Import API for CSV
122
- - Jira: Bulk label/component updates, sprint management, custom field batch updates
123
- - ServiceNow: Import Sets with transform maps, batch table API calls
124
- - Zendesk: Bulk ticket update (update_many), Incremental Export API for full sync
125
- - Monday.com: Multiple mutations in single request, board duplication, subitems
126
- - Dynamics 365: $batch endpoint, FetchXML for complex aggregations
127
- - Asana: Parallel task creation patterns (respecting rate limits), Portfolio batch reads
101
+ These are lower priority than new skills but worth finishing:
128
102
 
129
- **Cross-tool dependencies:**
130
- - All Phase 2 & 3 recipes stable
131
- - Rate limit / backoff patterns from Phase 1 must handle burst scenarios
103
+ **Phase 4 gaps (Bulk operations):**
104
+ - Salesforce Bulk API v2: end-to-end CSV ingest tested at ≥500 rows with error-row reporting
105
+ - HubSpot batch create/update: tested at max batch size (100 records), partial-success handling
106
+ - Zendesk Incremental Export API: full-sync recipe with cursor continuation
132
107
 
133
- **Acceptance criteria:**
134
- - [ ] Bulk create tested with ≥500 records per supported tool
135
- - [ ] Bulk job status polling recipe documented (for async APIs: Salesforce Bulk, ServiceNow Import Set)
136
- - [ ] Memory/time complexity noted for large payloads
137
- - [ ] Error partial-success handling documented (some rows fail, some succeed)
108
+ **Phase 5 (Cross-tool orchestration) — first 3 recipes:**
109
+ - Zendesk Ticket → Jira Bug (bidirectional status sync)
110
+ - HubSpot Deal Won → Asana project creation (onboarding trigger)
111
+ - Salesforce Lead → HubSpot Contact sync (dedup on email)
138
112
 
139
- **Definition of done:** An integration can process a 10,000-row export from one system and upsert into another using bulk APIs, with error reporting per failed row.
113
+ Each recipe lives as a `## Cross-tool recipe` appendix section in the relevant primary skill doc (e.g., the Zendesk→Jira recipe goes in both `zendesk/skill.md` and `jira/skill.md`).
140
114
 
141
115
  ---
142
116
 
143
- ### Phase 5 — Cross-Tool Orchestration & AI-Ready Patterns (Weeks 21–28)
144
-
145
- **Theme:** Connect the systems. Build the integration recipes that span multiple tools, and prepare data flows for AI enrichment.
117
+ ## Prioritization framework
146
118
 
147
- **Deliverables:**
148
- - Cross-tool recipes (documented separately or as appendices in relevant skill.md files):
149
- - Salesforce Lead → HubSpot Contact sync
150
- - Zendesk Ticket → Jira Bug creation (bidirectional status)
151
- - ServiceNow Incident → Monday.com item (ops escalation board)
152
- - HubSpot Deal Won → Asana project creation (onboarding workflow)
153
- - Dynamics 365 Opportunity → Jira Epic (delivery handoff)
154
- - Enrichment patterns: append AI-generated summaries to ticket/task descriptions
155
- - Reporting aggregation: pull data from multiple tools into unified payload
156
-
157
- **Cross-tool dependencies:**
158
- - All Phase 1–4 skills stable
159
- - Canonical data model (shared field mapping table) agreed across tools
160
-
161
- **Acceptance criteria:**
162
- - [ ] Each cross-tool recipe: end-to-end tested in staging environments
163
- - [ ] Canonical IDs (external_id / reference fields) used to link records across systems
164
- - [ ] No data loss on failure (dead-letter queue or retry log)
165
- - [ ] Latency < 30s for real-time cross-tool sync
166
-
167
- **Definition of done:** A single external event (e.g., new support ticket) can automatically create linked records in 2+ systems with correct field mapping, documented in a runbook.
119
+ Each skill/recipe is scored on five dimensions (1–5 each):
168
120
 
169
- ---
121
+ | Dimension | Description |
122
+ |-----------|-------------|
123
+ | **Impact** | Business value if automated (revenue, hours saved, error reduction) |
124
+ | **Frequency** | How often the workflow runs daily/weekly |
125
+ | **Complexity** | Inverse score — simpler = higher priority |
126
+ | **Risk** | Inverse score — lower risk of data loss = higher priority |
127
+ | **Dependencies** | Whether other workflows depend on this one being stable |
170
128
 
171
- ## Deliverables by Tool
172
-
173
- | Tool | Phase | Deliverable | Notes | Dependencies |
174
- |------|-------|-------------|-------|--------------|
175
- | All tools | 1 | Auth + Core CRUD skill sections | Sandbox environments required | None |
176
- | Monday.com | 1 | Auth (token + OAuth), Board/Item CRUD | GraphQL API — different pattern from REST tools | None |
177
- | Monday.com | 2 | Intake workflow, status sync, approval tracking | Column value JSON shapes per type | Phase 1 |
178
- | Monday.com | 3 | Webhook setup + column-change events | Webhooks require HTTPS endpoint | Phase 1 |
179
- | Monday.com | 4 | Multi-mutation requests, subitems | Complexity points budget management | Phase 2 |
180
- | Salesforce | 1 | Connected App, OAuth JWT, REST CRUD | Sandbox org required | None |
181
- | Salesforce | 2 | Lead capture, Opportunity update, Task logging | Validation rules awareness | Phase 1 |
182
- | Salesforce | 3 | Platform Events / CDC / Outbound Messaging | Streaming API is separate product | Phase 2 |
183
- | Salesforce | 4 | Bulk API v2, Composite API, SOQL aggregates | Bulk API best for >1000 rows | Phase 2 |
184
- | Salesforce | 5 | Lead → HubSpot sync, Opp → Jira Epic | Canonical field mapping required | Phase 4 |
185
- | Jira | 1 | API Token auth, Issue CRUD | Cloud vs Server distinction | None |
186
- | Jira | 2 | JQL search, workflow transitions, triage | ADF for rich text comments | Phase 1 |
187
- | Jira | 3 | Webhook registration + issue-updated events | Webhook URL must be publicly reachable | Phase 2 |
188
- | Jira | 4 | Bulk label/component updates, sprint ops | No native bulk create — workarounds needed | Phase 2 |
189
- | Jira | 5 | Zendesk Ticket → Jira Bug (bidirectional) | Status mapping table required | Phase 4 |
190
- | Dynamics 365 | 1 | Azure AD app registration, Web API CRUD | Azure tenant required; security roles | None |
191
- | Dynamics 365 | 2 | Account/Contact upsert, Opportunity update, Activity log | Solution prefix awareness | Phase 1 |
192
- | Dynamics 365 | 3 | Plugin/webhook setup, OData change notifications | Plugin Registration Tool needed | Phase 2 |
193
- | Dynamics 365 | 4 | $batch endpoint, FetchXML complex queries | FetchXML for anything OData can't express | Phase 2 |
194
- | Dynamics 365 | 5 | Opportunity → Jira Epic handoff | Canonical ID linking | Phase 4 |
195
- | HubSpot | 1 | Private App token, OAuth, CRM Object CRUD | Scopes per object type | None |
196
- | HubSpot | 2 | Contact/Company sync, Deal updates, Engagement logging | Properties API for custom fields | Phase 1 |
197
- | HubSpot | 3 | Webhook subscriptions + event handling | App registration required for webhooks | Phase 2 |
198
- | HubSpot | 4 | Batch APIs, Import API for CSV | 100-record batch limit | Phase 2 |
199
- | HubSpot | 5 | Salesforce Lead → HubSpot Contact sync | Dedup on email field | Phase 4 |
200
- | ServiceNow | 1 | Basic auth + OAuth, Table API CRUD | Dev instance recommended | None |
201
- | ServiceNow | 2 | Incident create/update, work notes, assignment | State values are integers — verify per instance | Phase 1 |
202
- | ServiceNow | 3 | Outbound REST + Business Rule webhooks | Flow Designer alternative | Phase 2 |
203
- | ServiceNow | 4 | Import Sets + transform maps, batch GETs | Transform map must be configured in UI | Phase 2 |
204
- | ServiceNow | 5 | Incident → Monday.com escalation board | State-to-status mapping required | Phase 4 |
205
- | Zendesk | 1 | API Token, OAuth, Ticket CRUD | Subdomain required for all calls | None |
206
- | Zendesk | 2 | Ticket create/update, note vs reply, bulk update | Status machine strictly enforced | Phase 1 |
207
- | Zendesk | 3 | Webhook + Trigger setup, signature verification | New webhook API vs deprecated HTTP targets | Phase 2 |
208
- | Zendesk | 4 | Bulk update_many, Incremental Export API | Incremental API requires Enterprise or above | Phase 2 |
209
- | Zendesk | 5 | Zendesk Ticket → Jira Bug (bidirectional) | Requires external_id / tag mapping | Phase 4 |
210
- | Asana | 1 | PAT + OAuth, Task/Project CRUD | opt_fields required for all reads | None |
211
- | Asana | 2 | Task creation in section, status update, story/comment | Memberships array for project placement | Phase 1 |
212
- | Asana | 3 | Webhook registration + X-Hook-Secret handshake | Webhook events are coarse-grained | Phase 2 |
213
- | Asana | 4 | Parallel task creation, Portfolio reads | No native bulk — rate limit math required | Phase 2 |
214
- | Asana | 5 | HubSpot Deal Won → Asana project (onboarding) | Template project duplication | Phase 4 |
129
+ **Priority score = (Impact × 2) + (Frequency × 1.5) + Complexity + Risk + Dependencies**
215
130
 
216
131
  ---
217
132
 
218
- ## Quality Bar & Governance
133
+ ## Quality bar & governance
219
134
 
220
135
  ### Keeping docs accurate
221
136
 
222
- - **Version pinning:** Each skill.md must note the API version it was validated against (e.g., Salesforce API v62.0, Jira REST API v3, Dynamics 365 v9.2). Update the version header when re-validating.
223
- - **Quarterly review cycle:** Each skill.md has a `Last validated:` date in its header. Docs older than 90 days are flagged for re-review.
224
- - **Changelog section:** Major API changes (new auth flows, deprecated endpoints, rate limit changes) are logged in a `## Changelog` section at the bottom of each skill.md.
137
+ - **Version pinning:** Each skill.md notes the API version it was validated against. Update the version header when re-validating.
138
+ - **Quarterly review cycle:** Docs older than 90 days are flagged by the freshness pipeline for re-review.
139
+ - **Changelog notes:** Major API changes (new auth flows, deprecated endpoints, rate limit changes) noted inline with `> ⚠️ Changed [date]:` callouts.
225
140
 
226
141
  ### Validation approach
227
142
 
228
- - **Automated smoke tests:** For each tool, maintain a minimal test script (curl or SDK) that hits auth, a read, and a write. Run weekly in CI against sandbox environments. Failure triggers a doc-review issue.
229
- - **Breaking change monitoring:** Subscribe to each vendor's developer changelog / API release notes. Sources:
143
+ - **CI test suite:** Real-skills tests in `mcp-server/src/index.test.ts` verify all skills load, have required sections, and are ≥5 KB.
144
+ - **Freshness pipeline:** Weekly cron checks `Last validated:` dates (see Priority 2 above).
145
+ - **Live smoke tests:** Optional phase B — weekly auth + read tests against sandboxes.
146
+ - **Breaking change monitoring:** Subscribe to each vendor's developer changelog:
230
147
  - Monday: https://developer.monday.com/changelog
231
148
  - Salesforce: https://help.salesforce.com/s/articleView?id=release-notes.salesforce_release_notes.htm
232
149
  - Jira: https://developer.atlassian.com/cloud/jira/platform/changelog/
233
150
  - Dynamics 365: https://learn.microsoft.com/en-us/dynamics365/release-plans/
234
151
  - HubSpot: https://developers.hubspot.com/changelog
235
- - ServiceNow: https://developer.servicenow.com/dev.do (release notes per version)
152
+ - ServiceNow: https://developer.servicenow.com/dev.do
236
153
  - Zendesk: https://developer.zendesk.com/api-reference/ticketing/introduction/#api-changelog
237
154
  - Asana: https://developers.asana.com/docs/changelog
155
+ - GitHub: https://github.blog/changelog/
156
+ - Figma: https://www.figma.com/developers/api#changelog
157
+ - Slack: https://api.slack.com/changelog
158
+ - Stripe: https://stripe.com/docs/changelog
159
+ - Notion: https://developers.notion.com/page/changelog
160
+ - Linear: https://linear.app/changelog
238
161
 
239
162
  ### Handling deprecations
240
163
 
@@ -245,29 +168,31 @@ Phases are ordered by descending average priority score within a theme.
245
168
 
246
169
  ### Contribution process
247
170
 
248
- - PRs to skill.md files require: (a) reference to official doc, (b) tested curl/pseudocode example, (c) updated `Last validated:` date.
249
- - All changes reviewed by at least one person who has tested against the live API.
171
+ - PRs to `skill.md` files require: (a) reference to official doc, (b) tested curl/pseudocode example, (c) updated `Last validated:` date.
172
+ - Branch convention: `skill/<toolname>` → PR → merge to main.
173
+ - CI runs `npm test` on every PR — validates skill loads and has all required sections.
174
+ - Releases: merge to main, then GitHub Actions → **Release** → Run workflow → pick `patch / minor / major`.
250
175
 
251
176
  ---
252
177
 
253
- ## Backlog (Nice-to-Have)
254
-
255
- These items are out of scope for Phases 1–5 but worth tracking for future investment:
178
+ ## Backlog (tracked, not yet scheduled)
256
179
 
257
180
  | Item | Tool(s) | Value | Complexity |
258
181
  |------|---------|-------|------------|
259
- | AI-powered ticket summarization (append GPT summary to description) | Zendesk, Jira, ServiceNow | High | Medium |
182
+ | AI-powered ticket summarization (append LLM summary to description) | Zendesk, Jira, ServiceNow | High | Medium |
260
183
  | Automated lead scoring sync | Salesforce, HubSpot | High | Medium |
261
184
  | Revenue analytics aggregation (pull pipeline across CRMs) | Salesforce, HubSpot, Dynamics 365 | High | High |
262
- | Admin automation: user provisioning / deprovisioning | All tools | Medium | Medium |
185
+ | Token rotation automation (refresh before expiry) | All OAuth tools | High | Low |
186
+ | Twilio skill (SMS/voice notifications) | Twilio | High | Medium |
187
+ | Intercom skill (in-app messaging, user segments) | Intercom | Medium | Medium |
188
+ | Okta/Auth0 skill (identity + SSO) | Okta | Medium | Medium |
189
+ | PagerDuty skill (on-call, incident escalation) | PagerDuty | Medium | Low |
190
+ | Docs website (Mintlify/Docusaurus) | — | High | Medium |
191
+ | VS Code extension (inject skill doc into editor context) | — | Medium | High |
192
+ | REST API / hosted endpoint for skill doc retrieval | — | Medium | High |
193
+ | Admin automation: user provisioning/deprovisioning | All tools | Medium | Medium |
263
194
  | Compliance export (GDPR data subject requests) | Zendesk, Salesforce, HubSpot | Medium | High |
264
- | Monday → Asana project migration utility | Monday, Asana | Low | Medium |
265
- | Jira custom field schema introspection | Jira | Medium | Low |
266
- | Dynamics 365 Power Automate connector alternatives | Dynamics 365 | Medium | Low |
267
- | ServiceNow CMDB auto-discovery integration | ServiceNow | High | High |
268
195
  | Zendesk → Salesforce Case sync (bidirectional) | Zendesk, Salesforce | High | High |
269
- | HubSpot Sequences → Outreach/Salesloft parity | HubSpot | Medium | Medium |
270
- | Monday dashboards → BI tool (Looker/Tableau) export | Monday | Medium | Medium |
196
+ | ServiceNow CMDB auto-discovery integration | ServiceNow | High | High |
271
197
  | Multi-workspace / multi-org management recipes | All tools | Medium | High |
272
- | Token rotation automation (refresh before expiry) | All OAuth tools | High | Low |
273
198
  | Audit log export to SIEM | Salesforce, Zendesk, ServiceNow | Medium | Medium |
@@ -0,0 +1,823 @@
1
+ # Stripe Skill
2
+
3
+ > **Last validated:** 2026-03-01 | **API version:** `2026-02-25.clover` (latest stable)
4
+ > **REST base URL:** `https://api.stripe.com/v1/`
5
+ > **Assumed product:** Stripe Payments + Billing. Stripe Connect (multi-account platform) is covered in the Auth and Recipes sections.
6
+
7
+ ---
8
+
9
+ ## What this skill enables
10
+
11
+ - Collect one-time payments and save cards for future use without handling raw card data (PCI-compliant via Stripe.js / Payment Element).
12
+ - Create and manage recurring subscriptions with automatic billing, dunning, and trial periods.
13
+ - Issue full or partial refunds and query payment history programmatically.
14
+ - Build hosted checkout flows (Checkout Sessions) that Stripe renders — no front-end payment UI required.
15
+ - Handle post-payment events reliably via webhooks: fulfil orders, provision access, update CRM records.
16
+ - Operate as a platform (Stripe Connect): onboard connected accounts, route payments, split revenue.
17
+ - Test the full payment lifecycle with Stripe's sandbox — no real money, no bank involvement.
18
+
19
+ ---
20
+
21
+ ## Best-fit use cases
22
+
23
+ | Use case | Why it matters | Primary objects | Typical trigger | Success criteria |
24
+ |----------|---------------|-----------------|-----------------|-----------------|
25
+ | One-time purchase | Charge a customer once for a product or service | PaymentIntent, PaymentMethod, Customer | User submits payment form | `payment_intent.succeeded` webhook received; order fulfilled |
26
+ | Save card for future billing | Charge a returning customer without re-entering card | PaymentMethod, Customer | User checks "save card" | PaymentMethod attached to Customer; future charges succeed |
27
+ | Recurring subscription | Monthly/annual SaaS or membership billing | Subscription, Price, Invoice, Customer | User selects plan | Subscription `active`; first invoice `paid` |
28
+ | Hosted checkout page | Delegate payment UI to Stripe | Checkout Session | User clicks "Buy now" | `checkout.session.completed` webhook; `payment_status: paid` |
29
+ | Issue a refund | Reverse a charge (full or partial) | Refund, Charge | Support request or automated policy | Refund `succeeded`; `charge.refunded` webhook received |
30
+ | Failed payment recovery | Retry a failed subscription invoice | Invoice, PaymentIntent | `invoice.payment_failed` webhook | Payment retried; subscription back to `active` |
31
+ | Multi-vendor marketplace | Route payments between platform and sellers | Connect Account, Transfer, Charge | Order placed on platform | Connected account receives funds; platform fee collected |
32
+ | Payout reporting | Pull all payouts and match to bank statement | Payout, BalanceTransaction | Finance reconciliation run | Every payout has matching BalanceTransactions totalling net amount |
33
+ | Metered billing | Charge based on usage at end of billing period | SubscriptionItem, UsageRecord, Invoice | Usage event from product | Invoice includes correct usage line items |
34
+ | Payment link (no-code) | Generate a shareable URL for one-time or recurring payment | PaymentLink | Sales or support request | Customer completes payment via link; webhook confirms |
35
+
36
+ ---
37
+
38
+ ## Key concepts & data model
39
+
40
+ ### Core objects
41
+
42
+ | Object | Description | ID prefix |
43
+ |--------|-------------|-----------|
44
+ | **Customer** | A person or business entity; stores payment methods and billing info | `cus_` |
45
+ | **PaymentIntent** | The authoritative record of a payment attempt; tracks state through to success/failure | `pi_` |
46
+ | **PaymentMethod** | A reusable token representing a card, bank account, or wallet | `pm_` |
47
+ | **Charge** | A legacy object created when a PaymentIntent succeeds; most APIs now return the PaymentIntent directly | `ch_` |
48
+ | **Invoice** | A bill sent to a Customer; created automatically for subscriptions | `in_` |
49
+ | **Subscription** | A recurring billing agreement linking a Customer to one or more Prices | `sub_` |
50
+ | **Price** | Defines the billing amount, currency, and interval for a Product | `price_` |
51
+ | **Product** | A good or service offered; Prices are attached to Products | `prod_` |
52
+ | **Refund** | A reversal of a Charge, full or partial | `re_` |
53
+ | **Checkout Session** | A hosted payment page managed by Stripe | `cs_` |
54
+ | **PaymentLink** | A shareable URL backed by a Checkout Session template | `plink_` |
55
+ | **Transfer** | Funds moved from platform balance to a connected account | `tr_` |
56
+ | **Payout** | Funds sent from Stripe balance to a bank account | `po_` |
57
+ | **BalanceTransaction** | Every money movement in Stripe (fee, charge, refund, payout) | `txn_` |
58
+ | **Event** | A webhook payload describing a state change | `evt_` |
59
+ | **Connected Account** | An account on your platform (Stripe Connect) | `acct_` |
60
+
61
+ ### PaymentIntent lifecycle
62
+
63
+ ```
64
+ requires_payment_method → requires_confirmation → requires_action → processing → succeeded
65
+ ↘ canceled
66
+ ```
67
+
68
+ | Status | Meaning |
69
+ |--------|---------|
70
+ | `requires_payment_method` | No valid payment method attached yet |
71
+ | `requires_confirmation` | Payment method attached; awaiting explicit confirm call |
72
+ | `requires_action` | 3D Secure or redirect authentication needed from the customer |
73
+ | `processing` | Bank processing in progress (instant cards transition through this quickly) |
74
+ | `succeeded` | Payment captured; funds reserved or settled |
75
+ | `canceled` | Cancelled; a new PaymentIntent must be created |
76
+
77
+ ### Subscription lifecycle
78
+
79
+ | Status | Meaning |
80
+ |--------|---------|
81
+ | `trialing` | In free trial; no payment yet |
82
+ | `active` | In good standing; latest invoice paid |
83
+ | `incomplete` | First payment not yet made; customer has 23 hours |
84
+ | `incomplete_expired` | Initial 23-hour window expired without payment |
85
+ | `past_due` | Latest renewal invoice failed; automatic retries in progress |
86
+ | `unpaid` | Retries exhausted; subscription remains but no more attempts |
87
+ | `paused` | Trial ended without a default payment method |
88
+ | `canceled` | Terminal; cannot be reactivated |
89
+
90
+ ### Amounts and currencies
91
+
92
+ All monetary amounts are in the **smallest currency unit** — cents for USD, pence for GBP, yen for JPY (which has no subunit, so `100` = ¥100). Always store and pass amounts as integers.
93
+
94
+ ### Expandable fields
95
+
96
+ Any field that returns an ID (e.g., `"customer": "cus_xxx"`) can be expanded to the full object by passing `expand[]=customer` in the request. Nest with dots: `expand[]=latest_invoice.payment_intent`.
97
+
98
+ ### Metadata
99
+
100
+ Every Stripe object has a `metadata` dictionary for storing arbitrary key/value pairs (e.g., your internal IDs). Limits: 50 keys per object, key ≤ 40 chars, value ≤ 500 chars.
101
+
102
+ ---
103
+
104
+ ## Authentication & permissions
105
+
106
+ ### API key types
107
+
108
+ | Key type | Prefix | Use | Never in |
109
+ |----------|--------|-----|----------|
110
+ | Secret (live) | `sk_live_` | Server-side; full API access | Client-side code, logs, version control |
111
+ | Secret (sandbox) | `sk_test_` | Server-side; test mode only | Production environments |
112
+ | Publishable (live) | `pk_live_` | Browser/mobile; only creates tokens | Server-side requests |
113
+ | Publishable (sandbox) | `pk_test_` | Browser/mobile; test mode | Production environments |
114
+ | Restricted | `rk_live_` / `rk_test_` | Server-side; limited to specific resources | When full access is needed |
115
+
116
+ Create restricted keys in **Dashboard → Developers → API keys → Create restricted key**. Assign **None / Read / Write** per resource (Customers, PaymentIntents, Subscriptions, etc.).
117
+
118
+ ### Authentication header
119
+
120
+ Stripe uses HTTP Basic auth with the secret key as the username and an empty password. All major HTTP clients also accept `Authorization: Bearer sk_...`:
121
+
122
+ ```bash
123
+ # Basic auth (canonical Stripe style)
124
+ curl https://api.stripe.com/v1/customers \
125
+ -u "sk_test_51Abc123...:
126
+
127
+ # Bearer token (equivalent)
128
+ curl https://api.stripe.com/v1/customers \
129
+ -H "Authorization: Bearer sk_test_51Abc123..."
130
+ ```
131
+
132
+ ### API version pinning
133
+
134
+ Always pin the API version explicitly to avoid unexpected behaviour when Stripe releases a new default:
135
+
136
+ ```bash
137
+ curl https://api.stripe.com/v1/payment_intents \
138
+ -u "sk_test_...:" \
139
+ -H "Stripe-Version: 2026-02-25.clover" \
140
+ -d amount=2000 \
141
+ -d currency=usd
142
+ ```
143
+
144
+ Set a default version for your account in **Dashboard → Developers → API version**. The SDK reads your account default unless you override per-request.
145
+
146
+ ### Stripe Connect — acting on behalf of a connected account
147
+
148
+ Pass `Stripe-Account: acct_xxx` to perform an API call in the context of a connected account using your platform key:
149
+
150
+ ```bash
151
+ curl https://api.stripe.com/v1/customers \
152
+ -u "sk_live_platform...:" \
153
+ -H "Stripe-Account: acct_1ABCxyzConnected"
154
+ ```
155
+
156
+ ### Idempotency keys
157
+
158
+ Use `Idempotency-Key` on every `POST` request to safely retry without double-charging:
159
+
160
+ ```bash
161
+ curl https://api.stripe.com/v1/payment_intents \
162
+ -u "sk_test_...:" \
163
+ -H "Idempotency-Key: $(uuidgen)" \
164
+ -d amount=2000 \
165
+ -d currency=usd
166
+ ```
167
+
168
+ - Keys are strings up to 255 characters; UUIDs v4 are recommended.
169
+ - Results are cached for **24 hours**. Reusing a key after expiry generates a new request.
170
+ - Reusing a key with **different parameters** returns a `409 Conflict` `idempotency_error`.
171
+ - Only use on `POST` — `GET` and `DELETE` are inherently idempotent.
172
+
173
+ ---
174
+
175
+ ## Common workflows (recipes)
176
+
177
+ ### 1. Create a one-time payment (PaymentIntent flow)
178
+
179
+ **Server-side — create PaymentIntent:**
180
+
181
+ ```bash
182
+ curl https://api.stripe.com/v1/payment_intents \
183
+ -u "sk_test_...:" \
184
+ -H "Idempotency-Key: order-42-$(date +%s)" \
185
+ -d amount=4999 \
186
+ -d currency=usd \
187
+ -d "automatic_payment_methods[enabled]=true" \
188
+ -d "metadata[order_id]=order_42"
189
+ ```
190
+
191
+ **Response (key fields):**
192
+
193
+ ```json
194
+ {
195
+ "id": "pi_3OxAbc2eZvKYlo2C1hb8mT9k",
196
+ "object": "payment_intent",
197
+ "amount": 4999,
198
+ "currency": "usd",
199
+ "status": "requires_payment_method",
200
+ "client_secret": "pi_3OxAbc...hb8mT9k_secret_Xyz",
201
+ "metadata": { "order_id": "order_42" }
202
+ }
203
+ ```
204
+
205
+ **Client-side — confirm with Stripe.js:**
206
+
207
+ ```javascript
208
+ const { error } = await stripe.confirmPayment({
209
+ elements, // Stripe Elements instance
210
+ clientSecret: pi.client_secret,
211
+ confirmParams: {
212
+ return_url: "https://example.com/order/complete"
213
+ }
214
+ });
215
+ ```
216
+
217
+ **Fulfil on webhook `payment_intent.succeeded`** — see Recipes #7.
218
+
219
+ ---
220
+
221
+ ### 2. Save a card for future use
222
+
223
+ ```bash
224
+ # Step 1 — create or retrieve the Customer
225
+ curl https://api.stripe.com/v1/customers \
226
+ -u "sk_test_...:" \
227
+ -d email="alice@example.com" \
228
+ -d "metadata[user_id]=usr_99"
229
+
230
+ # Step 2 — create a SetupIntent (confirm later via Stripe.js)
231
+ curl https://api.stripe.com/v1/setup_intents \
232
+ -u "sk_test_...:" \
233
+ -d customer=cus_PAbcXyz \
234
+ -d "automatic_payment_methods[enabled]=true"
235
+ ```
236
+
237
+ After the client confirms the SetupIntent, the PaymentMethod is attached to the Customer. To charge it later:
238
+
239
+ ```bash
240
+ curl https://api.stripe.com/v1/payment_intents \
241
+ -u "sk_test_...:" \
242
+ -d amount=2000 \
243
+ -d currency=usd \
244
+ -d customer=cus_PAbcXyz \
245
+ -d payment_method=pm_1ABCdefGhIjKlMnO \
246
+ -d confirm=true \
247
+ -d off_session=true
248
+ ```
249
+
250
+ `off_session=true` signals that the customer is not present — Stripe will attempt to complete without 3DS if allowed by the card issuer.
251
+
252
+ ---
253
+
254
+ ### 3. Create a subscription
255
+
256
+ ```bash
257
+ # Step 1 — ensure Customer has a default PaymentMethod
258
+ curl https://api.stripe.com/v1/customers/cus_PAbcXyz \
259
+ -u "sk_test_...:" \
260
+ -X POST \
261
+ -d invoice_settings[default_payment_method]=pm_1ABCdefGhIjKlMnO
262
+
263
+ # Step 2 — create the Subscription
264
+ curl https://api.stripe.com/v1/subscriptions \
265
+ -u "sk_test_...:" \
266
+ -d customer=cus_PAbcXyz \
267
+ -d "items[0][price]=price_1ABCdefGhIjKlMnO" \
268
+ -d payment_behavior=default_incomplete \
269
+ -d "expand[]=latest_invoice.payment_intent"
270
+ ```
271
+
272
+ `payment_behavior=default_incomplete` starts the subscription in `incomplete` status — confirm payment client-side using the `latest_invoice.payment_intent.client_secret` before it expires (23 hours).
273
+
274
+ **Response (key fields):**
275
+
276
+ ```json
277
+ {
278
+ "id": "sub_1ABCdef...",
279
+ "status": "incomplete",
280
+ "current_period_end": 1740000000,
281
+ "latest_invoice": {
282
+ "id": "in_1ABCdef...",
283
+ "payment_intent": {
284
+ "id": "pi_1ABCdef...",
285
+ "client_secret": "pi_...secret_..."
286
+ }
287
+ }
288
+ }
289
+ ```
290
+
291
+ ---
292
+
293
+ ### 4. Create a hosted Checkout Session
294
+
295
+ No front-end payment form — Stripe hosts and renders it:
296
+
297
+ ```bash
298
+ curl https://api.stripe.com/v1/checkout/sessions \
299
+ -u "sk_test_...:" \
300
+ -d mode=payment \
301
+ -d "line_items[0][price]=price_1ABCdefGhIjKlMnO" \
302
+ -d "line_items[0][quantity]=1" \
303
+ -d success_url="https://example.com/success?session_id={CHECKOUT_SESSION_ID}" \
304
+ -d cancel_url="https://example.com/cancel" \
305
+ -d customer_email="alice@example.com"
306
+ ```
307
+
308
+ Redirect the browser to `session.url`. Stripe handles the payment UI and redirects to `success_url` on completion. Confirm fulfilment via `checkout.session.completed` webhook — do not trust the redirect URL alone.
309
+
310
+ For a subscription Checkout Session, change `mode=subscription` and pass a recurring Price.
311
+
312
+ ---
313
+
314
+ ### 5. Issue a full refund
315
+
316
+ ```bash
317
+ curl https://api.stripe.com/v1/refunds \
318
+ -u "sk_test_...:" \
319
+ -H "Idempotency-Key: refund-ch_1ABC-$(date +%s)" \
320
+ -d charge=ch_1ABCdefGhIjKlMnO
321
+ ```
322
+
323
+ **Partial refund** — add `amount` in cents:
324
+
325
+ ```bash
326
+ curl https://api.stripe.com/v1/refunds \
327
+ -u "sk_test_...:" \
328
+ -d charge=ch_1ABCdefGhIjKlMnO \
329
+ -d amount=500
330
+ ```
331
+
332
+ **Response (key fields):**
333
+
334
+ ```json
335
+ {
336
+ "id": "re_1ABCdef...",
337
+ "object": "refund",
338
+ "amount": 500,
339
+ "status": "succeeded",
340
+ "charge": "ch_1ABCdef..."
341
+ }
342
+ ```
343
+
344
+ Watch for `charge.refunded` webhook for async confirmation.
345
+
346
+ ---
347
+
348
+ ### 6. Handle a failed subscription payment
349
+
350
+ ```python
351
+ import stripe
352
+
353
+ stripe.api_key = "sk_live_..."
354
+
355
+ # Called from your webhook handler when invoice.payment_failed fires
356
+ def handle_payment_failed(invoice_id: str) -> None:
357
+ invoice = stripe.Invoice.retrieve(invoice_id, expand=["subscription"])
358
+ sub = invoice.subscription
359
+
360
+ if sub.status == "past_due":
361
+ # Notify the customer to update their payment method
362
+ send_dunning_email(sub.customer, invoice.hosted_invoice_url)
363
+
364
+ # Stripe will automatically retry according to your retry schedule
365
+ # (Dashboard → Settings → Billing → Retry schedule)
366
+ # To trigger an immediate retry:
367
+ # stripe.Invoice.pay(invoice_id)
368
+ ```
369
+
370
+ When the customer updates their payment method:
371
+
372
+ ```bash
373
+ # Attach the new PaymentMethod to the Customer
374
+ curl https://api.stripe.com/v1/payment_methods/pm_NEW.../attach \
375
+ -u "sk_live_...:" \
376
+ -d customer=cus_PAbcXyz
377
+
378
+ # Attempt to pay the open invoice immediately
379
+ curl https://api.stripe.com/v1/invoices/in_OPEN.../pay \
380
+ -u "sk_live_...:" \
381
+ -X POST
382
+ ```
383
+
384
+ ---
385
+
386
+ ### 7. Webhook receiver — verify and dispatch
387
+
388
+ ```python
389
+ import stripe
390
+ from flask import Flask, request, jsonify
391
+
392
+ app = Flask(__name__)
393
+ stripe.api_key = "sk_live_..."
394
+ WEBHOOK_SECRET = "whsec_..."
395
+
396
+ @app.post("/stripe/webhook")
397
+ def webhook():
398
+ sig = request.headers.get("Stripe-Signature")
399
+ try:
400
+ event = stripe.Webhook.construct_event(
401
+ payload=request.data, # raw bytes — do NOT parse JSON first
402
+ sig_header=sig,
403
+ secret=WEBHOOK_SECRET,
404
+ )
405
+ except stripe.error.SignatureVerificationError:
406
+ return jsonify(error="invalid signature"), 400
407
+
408
+ match event["type"]:
409
+ case "payment_intent.succeeded":
410
+ handle_payment_succeeded(event["data"]["object"])
411
+ case "invoice.paid":
412
+ handle_invoice_paid(event["data"]["object"])
413
+ case "customer.subscription.deleted":
414
+ handle_subscription_cancelled(event["data"]["object"])
415
+ case "checkout.session.completed":
416
+ handle_checkout_complete(event["data"]["object"])
417
+
418
+ # Must return 2xx within ~30 seconds or Stripe retries
419
+ return jsonify(ok=True), 200
420
+ ```
421
+
422
+ **Critical rules:**
423
+ - Always verify the `Stripe-Signature` header before processing.
424
+ - Read raw request body — any JSON parsing before `construct_event` may corrupt the signature.
425
+ - Return `200` before triggering long-running work (enqueue a job instead).
426
+ - Make handlers **idempotent** — Stripe may deliver the same event more than once. Use `event.id` to deduplicate.
427
+
428
+ ---
429
+
430
+ ### 8. Stripe Connect — charge on a connected account (destination charge)
431
+
432
+ ```bash
433
+ # Create a PaymentIntent where funds go to the connected account
434
+ # Platform retains application_fee_amount
435
+ curl https://api.stripe.com/v1/payment_intents \
436
+ -u "sk_live_platform...:" \
437
+ -d amount=5000 \
438
+ -d currency=usd \
439
+ -d "automatic_payment_methods[enabled]=true" \
440
+ -d transfer_data[destination]=acct_1ConnectedAcct \
441
+ -d application_fee_amount=500
442
+ ```
443
+
444
+ **Direct charge** (create on the connected account itself):
445
+
446
+ ```bash
447
+ curl https://api.stripe.com/v1/payment_intents \
448
+ -u "sk_live_platform...:" \
449
+ -H "Stripe-Account: acct_1ConnectedAcct" \
450
+ -d amount=5000 \
451
+ -d currency=usd \
452
+ -d "automatic_payment_methods[enabled]=true"
453
+ ```
454
+
455
+ **Create a connected account (Express onboarding):**
456
+
457
+ ```bash
458
+ # Step 1 — create the account
459
+ curl https://api.stripe.com/v1/accounts \
460
+ -u "sk_live_platform...:" \
461
+ -d type=express \
462
+ -d country=US \
463
+ -d email="seller@example.com"
464
+ # → { "id": "acct_1ABCdef...", ... }
465
+
466
+ # Step 2 — generate onboarding link
467
+ curl https://api.stripe.com/v1/account_links \
468
+ -u "sk_live_platform...:" \
469
+ -d account=acct_1ABCdef \
470
+ -d "refresh_url=https://example.com/reauth" \
471
+ -d "return_url=https://example.com/onboarded" \
472
+ -d type=account_onboarding
473
+ # → { "url": "https://connect.stripe.com/setup/e/..." }
474
+ ```
475
+
476
+ ---
477
+
478
+ ### 9. Retrieve customer payment history (list charges)
479
+
480
+ ```python
481
+ import stripe
482
+
483
+ stripe.api_key = "sk_live_..."
484
+
485
+ def get_customer_charges(customer_id: str, limit: int = 100) -> list:
486
+ charges = []
487
+ params = {
488
+ "customer": customer_id,
489
+ "limit": 100,
490
+ }
491
+ while True:
492
+ page = stripe.Charge.list(**params)
493
+ charges.extend(page.data)
494
+ if not page.has_more:
495
+ break
496
+ params["starting_after"] = page.data[-1].id
497
+ return charges
498
+ ```
499
+
500
+ ---
501
+
502
+ ### 10. Cancel a subscription (at period end)
503
+
504
+ ```bash
505
+ # Cancel at the end of the current billing period (no proration)
506
+ curl https://api.stripe.com/v1/subscriptions/sub_1ABCdef... \
507
+ -u "sk_live_...:" \
508
+ -X POST \
509
+ -d cancel_at_period_end=true
510
+
511
+ # Cancel immediately
512
+ curl https://api.stripe.com/v1/subscriptions/sub_1ABCdef... \
513
+ -u "sk_live_...:" \
514
+ -X DELETE
515
+ ```
516
+
517
+ Listen for `customer.subscription.deleted` webhook to revoke access.
518
+
519
+ ---
520
+
521
+ ## Query patterns & filtering
522
+
523
+ ### Cursor-based pagination
524
+
525
+ All list endpoints return a consistent envelope:
526
+
527
+ ```json
528
+ {
529
+ "object": "list",
530
+ "data": [ ... ],
531
+ "has_more": true,
532
+ "url": "/v1/charges"
533
+ }
534
+ ```
535
+
536
+ Parameters:
537
+
538
+ | Parameter | Type | Default | Max | Description |
539
+ |-----------|------|---------|-----|-------------|
540
+ | `limit` | integer | 10 | 100 | Items per page |
541
+ | `starting_after` | string | — | — | ID of last item on previous page (forward pagination) |
542
+ | `ending_before` | string | — | — | ID of first item on next page (backward pagination) |
543
+
544
+ `starting_after` and `ending_before` are mutually exclusive.
545
+
546
+ ### Date range filters
547
+
548
+ All list endpoints support `created[gte]` / `created[lte]` (Unix timestamps):
549
+
550
+ ```bash
551
+ # All charges from the last 7 days
552
+ curl "https://api.stripe.com/v1/charges?limit=100&created[gte]=$(date -v-7d +%s)" \
553
+ -u "sk_live_...:"
554
+ ```
555
+
556
+ Other common filter parameters:
557
+
558
+ | Endpoint | Filter | Example |
559
+ |----------|--------|---------|
560
+ | `/v1/charges` | `customer`, `payment_intent`, `created[gte/lte]` | `customer=cus_xxx` |
561
+ | `/v1/subscriptions` | `customer`, `status`, `price`, `current_period_end[gte]` | `status=past_due` |
562
+ | `/v1/invoices` | `customer`, `subscription`, `status`, `due_date[gte]` | `status=open` |
563
+ | `/v1/payment_intents` | `customer`, `created[gte/lte]` | `customer=cus_xxx` |
564
+ | `/v1/refunds` | `charge`, `payment_intent`, `created[gte/lte]` | `charge=ch_xxx` |
565
+
566
+ ### Auto-pagination (Python SDK)
567
+
568
+ ```python
569
+ # Iterates all pages automatically
570
+ for charge in stripe.Charge.list(customer="cus_xxx", limit=100).auto_paging_iter():
571
+ process(charge)
572
+ ```
573
+
574
+ ### Search API
575
+
576
+ Stripe has a structured Search API for Customers, PaymentIntents, Charges, Subscriptions, and Invoices:
577
+
578
+ ```bash
579
+ curl "https://api.stripe.com/v1/customers/search?query=email:'alice@example.com'" \
580
+ -u "sk_live_...:"
581
+ ```
582
+
583
+ Search is rate-limited to **20 read operations per second** (stricter than list endpoints).
584
+
585
+ ---
586
+
587
+ ## Reliability: rate limits, retries, idempotency
588
+
589
+ ### Rate limits
590
+
591
+ | Mode | Global limit | Notes |
592
+ |------|-------------|-------|
593
+ | Live | **100 req/sec** | Per account; some endpoints are stricter (see below) |
594
+ | Sandbox | **25 req/sec** | Intentionally lower to surface rate-limit bugs early |
595
+
596
+ **Endpoint-specific limits (stricter):**
597
+
598
+ | Endpoint | Limit |
599
+ |----------|-------|
600
+ | Search API | 20 read ops/sec |
601
+ | Files API | 20 reads/sec, 20 writes/sec |
602
+ | Meter Events (`/v1/billing/meter_events`) | 1,000/sec live |
603
+ | PaymentIntent updates | 1,000 updates/PaymentIntent/hr |
604
+ | Create Payout | 15/sec, 30 concurrent |
605
+ | Connect — create account | 5/sec sandbox, 30/sec live |
606
+
607
+ ### Rate limit response
608
+
609
+ HTTP `429` with header:
610
+
611
+ ```
612
+ Stripe-Rate-Limited-Reason: global-rate
613
+ ```
614
+
615
+ Possible values: `global-concurrency`, `global-rate`, `endpoint-concurrency`, `endpoint-rate`, `resource-specific`.
616
+
617
+ ### Retry with exponential backoff + jitter
618
+
619
+ ```python
620
+ import time, random, stripe
621
+
622
+ def stripe_call_with_retry(fn, *args, max_retries=5, **kwargs):
623
+ for attempt in range(max_retries):
624
+ try:
625
+ return fn(*args, **kwargs)
626
+ except stripe.error.RateLimitError:
627
+ if attempt == max_retries - 1:
628
+ raise
629
+ wait = (2 ** attempt) + random.uniform(0, 1)
630
+ time.sleep(wait)
631
+ except stripe.error.APIConnectionError:
632
+ if attempt == max_retries - 1:
633
+ raise
634
+ time.sleep(2 ** attempt)
635
+ ```
636
+
637
+ **Python SDK auto-retry:** `stripe.max_network_retries = 3` enables built-in retry for network errors and `429`s.
638
+
639
+ ### Idempotency
640
+
641
+ - Include `Idempotency-Key` on every `POST` (charge, refund, subscription creation).
642
+ - Use a stable key derived from your internal operation ID, e.g., `f"order-{order_id}-payment"`.
643
+ - Results cached **24 hours**; same key = same response (including `5xx` errors).
644
+ - Different params + same key = `409 idempotency_error`.
645
+
646
+ ```python
647
+ stripe.PaymentIntent.create(
648
+ amount=4999,
649
+ currency="usd",
650
+ idempotency_key=f"order-{order_id}-payment-intent",
651
+ )
652
+ ```
653
+
654
+ ---
655
+
656
+ ## Error handling & troubleshooting
657
+
658
+ ### Error object
659
+
660
+ ```json
661
+ {
662
+ "error": {
663
+ "type": "card_error",
664
+ "code": "card_declined",
665
+ "decline_code": "insufficient_funds",
666
+ "message": "Your card has insufficient funds.",
667
+ "param": null,
668
+ "charge": "ch_1ABCdef...",
669
+ "doc_url": "https://stripe.com/docs/error-codes/card-declined"
670
+ }
671
+ }
672
+ ```
673
+
674
+ ### HTTP status → action
675
+
676
+ | Status | Type | Action |
677
+ |--------|------|--------|
678
+ | `400` | `invalid_request_error` | Fix the request — missing or malformed parameter. Check `error.param`. |
679
+ | `401` | `api_error` | Invalid API key. Verify `sk_live_`/`sk_test_` prefix matches environment. |
680
+ | `402` | `card_error` | Card declined or transaction failed. Show `error.message` to the user. |
681
+ | `403` | `api_error` | Insufficient permissions — use a secret key or check restricted key scopes. |
682
+ | `404` | `invalid_request_error` | Object not found. Verify the ID prefix matches the endpoint. |
683
+ | `409` | `idempotency_error` | Same idempotency key reused with different params. Generate a new key. |
684
+ | `429` | — | Rate limited. Retry with exponential backoff; see `Stripe-Rate-Limited-Reason`. |
685
+ | `5xx` | `api_error` | Stripe infrastructure issue. Retry with backoff; check https://status.stripe.com. |
686
+
687
+ ### Error type → handler
688
+
689
+ | `error.type` | Meaning | What to do |
690
+ |--------------|---------|------------|
691
+ | `card_error` | Card issue (decline, insufficient funds, expired) | Show `error.message` to the end user; do not retry without user action |
692
+ | `invalid_request_error` | Bad API request | Fix the code; do not retry unchanged |
693
+ | `api_error` | Stripe-side problem | Retry with exponential backoff |
694
+ | `idempotency_error` | Key reused with different params | Generate a new idempotency key |
695
+
696
+ ### Common `decline_code` values
697
+
698
+ | `decline_code` | Meaning | User-facing message |
699
+ |----------------|---------|---------------------|
700
+ | `card_declined` | Generic decline from issuer | "Your card was declined. Please try a different card." |
701
+ | `insufficient_funds` | Not enough balance | "Your card has insufficient funds." |
702
+ | `expired_card` | Card expired | "Your card is expired. Please update your payment method." |
703
+ | `incorrect_cvc` | Wrong CVC | "Incorrect security code. Please check and try again." |
704
+ | `stolen_card` / `lost_card` | Flagged by issuer | "Your card was declined. Please contact your bank." |
705
+ | `do_not_honor` | Issuer catch-all decline | "Your card was declined. Please try a different card or contact your bank." |
706
+ | `fraudulent` | Stripe Radar blocked | Log internally; do not tell user it was flagged as fraud |
707
+
708
+ ### Troubleshooting checklist
709
+
710
+ | Symptom | Likely cause | Fix |
711
+ |---------|-------------|-----|
712
+ | `401 Unauthorized` | Wrong key or test key in prod | Confirm key prefix: `sk_live_` for production |
713
+ | `404` on a valid-looking ID | Wrong mode (test ID in live mode) | `pi_test_...` IDs only work with `sk_test_...` |
714
+ | Webhook `400` signature failure | Raw body was parsed/modified | Use `request.data` (raw bytes) before passing to `construct_event` |
715
+ | `409 idempotency_error` | Same key, different params | Generate a fresh UUID for the new request |
716
+ | Subscription stuck `incomplete` | Customer never confirmed payment | Send them the `latest_invoice.hosted_invoice_url`; confirm within 23 hours |
717
+ | `402` on off-session charge | 3DS required | Handle `requires_action` — send `payment_intent.client_secret` to customer |
718
+ | Webhook events arriving twice | Stripe retry after timeout | Make handlers idempotent; deduplicate on `event.id` |
719
+
720
+ ---
721
+
722
+ ## Security & compliance
723
+
724
+ ### PCI compliance
725
+
726
+ Stripe handles PCI scope when you use Stripe.js / Stripe Elements / Payment Element or Checkout Sessions — you never touch raw card numbers. Maintain **SAQ A** compliance:
727
+
728
+ - Never log, store, or transmit raw card numbers (`number`, `cvc`, full `exp_month`/`exp_year` combination).
729
+ - Never accept card data in your own API endpoint — only accept PaymentMethod IDs (`pm_...`) or tokens.
730
+ - Serve your payment page over HTTPS.
731
+ - If you find card data in logs, rotate the API keys immediately and notify Stripe.
732
+
733
+ ### API key security
734
+
735
+ - Store keys in environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault), never in source code.
736
+ - Use **restricted keys** for operations that don't need full access (e.g., a reporting service needs only `Read` on `Charges` and `Invoices`).
737
+ - Rotate keys immediately on suspected exposure: Dashboard → API keys → Roll key.
738
+ - Use `sk_test_` in all non-production environments — a test key can never trigger live charges.
739
+
740
+ ### Webhook security
741
+
742
+ - Always verify `Stripe-Signature` before processing any webhook payload.
743
+ - Use a **separate webhook signing secret** (`whsec_...`) per endpoint — do not reuse across environments.
744
+ - Store the signing secret in environment variables.
745
+ - Reject webhooks with a timestamp more than **5 minutes** old to prevent replay attacks (the SDK does this by default with a 300-second tolerance).
746
+
747
+ ### Stripe Connect — platform responsibilities
748
+
749
+ - Use the minimum Connect account type needed (Express > Standard > Custom — lower customisation = lower compliance burden).
750
+ - Platforms are responsible for complying with KYC/AML requirements for their connected accounts.
751
+ - Never display the connected account's full bank account or SSN to end users.
752
+
753
+ ### Audit trail
754
+
755
+ Every API action is logged in **Dashboard → Developers → Logs** (7-day retention for all accounts; extended with Sigma). Use `metadata` to attach your internal IDs for easier cross-referencing.
756
+
757
+ ---
758
+
759
+ ## Testing checklist
760
+
761
+ Use sandbox keys (`sk_test_`, `pk_test_`) and the test card numbers below. No real money moves.
762
+
763
+ ### Test card numbers
764
+
765
+ | Scenario | Card number | Expiry | CVC |
766
+ |----------|-------------|--------|-----|
767
+ | Payment succeeds | `4242 4242 4242 4242` | Any future | Any 3 digits |
768
+ | Payment declined (generic) | `4000 0000 0000 0002` | Any future | Any 3 digits |
769
+ | Insufficient funds | `4000 0000 0000 9995` | Any future | Any 3 digits |
770
+ | 3D Secure required | `4000 0025 0000 3155` | Any future | Any 3 digits |
771
+ | 3D Secure 2 — frictionless pass | `4000 0000 0000 3220` | Any future | Any 3 digits |
772
+ | Card expired | `4000 0000 0000 0069` | Any future | Any 3 digits |
773
+ | Incorrect CVC | `4000 0000 0000 0101` | Any future | Any 3 digits |
774
+ | Mastercard success | `5555 5555 5555 4444` | Any future | Any 3 digits |
775
+
776
+ ### Trigger test webhook events (Stripe CLI)
777
+
778
+ ```bash
779
+ # Install: brew install stripe/stripe-cli/stripe
780
+ stripe login
781
+ stripe listen --forward-to localhost:8000/stripe/webhook
782
+
783
+ # In a separate terminal:
784
+ stripe trigger payment_intent.succeeded
785
+ stripe trigger invoice.payment_failed
786
+ stripe trigger customer.subscription.deleted
787
+ stripe trigger checkout.session.completed
788
+ ```
789
+
790
+ ### QA checklist
791
+
792
+ - [ ] PaymentIntent created in sandbox; `client_secret` returned
793
+ - [ ] Test card `4242...` → PaymentIntent reaches `succeeded`
794
+ - [ ] Decline card `4000...0002` → `402` with `card_error`, `decline_code: card_declined`
795
+ - [ ] 3DS card `4000...3155` → PaymentIntent reaches `requires_action`; completes after challenge
796
+ - [ ] Refund issued on succeeded Charge; `re_...` returned with `status: succeeded`
797
+ - [ ] Subscription created with `payment_behavior=default_incomplete`; first invoice payment confirmed
798
+ - [ ] `invoice.payment_failed` webhook received and processed without error
799
+ - [ ] `cancel_at_period_end=true` sets flag; `customer.subscription.deleted` fires at period end
800
+ - [ ] Webhook signature verification passes for valid payload; returns `400` for tampered payload
801
+ - [ ] Idempotency key: same request sent twice → identical response, no duplicate charge
802
+ - [ ] Pagination loop retrieves all pages (`has_more=false` terminates loop)
803
+ - [ ] Rate limit hit in sandbox (25 req/sec); `429` handled with backoff, eventual success
804
+
805
+ ---
806
+
807
+ ## Sources
808
+
809
+ - [Stripe API Reference](https://docs.stripe.com/api)
810
+ - [Authentication & API Keys](https://docs.stripe.com/keys)
811
+ - [API Versioning & Changelog](https://docs.stripe.com/changelog)
812
+ - [Payment Intents](https://docs.stripe.com/payments/payment-intents)
813
+ - [Subscriptions Overview](https://docs.stripe.com/billing/subscriptions/overview)
814
+ - [Checkout Sessions](https://docs.stripe.com/payments/checkout)
815
+ - [Refunds](https://docs.stripe.com/refunds)
816
+ - [Webhook Integration](https://docs.stripe.com/webhooks)
817
+ - [Idempotent Requests](https://docs.stripe.com/idempotency)
818
+ - [Rate Limits](https://docs.stripe.com/rate-limits)
819
+ - [Error Codes](https://docs.stripe.com/error-codes)
820
+ - [Stripe Connect](https://docs.stripe.com/connect)
821
+ - [Testing](https://docs.stripe.com/testing)
822
+ - [Security Best Practices](https://docs.stripe.com/security)
823
+ - [API Status](https://status.stripe.com)