zuplo 6.69.9 → 6.69.11

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.
Files changed (65) hide show
  1. package/docs/ai-gateway/apps.mdx +5 -5
  2. package/docs/ai-gateway/custom-providers.mdx +6 -5
  3. package/docs/ai-gateway/getting-started.mdx +2 -1
  4. package/docs/ai-gateway/guardrails.mdx +2 -2
  5. package/docs/ai-gateway/managing-apps.mdx +10 -8
  6. package/docs/ai-gateway/managing-providers.mdx +9 -7
  7. package/docs/ai-gateway/managing-teams.mdx +4 -4
  8. package/docs/ai-gateway/usage-limits.mdx +8 -5
  9. package/docs/articles/accounts/audit-logs.mdx +3 -5
  10. package/docs/articles/accounts/billing.mdx +9 -5
  11. package/docs/articles/accounts/default-api-key.mdx +4 -5
  12. package/docs/articles/accounts/delete-account.mdx +11 -11
  13. package/docs/articles/accounts/enterprise-sso.mdx +5 -3
  14. package/docs/articles/accounts/managing-account-members.mdx +3 -3
  15. package/docs/articles/accounts/zuplo-api-keys.mdx +8 -6
  16. package/docs/articles/api-key-administration.mdx +8 -5
  17. package/docs/articles/api-key-end-users.mdx +4 -3
  18. package/docs/articles/api-key-self-serve-integration.mdx +8 -4
  19. package/docs/articles/branch-based-deployments.mdx +7 -4
  20. package/docs/articles/custom-ci-cd-azure.mdx +3 -2
  21. package/docs/articles/custom-ci-cd-bitbucket.mdx +3 -2
  22. package/docs/articles/custom-ci-cd-circleci.mdx +4 -2
  23. package/docs/articles/custom-ci-cd-github.mdx +5 -3
  24. package/docs/articles/custom-ci-cd-gitlab.mdx +3 -2
  25. package/docs/articles/custom-ci-cd.mdx +6 -8
  26. package/docs/articles/custom-domains.mdx +8 -6
  27. package/docs/articles/environments.mdx +5 -2
  28. package/docs/articles/mcp-quickstart.mdx +2 -2
  29. package/docs/articles/migrate-from-kong.md +2 -2
  30. package/docs/articles/monetization/api-access.mdx +3 -2
  31. package/docs/articles/monetization/billing-models.md +137 -31
  32. package/docs/articles/monetization/developer-portal.md +7 -3
  33. package/docs/articles/monetization/features.mdx +0 -28
  34. package/docs/articles/monetization/meters.mdx +14 -7
  35. package/docs/articles/monetization/plans.mdx +1 -3
  36. package/docs/articles/monetization/pricing-models.mdx +21 -7
  37. package/docs/articles/monetization/private-plans.md +0 -1
  38. package/docs/articles/monetization/quickstart.md +4 -2
  39. package/docs/articles/monetization/rate-cards.mdx +40 -7
  40. package/docs/articles/monetization/stripe-integration.md +16 -12
  41. package/docs/articles/monetization/subscription-lifecycle.md +4 -4
  42. package/docs/articles/monorepo-deployment.mdx +2 -3
  43. package/docs/articles/source-control-setup-github.mdx +6 -4
  44. package/docs/articles/step-1-setup-basic-gateway.mdx +3 -3
  45. package/docs/articles/step-3-add-api-key-auth-local.mdx +4 -3
  46. package/docs/articles/step-3-add-api-key-auth.mdx +3 -2
  47. package/docs/articles/step-4-deploying-to-the-edge.mdx +6 -4
  48. package/docs/articles/testing.mdx +4 -3
  49. package/docs/articles/troubleshooting.md +7 -4
  50. package/docs/cli/authentication.mdx +4 -2
  51. package/docs/cli/bucket-list.mdx +71 -0
  52. package/docs/cli/deploy.mdx +2 -1
  53. package/docs/cli/deploy.partial.mdx +2 -1
  54. package/docs/cli/logout.mdx +25 -0
  55. package/docs/concepts/api-keys.md +9 -8
  56. package/docs/concepts/authentication.mdx +3 -2
  57. package/docs/concepts/source-control-and-deployment.mdx +3 -1
  58. package/docs/dev-portal/documenting-mcp-servers.mdx +223 -0
  59. package/docs/dev-portal/zudoku/openapi-extensions/x-mcp-server.md +1 -1
  60. package/docs/guides/canary-routing-for-employees.mdx +3 -1
  61. package/docs/guides/user-based-backend-routing.mdx +3 -2
  62. package/docs/policies/api-key-inbound/schema.json +5 -0
  63. package/docs/programmable-api/environment.mdx +6 -5
  64. package/docs/programmable-api/zuplo-context.mdx +3 -3
  65. package/package.json +4 -4
@@ -46,9 +46,10 @@ are set in your terminal:
46
46
 
47
47
  ```bash
48
48
  # Your Bucket ID (could be working-copy, preview, or production)
49
- # (Found in Project Services > Bucket Details)
49
+ # (Found in Project Services > Bucket Details — https://portal.zuplo.com/+/account/project/services)
50
50
  export BUCKET_ID=your-bucket-id
51
- # Your Zuplo API Key (Found in Account Settings > Zuplo API Keys)
51
+ # Your Zuplo API Key (Found in Account Settings > Zuplo API Keys
52
+ # https://portal.zuplo.com/+/account/settings/api-keys)
52
53
  export ZAPI_KEY=zpka_YOUR_API_KEY
53
54
  ```
54
55
 
@@ -45,15 +45,16 @@ API until their quota runs out. Clear and predictable for budgeting.
45
45
  "rateCards": [
46
46
  {
47
47
  "type": "flat_fee",
48
- "key": "api_calls",
48
+ "key": "api_requests",
49
49
  "name": "API Calls",
50
- "featureKey": "api_calls",
50
+ "featureKey": "api_requests",
51
51
  "billingCadence": null,
52
52
  "price": null,
53
53
  "entitlementTemplate": {
54
54
  "type": "metered",
55
55
  "issueAfterReset": 1000,
56
- "isSoftLimit": false
56
+ "isSoftLimit": false,
57
+ "usagePeriod": "P1M"
57
58
  }
58
59
  }
59
60
  ]
@@ -78,9 +79,9 @@ API until their quota runs out. Clear and predictable for budgeting.
78
79
  "rateCards": [
79
80
  {
80
81
  "type": "flat_fee",
81
- "key": "api_calls",
82
+ "key": "api_requests",
82
83
  "name": "API Calls",
83
- "featureKey": "api_calls",
84
+ "featureKey": "api_requests",
84
85
  "billingCadence": "P1M",
85
86
  "price": {
86
87
  "type": "flat",
@@ -114,9 +115,9 @@ API until their quota runs out. Clear and predictable for budgeting.
114
115
  "rateCards": [
115
116
  {
116
117
  "type": "flat_fee",
117
- "key": "api_calls",
118
+ "key": "api_requests",
118
119
  "name": "API Calls",
119
- "featureKey": "api_calls",
120
+ "featureKey": "api_requests",
120
121
  "billingCadence": "P1M",
121
122
  "price": {
122
123
  "type": "flat",
@@ -134,8 +135,9 @@ API until their quota runs out. Clear and predictable for budgeting.
134
135
  }
135
136
  ```
136
137
 
137
- **Stripe behavior:** Subscription created with a fixed-price line item. Payment
138
- charged in advance at the start of each billing period.
138
+ **Stripe behavior:** At the start of each billing period, Zuplo issues a Stripe
139
+ Invoice with a single fixed-price line item; Stripe collects the payment in
140
+ advance.
139
141
 
140
142
  ## Pay-as-you-go
141
143
 
@@ -173,9 +175,9 @@ pay for what they use. No quota limits, no hard caps.
173
175
  "rateCards": [
174
176
  {
175
177
  "type": "usage_based",
176
- "key": "api_calls",
178
+ "key": "api_requests",
177
179
  "name": "API Calls",
178
- "featureKey": "api_calls",
180
+ "featureKey": "api_requests",
179
181
  "billingCadence": "P1M",
180
182
  "price": {
181
183
  "type": "unit",
@@ -199,7 +201,7 @@ quota and no hard limit — everything is billed per-unit.
199
201
 
200
202
  ```json
201
203
  {
202
- "key": "paygo-graduated",
204
+ "key": "paygograduated",
203
205
  "name": "Pay As You Go",
204
206
  "currency": "USD",
205
207
  "billingCadence": "P1M",
@@ -211,9 +213,9 @@ quota and no hard limit — everything is billed per-unit.
211
213
  "rateCards": [
212
214
  {
213
215
  "type": "usage_based",
214
- "key": "api_calls",
216
+ "key": "api_requests",
215
217
  "name": "API Calls",
216
- "featureKey": "api_calls",
218
+ "featureKey": "api_requests",
217
219
  "billingCadence": "P1M",
218
220
  "price": {
219
221
  "type": "tiered",
@@ -221,14 +223,16 @@ quota and no hard limit — everything is billed per-unit.
221
223
  "tiers": [
222
224
  {
223
225
  "upToAmount": "10000",
226
+ "flatPrice": null,
224
227
  "unitPrice": { "type": "unit", "amount": "0.10" }
225
228
  },
226
229
  {
227
230
  "upToAmount": "100000",
231
+ "flatPrice": null,
228
232
  "unitPrice": { "type": "unit", "amount": "0.05" }
229
233
  },
230
234
  {
231
- "upToAmount": null,
235
+ "flatPrice": null,
232
236
  "unitPrice": { "type": "unit", "amount": "0.01" }
233
237
  }
234
238
  ]
@@ -244,9 +248,8 @@ quota and no hard limit — everything is billed per-unit.
244
248
  }
245
249
  ```
246
250
 
247
- **Stripe behavior:** Subscription with usage-based billing. Usage is tracked
248
- continuously and billed through the integrated billing system at the end of each
249
- period.
251
+ **Stripe behavior:** At the end of each billing period, Zuplo issues a Stripe
252
+ Invoice with usage-based line items in arrears; Stripe collects the payment.
250
253
 
251
254
  **Risk consideration:** Pay-as-you-go means you're extending credit. If a
252
255
  customer racks up significant usage and their card declines at invoicing time,
@@ -285,9 +288,9 @@ overage:
285
288
  "rateCards": [
286
289
  {
287
290
  "type": "usage_based",
288
- "key": "api_calls",
291
+ "key": "api_requests",
289
292
  "name": "API Calls",
290
- "featureKey": "api_calls",
293
+ "featureKey": "api_requests",
291
294
  "billingCadence": "P1M",
292
295
  "price": {
293
296
  "type": "tiered",
@@ -300,7 +303,7 @@ overage:
300
303
  },
301
304
  {
302
305
  "flatPrice": null,
303
- "unitPrice": { "type": "unit", "amount": "0.05" }
306
+ "unitPrice": { "type": "unit", "amount": "0.0005" }
304
307
  }
305
308
  ]
306
309
  },
@@ -316,9 +319,20 @@ overage:
316
319
  }
317
320
  ```
318
321
 
319
- $499/month for 1,000,000 requests. Requests beyond 1M are billed at $0.05 each.
320
- A customer using 1,200,000 requests pays $499 + (200,000 x $0.05) = $499 + $100
321
- = $599.
322
+ $499 covers up to 1,000,000 requests. Requests beyond 1M are billed at $0.0005
323
+ each. A customer using 1,200,000 requests pays $499 + (200,000 x $0.0005) =
324
+ $499 + $100 = $599.
325
+
326
+ :::note
327
+
328
+ The $499 sits inside tier 1's `flatPrice`, not as a separate subscription fee.
329
+ It's charged unconditionally for the period (regardless of actual usage), but
330
+ **in arrears** — it appears on the invoice issued after the end of the billing
331
+ period, as part of the invoice's tiered usage line. To collect $499 at the
332
+ **start** of every billing period instead (a true in-advance subscription fee),
333
+ see [Example: Base fee in advance](#example-base-fee-in-advance) below.
334
+
335
+ :::
322
336
 
323
337
  ### Example: Graduated overage pricing
324
338
 
@@ -338,9 +352,9 @@ For high-volume APIs, you might want overage pricing that decreases at scale:
338
352
  "rateCards": [
339
353
  {
340
354
  "type": "usage_based",
341
- "key": "api_calls",
355
+ "key": "api_requests",
342
356
  "name": "API Calls",
343
- "featureKey": "api_calls",
357
+ "featureKey": "api_requests",
344
358
  "billingCadence": "P1M",
345
359
  "price": {
346
360
  "type": "tiered",
@@ -353,10 +367,10 @@ For high-volume APIs, you might want overage pricing that decreases at scale:
353
367
  },
354
368
  {
355
369
  "upToAmount": "5000000",
356
- "unitPrice": { "type": "unit", "amount": "0.05" }
370
+ "unitPrice": { "type": "unit", "amount": "0.0005" }
357
371
  },
358
372
  {
359
- "unitPrice": { "type": "unit", "amount": "0.02" }
373
+ "unitPrice": { "type": "unit", "amount": "0.0002" }
360
374
  }
361
375
  ]
362
376
  },
@@ -372,9 +386,101 @@ For high-volume APIs, you might want overage pricing that decreases at scale:
372
386
  }
373
387
  ```
374
388
 
375
- **Stripe behavior:** Subscription with both a fixed-price component (advance
376
- payment) and a usage-based component (arrears). Usage is tracked and billed
377
- through the integrated billing system.
389
+ :::note
390
+
391
+ Like the previous example, the $499 sits inside tier 1's `flatPrice` and is
392
+ charged unconditionally for the period in arrears, as part of the invoice's
393
+ tiered usage line.
394
+
395
+ :::
396
+
397
+ ### Example: Base fee in advance
398
+
399
+ If you need the $499 collected unconditionally at the start of every billing
400
+ period (a true subscription fee), split it into a separate `flat_fee` rate card
401
+ with `paymentTerm: "in_advance"` and set the usage-based rate card's tier 1 to
402
+ $0 per unit for the included quota:
403
+
404
+ ```json
405
+ {
406
+ "key": "enterprise",
407
+ "name": "Enterprise",
408
+ "currency": "USD",
409
+ "billingCadence": "P1M",
410
+ "phases": [
411
+ {
412
+ "key": "default",
413
+ "name": "Enterprise Monthly",
414
+ "duration": null,
415
+ "rateCards": [
416
+ {
417
+ "type": "flat_fee",
418
+ "key": "subscription_fee",
419
+ "name": "Enterprise Subscription",
420
+ "billingCadence": "P1M",
421
+ "price": {
422
+ "type": "flat",
423
+ "amount": "499.00",
424
+ "paymentTerm": "in_advance"
425
+ }
426
+ },
427
+ {
428
+ "type": "usage_based",
429
+ "key": "api_requests",
430
+ "name": "API Calls",
431
+ "featureKey": "api_requests",
432
+ "billingCadence": "P1M",
433
+ "entitlementTemplate": {
434
+ "type": "metered",
435
+ "issueAfterReset": 1000000,
436
+ "isSoftLimit": true
437
+ },
438
+ "price": {
439
+ "type": "tiered",
440
+ "mode": "graduated",
441
+ "tiers": [
442
+ {
443
+ "upToAmount": "1000000",
444
+ "flatPrice": null,
445
+ "unitPrice": { "type": "unit", "amount": "0.00" }
446
+ },
447
+ {
448
+ "flatPrice": null,
449
+ "unitPrice": { "type": "unit", "amount": "0.0005" }
450
+ }
451
+ ]
452
+ }
453
+ }
454
+ ]
455
+ }
456
+ ]
457
+ }
458
+ ```
459
+
460
+ Both patterns charge the customer $499 for every billing period regardless of
461
+ usage. The differences are timing and how the fee appears on the invoice:
462
+
463
+ | Behavior | Tier-1 flat price (previous examples) | Separate flat-fee rate card (this example) |
464
+ | ------------------------ | ---------------------------------------------------- | ---------------------------------------------------------------------------------- |
465
+ | When the $499 is charged | End of period, in arrears | Start of period, in advance |
466
+ | Invoice presentation | Single tiered usage line item that includes the $499 | Distinct line items: one for the $499, one for usage |
467
+ | Best for | When end-of-period billing is acceptable | True subscriptions where the fee should be collected upfront and listed separately |
468
+
469
+ The `subscription_fee` rate card has no `featureKey` — it's a
470
+ [rate card without a feature](./rate-cards.mdx#rate-cards-without-features), the
471
+ right shape for a billing-only line item that doesn't grant any entitlement.
472
+
473
+ **Stripe behavior:** At the start of each billing period, Zuplo issues a single
474
+ Stripe Invoice that includes both:
475
+
476
+ - The $499 fixed-price line item from the `subscription_fee` rate card, charged
477
+ in advance for the period that's just starting.
478
+ - Any usage-based line items for overage above 1M from the **previous** billing
479
+ period, charged in arrears.
480
+
481
+ Stripe collects payment for the full invoice. The first billing period's invoice
482
+ contains only the $499, since there's no prior period to bill overage for. No
483
+ Stripe Subscription is created.
378
484
 
379
485
  ## Credits / tokens (prepaid)
380
486
 
@@ -76,8 +76,10 @@ Save and deploy. Once the plugin is enabled, ensure:
76
76
 
77
77
  ### Plan display order
78
78
 
79
- Control plan display order in the Zuplo Portal under **Services →
80
- Monetization**. Plans can be reordered using drag-and-drop.
79
+ Control plan display order from your project's
80
+ [**Services**](https://portal.zuplo.com/+/account/project/services) page in the
81
+ Zuplo Portal — open the Monetization Service. Plans can be reordered using
82
+ drag-and-drop.
81
83
 
82
84
  ### Feature comparison matrix
83
85
 
@@ -158,7 +160,9 @@ use the same fonts, colors, and layout as the rest of your portal.
158
160
  The Developer Portal runs at `https://your-project.zuplo.dev/docs` by default.
159
161
  For production, configure a custom domain:
160
162
 
161
- 1. Navigate to **Settings → Custom Domains** in the Zuplo Portal
163
+ 1. Open
164
+ [**Account Settings → Custom Domains**](https://portal.zuplo.com/+/account/settings/custom-domains)
165
+ in the Zuplo Portal
162
166
  2. Add your domain (e.g., `developers.your-company.com`)
163
167
  3. Configure the DNS records as instructed
164
168
  4. SSL is provisioned automatically
@@ -95,34 +95,6 @@ curl \
95
95
  EOF
96
96
  ```
97
97
 
98
- ### Creating a Billing-Only Feature
99
-
100
- Some plans charge a flat subscription fee that isn't tied to any entitlement — a
101
- monthly access fee, a setup fee, or a fixed retainer. Model these the same way
102
- as a static feature (no `meterSlug`), then attach them to a plan via a
103
- `flat_fee` rate card with no `entitlementTemplate` and a price whose
104
- `paymentTerm` is `"in_advance"`. Zuplo issues a Stripe Invoice for the fee at
105
- the start of each billing period.
106
-
107
- ```shell
108
- curl \
109
- https://dev.zuplo.com/v3/metering/$BUCKET_ID/features \
110
- --request POST \
111
- --header "Authorization: Bearer $ZAPI_KEY" \
112
- --header "Content-Type: application/json" \
113
- --data @- << EOF
114
- {
115
- "key": "monthly_fee",
116
- "name": "Monthly Fee"
117
- }
118
- EOF
119
- ```
120
-
121
- Because the rate card carries no entitlement, the developer portal's
122
- feature-comparison matrix doesn't render a row for the feature — the price rolls
123
- into the plan's headline cost. See the Pro plan example in [Plans](./plans.mdx)
124
- for the rate-card shape.
125
-
126
98
  ## API Reference
127
99
 
128
100
  For complete API operations (list, get, archive), see the
@@ -43,8 +43,10 @@ Track the total number of API requests:
43
43
  }
44
44
  ```
45
45
 
46
- Each event contains the `subscription` ID linking it to a subscription and a
47
- `total` field in `data` with the quantity to record:
46
+ Each event identifies the subscription being metered, the actor that drove the
47
+ consumption, and how much to record. The `subscription` field carries the
48
+ subscription ID, the `subject` field identifies the actor, and `data.total`
49
+ carries the quantity:
48
50
 
49
51
  ```json
50
52
  {
@@ -52,7 +54,7 @@ Each event contains the `subscription` ID linking it to a subscription and a
52
54
  "specversion": "1.0",
53
55
  "type": "api_requests",
54
56
  "source": "monetization-policy",
55
- "subject": "01KNVXHQG356VA7T7W0V9N21GH",
57
+ "subject": "acme-prod",
56
58
  "subscription": "01KNVXHQG356VA7T7W0V9N21GH",
57
59
  "data": {
58
60
  "total": 1
@@ -62,8 +64,13 @@ Each event contains the `subscription` ID linking it to a subscription and a
62
64
 
63
65
  :::note
64
66
 
65
- Events emitted by the `MonetizationInboundPolicy` always set `subject` and
66
- `subscription` to the same subscription ULID. See
67
+ `subject` identifies _who_ consumed the subscription's entitlements on this
68
+ request typically the API key's consumer name, the end-user id, or another
69
+ stable per-actor identifier. It is **not** the subscription id (use the
70
+ `subscription` field for that) and is not used to route billing. Its purpose is
71
+ to let you break down usage within a subscription so you can see which key,
72
+ user, or agent drove the consumption — a single subscription will commonly emit
73
+ events with many different `subject` values. See
67
74
  [Monetization Policy](./monetization-policy.md) for how usage is recorded.
68
75
 
69
76
  :::
@@ -96,7 +103,7 @@ consumed 50 tokens looks like this:
96
103
  "specversion": "1.0",
97
104
  "type": "tokens",
98
105
  "source": "monetization-policy",
99
- "subject": "01KNVXHQG356VA7T7W0V9N21GH",
106
+ "subject": "acme-prod",
100
107
  "subscription": "01KNVXHQG356VA7T7W0V9N21GH",
101
108
  "data": {
102
109
  "total": 50
@@ -126,7 +133,7 @@ Each event reports the number of bytes transferred:
126
133
  "specversion": "1.0",
127
134
  "type": "data_transfer",
128
135
  "source": "monetization-policy",
129
- "subject": "01KNVXHQG356VA7T7W0V9N21GH",
136
+ "subject": "acme-prod",
130
137
  "subscription": "01KNVXHQG356VA7T7W0V9N21GH",
131
138
  "data": {
132
139
  "total": 4096
@@ -138,7 +138,6 @@ curl \
138
138
  "type": "flat_fee",
139
139
  "key": "monthly_fee",
140
140
  "name": "Monthly Fee",
141
- "featureKey": "monthly_fee",
142
141
  "billingCadence": "P1M",
143
142
  "price": {
144
143
  "type": "flat",
@@ -204,8 +203,7 @@ After the trial ends, customers automatically move to the default phase. The $99
204
203
  monthly subscription fee is charged in advance at the start of each billing
205
204
  period via the `monthly_fee` flat-fee rate card. The plan includes 10,000 API
206
205
  requests per period; additional requests are billed at $0.01 each in arrears
207
- (the soft limit on the metered entitlement allows overage to flow through to the
208
- next invoice).
206
+ (soft limit allows overage).
209
207
 
210
208
  ## Plan Properties
211
209
 
@@ -23,7 +23,8 @@ cards for subscriptions, setup fees, or access charges.
23
23
 
24
24
  ### Recurring Subscription
25
25
 
26
- A monthly platform fee that recurs each billing period:
26
+ A monthly subscription fee that recurs each billing period and is collected in
27
+ advance:
27
28
 
28
29
  ```json
29
30
  {
@@ -33,11 +34,24 @@ A monthly platform fee that recurs each billing period:
33
34
  "billingCadence": "P1M",
34
35
  "price": {
35
36
  "type": "flat",
36
- "amount": "99.00"
37
+ "amount": "99.00",
38
+ "paymentTerm": "in_advance"
37
39
  }
38
40
  }
39
41
  ```
40
42
 
43
+ Each billing period — every month for `P1M` — Zuplo adds a $99.00 line item for
44
+ this rate card to the customer's Stripe Invoice. Because `paymentTerm` is
45
+ `in_advance` (the default for flat prices), the customer is charged at the start
46
+ of the period rather than the end.
47
+
48
+ The rate card's `billingCadence` must align with the plan's `billingCadence` —
49
+ see [Rate Cards → Billing Cadence](./rate-cards.mdx#billing-cadence) for the
50
+ alignment rule. A flat-fee rate card like this one doesn't need a `featureKey`
51
+ (see
52
+ [Rate Cards Without Features](./rate-cards.mdx#rate-cards-without-features)) —
53
+ the rate card's `key` and `name` appear directly on the customer's invoice.
54
+
41
55
  ### One-Time Setup Fee
42
56
 
43
57
  A setup fee charged once when the subscription starts (no `billingCadence`):
@@ -62,7 +76,7 @@ Per-unit pricing charges a fixed amount for each unit of metered usage. Use
62
76
  ```json
63
77
  {
64
78
  "type": "usage_based",
65
- "featureKey": "api_calls",
79
+ "featureKey": "api_requests",
66
80
  "billingCadence": "P1M",
67
81
  "price": {
68
82
  "type": "unit",
@@ -90,7 +104,7 @@ Each unit is charged according to the tier it falls into:
90
104
  ```json
91
105
  {
92
106
  "type": "usage_based",
93
- "featureKey": "api_calls",
107
+ "featureKey": "api_requests",
94
108
  "billingCadence": "P1M",
95
109
  "price": {
96
110
  "type": "tiered",
@@ -125,7 +139,7 @@ All units are charged at the rate of the highest tier reached:
125
139
  ```json
126
140
  {
127
141
  "type": "usage_based",
128
- "featureKey": "api_calls",
142
+ "featureKey": "api_requests",
129
143
  "billingCadence": "P1M",
130
144
  "price": {
131
145
  "type": "tiered",
@@ -157,7 +171,7 @@ common pattern for "X calls included, then $Y per additional call":
157
171
  ```json
158
172
  {
159
173
  "type": "usage_based",
160
- "featureKey": "api_calls",
174
+ "featureKey": "api_requests",
161
175
  "billingCadence": "P1M",
162
176
  "price": {
163
177
  "type": "tiered",
@@ -185,7 +199,7 @@ Package pricing sells usage in fixed bundles rather than individual units:
185
199
  ```json
186
200
  {
187
201
  "type": "usage_based",
188
- "featureKey": "api_calls",
202
+ "featureKey": "api_requests",
189
203
  "billingCadence": "P1M",
190
204
  "price": {
191
205
  "type": "package",
@@ -54,7 +54,6 @@ curl -X POST "https://dev.zuplo.com/v3/metering/${ZUPLO_BUCKET_ID}/plans" \
54
54
  "rateCards": [
55
55
  {
56
56
  "billingCadence": "P1M",
57
- "featureKey": "monthly_fee",
58
57
  "key": "monthly_fee",
59
58
  "name": "Monthly Fee",
60
59
  "price": {
@@ -46,7 +46,8 @@ keeps your existing work safe from any breaking changes.
46
46
  :::
47
47
 
48
48
  1. Go to [portal.zuplo.com](https://portal.zuplo.com) and sign in.
49
- 2. Click **New Project** in the top right corner.
49
+ 2. Click **New Project** in the top right corner
50
+ ([open](https://portal.zuplo.com/+/account/projects/new)).
50
51
  3. Enter a **Project name** or use the randomly chosen name Zuplo provides.
51
52
  4. Select **Starter Project (Recommended)** — it comes with endpoints ready to
52
53
  monetize.
@@ -83,7 +84,8 @@ Add the monetization plugin to your Developer Portal configuration.
83
84
 
84
85
  ## Step 3: Configure the Monetization Service
85
86
 
86
- 1. Navigate to the **Services** tab in your project.
87
+ 1. Open the [**Services**](https://portal.zuplo.com/+/account/project/services)
88
+ tab in your project.
87
89
  2. Select the environment you want to configure. We will use **Working Copy**
88
90
  for this quickstart.
89
91
  3. Click **Configure** on the **Monetization Service** card.
@@ -26,7 +26,9 @@ A rate card consists of:
26
26
  - **Feature** - Optional link to a feature from your product catalog
27
27
  - **Price** - How much to charge (see [Pricing Models](./pricing-models.mdx))
28
28
  - **Entitlement** - Optional usage limits or access controls
29
- - **Billing Cadence** - How often to bill (monthly, one-time, etc.)
29
+ - **Billing Cadence** - How often this rate card produces a charge — distinct
30
+ from the plan's billing cadence, and constrained to align with it (see
31
+ [Billing Cadence](#billing-cadence) below)
30
32
 
31
33
  ## Rate Card Types
32
34
 
@@ -53,8 +55,9 @@ recurring fee. Use these for:
53
55
  }
54
56
  ```
55
57
 
56
- When `billingCadence` is set (e.g., `P1M` for monthly), the fee recurs each
57
- billing period. When `billingCadence` is `null`, the fee is charged once per
58
+ When `billingCadence` is set (e.g., `P1M`), the flat fee recurs at that cadence
59
+ see [Billing Cadence](#billing-cadence) for the constraint relative to the
60
+ plan's cadence. When `billingCadence` is `null`, the fee is charged once per
58
61
  subscription phase.
59
62
 
60
63
  The `paymentTerm` field controls when the charge is collected:
@@ -75,9 +78,9 @@ feature linked to a meter. Use these for:
75
78
  ```json
76
79
  {
77
80
  "type": "usage_based",
78
- "key": "api_calls",
81
+ "key": "api_requests",
79
82
  "name": "API Calls",
80
- "featureKey": "api_calls",
83
+ "featureKey": "api_requests",
81
84
  "billingCadence": "P1M",
82
85
  "price": {
83
86
  "type": "unit",
@@ -90,6 +93,36 @@ Usage-based rate cards support multiple pricing models. See
90
93
  [Pricing Models](./pricing-models.mdx) for details on unit, tiered, package, and
91
94
  dynamic pricing.
92
95
 
96
+ ## Billing Cadence
97
+
98
+ A rate card's `billingCadence` controls how often this specific rate card
99
+ produces a charge. It's distinct from the **plan's** `billingCadence`, which
100
+ sets the overall invoice schedule for the subscription:
101
+
102
+ - For **flat-fee** rate cards, the cadence determines how often the flat fee
103
+ recurs. Set it to `null` to charge once per subscription phase (a setup fee,
104
+ onboarding charge, or other one-time payment).
105
+ - For **usage-based** rate cards, the cadence is required and determines the
106
+ period over which metered usage is aggregated and emitted as an invoice line.
107
+
108
+ ### Alignment with the plan
109
+
110
+ The rate card's cadence must align with the plan's `billingCadence`. Two
111
+ cadences align when:
112
+
113
+ - They are identical (e.g., plan `P1M` and rate card `P1M`), or
114
+ - The shorter one divides the longer one without remainder (e.g., plan `P1M`
115
+ with a rate card at `P3M`, or plan `P1Y` with a rate card at `P1M`).
116
+
117
+ Plans accept these `billingCadence` values: `PT1H`, `P1D`, `P1W`, `P2W`, `P4W`,
118
+ `P1M`, `P3M`, `P6M`, `P12M`, `P1Y`. A rate card with a cadence that doesn't
119
+ align (for example, `P2M` on a `P3M` plan, where neither divides the other) is
120
+ rejected at plan creation.
121
+
122
+ This rule exists for invoice-generation correctness: it guarantees that every
123
+ rate-card cycle ends on a plan-invoice boundary, so a single charge from this
124
+ rate card lands on exactly one customer invoice rather than straddling two.
125
+
93
126
  ## Rate Cards With Features
94
127
 
95
128
  When a rate card is linked to a feature via `featureKey`:
@@ -121,9 +154,9 @@ include:
121
154
  ```json
122
155
  {
123
156
  "type": "usage_based",
124
- "key": "api_calls",
157
+ "key": "api_requests",
125
158
  "name": "API Calls",
126
- "featureKey": "api_calls",
159
+ "featureKey": "api_requests",
127
160
  "billingCadence": "P1M",
128
161
  "price": {
129
162
  "type": "unit",