zuplo 6.70.70 → 6.71.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.
- package/docs/ai-gateway/getting-started.mdx +2 -1
- package/docs/ai-gateway/integrations/ai-sdk.mdx +17 -0
- package/docs/ai-gateway/introduction.mdx +5 -5
- package/docs/ai-gateway/providers.mdx +2 -0
- package/docs/analytics/access-and-entitlements.md +71 -0
- package/docs/analytics/overview.md +67 -0
- package/docs/analytics/reference/metrics-glossary.md +105 -0
- package/docs/analytics/reference/url-parameters.md +66 -0
- package/docs/analytics/shared-controls.md +122 -0
- package/docs/analytics/tabs/agents.md +88 -0
- package/docs/analytics/tabs/consumers.md +73 -0
- package/docs/analytics/tabs/graphql.md +78 -0
- package/docs/analytics/tabs/mcp.md +80 -0
- package/docs/analytics/tabs/origins.md +83 -0
- package/docs/analytics/tabs/requests.md +97 -0
- package/docs/articles/accounts/enterprise-sso.mdx +8 -6
- package/docs/articles/api-key-administration.mdx +4 -0
- package/docs/articles/bypass-policy-for-testing.mdx +4 -0
- package/docs/articles/ci-cd-github/basic-deployment.mdx +10 -1
- package/docs/articles/ci-cd-github/deploy-and-test.mdx +14 -1
- package/docs/articles/ci-cd-github/local-testing.mdx +3 -1
- package/docs/articles/ci-cd-github/pr-preview-environments.mdx +36 -4
- package/docs/articles/custom-ci-cd-github.mdx +11 -2
- package/docs/articles/environment-variables.mdx +5 -1
- package/docs/articles/environments.mdx +2 -2
- package/docs/articles/graphql.mdx +23 -39
- package/docs/articles/mcp-quickstart-local.mdx +2 -1
- package/docs/articles/mcp-quickstart.mdx +6 -1
- package/docs/articles/monetization/api-access.mdx +184 -0
- package/docs/articles/monetization/meters.mdx +4 -4
- package/docs/articles/monetization/monetization-policy.md +4 -1
- package/docs/articles/monetization/private-plans.md +3 -4
- package/docs/articles/monetization/stripe-integration.md +9 -0
- package/docs/articles/monetization/subscription-lifecycle.md +12 -11
- package/docs/articles/monorepo-deployment.mdx +20 -2
- package/docs/articles/multiple-auth-policies.mdx +2 -2
- package/docs/articles/openapi.mdx +6 -1
- package/docs/articles/rename-or-move-project.mdx +4 -0
- package/docs/articles/securing-your-backend.mdx +11 -3
- package/docs/articles/source-control-setup-github.mdx +4 -0
- package/docs/articles/troubleshooting-slow-responses.mdx +2 -2
- package/docs/articles/troubleshooting.md +3 -3
- package/docs/cli/deploy.mdx +32 -0
- package/docs/cli/deploy.partial.mdx +32 -0
- package/docs/concepts/api-keys.md +2 -2
- package/docs/dedicated/akamai/architecture.mdx +9 -9
- package/docs/dev-portal/zudoku/components/browser-window.mdx +94 -0
- package/docs/dev-portal/zudoku/components/callout.mdx +11 -18
- package/docs/dev-portal/zudoku/components/landing-page.mdx +283 -0
- package/docs/dev-portal/zudoku/configuration/search.md +36 -0
- package/docs/dev-portal/zudoku/configuration/site.md +38 -0
- package/docs/dev-portal/zudoku/customization/colors-theme.mdx +51 -40
- package/docs/errors/rate-limit-exceeded.mdx +30 -3
- package/docs/handlers/system-handlers.mdx +2 -1
- package/docs/mcp-gateway/how-to/connect-upstream-api-key.mdx +2 -2
- package/docs/mcp-gateway/observability/analytics.mdx +17 -13
- package/docs/mcp-gateway/quickstart.mdx +4 -3
- package/docs/mcp-gateway/troubleshooting.mdx +4 -4
- package/docs/policies/_index.md +3 -0
- package/docs/policies/data-loss-prevention-inbound/doc.md +115 -0
- package/docs/policies/data-loss-prevention-inbound/intro.md +15 -0
- package/docs/policies/data-loss-prevention-inbound/schema.json +220 -0
- package/docs/policies/data-loss-prevention-outbound/doc.md +115 -0
- package/docs/policies/data-loss-prevention-outbound/intro.md +18 -0
- package/docs/policies/data-loss-prevention-outbound/schema.json +220 -0
- package/docs/policies/graphql-analytics-outbound/doc.md +93 -0
- package/docs/policies/graphql-analytics-outbound/intro.md +12 -0
- package/docs/policies/graphql-analytics-outbound/schema.json +93 -0
- package/docs/programmable-api/background-dispatcher.mdx +6 -8
- package/docs/programmable-api/zone-cache.mdx +1 -1
- package/docs/programmable-api/zuplo-context.mdx +3 -2
- package/docs/rate-limiting/combining-policies.mdx +293 -0
- package/docs/rate-limiting/dynamic-rate-limiting.mdx +240 -0
- package/docs/rate-limiting/getting-started.mdx +339 -0
- package/docs/rate-limiting/how-it-works.md +225 -0
- package/docs/rate-limiting/monitoring-and-troubleshooting.mdx +243 -0
- package/docs/{articles → rate-limiting}/per-user-rate-limits-using-db.mdx +39 -27
- package/package.json +4 -4
- package/docs/concepts/rate-limiting.md +0 -246
|
@@ -132,8 +132,10 @@ project's working copy — it only works in projects
|
|
|
132
132
|
|
|
133
133
|
1. **Install the plugin**
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
Check `docs/package.json` first — new projects ship with
|
|
136
|
+
`@zudoku/plugin-graphql` already listed in `dependencies`, so there's nothing
|
|
137
|
+
to install. Only older projects need to add it. In your project's `docs/`
|
|
138
|
+
folder (where `zudoku.config.tsx` lives), install the plugin:
|
|
137
139
|
|
|
138
140
|
```bash
|
|
139
141
|
npm install @zudoku/plugin-graphql
|
|
@@ -141,30 +143,10 @@ project's working copy — it only works in projects
|
|
|
141
143
|
|
|
142
144
|
The plugin requires `zudoku` `0.80.1` or newer.
|
|
143
145
|
|
|
144
|
-
2. **
|
|
145
|
-
|
|
146
|
-
Drop a GraphQL schema definition language (SDL) file next to your config:
|
|
147
|
-
|
|
148
|
-
```graphql title="schema.graphql"
|
|
149
|
-
type Query {
|
|
150
|
-
product(id: ID!): Product
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
type Product {
|
|
154
|
-
id: ID!
|
|
155
|
-
name: String!
|
|
156
|
-
price: Float!
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Don't have an SDL file handy? Skip this step and introspect a live endpoint
|
|
161
|
-
at build time with `type: "url"` in the next step — the schema is fetched for
|
|
162
|
-
you when the portal builds.
|
|
163
|
-
|
|
164
|
-
3. **Register the plugin**
|
|
146
|
+
2. **Register the plugin**
|
|
165
147
|
|
|
166
148
|
Import `graphqlPlugin` and add an instance per API. The `path` is where the
|
|
167
|
-
docs mount, and `input` points at your
|
|
149
|
+
docs mount, and `input` points at your GraphQL endpoint:
|
|
168
150
|
|
|
169
151
|
```tsx title="zudoku.config.tsx"
|
|
170
152
|
import { graphqlPlugin } from "@zudoku/plugin-graphql";
|
|
@@ -172,15 +154,12 @@ project's working copy — it only works in projects
|
|
|
172
154
|
const config = {
|
|
173
155
|
plugins: [
|
|
174
156
|
graphqlPlugin({
|
|
175
|
-
type: "
|
|
176
|
-
input: "
|
|
157
|
+
type: "url",
|
|
158
|
+
input: "https://graphql.example.com/api",
|
|
177
159
|
path: "/graphql/ecommerce",
|
|
178
160
|
options: {
|
|
179
161
|
title: "E-Commerce GraphQL API",
|
|
180
162
|
description: "Products, orders, and customers.",
|
|
181
|
-
playground: {
|
|
182
|
-
endpoint: "https://my-gateway.example.com/graphql",
|
|
183
|
-
},
|
|
184
163
|
},
|
|
185
164
|
}),
|
|
186
165
|
],
|
|
@@ -189,18 +168,23 @@ project's working copy — it only works in projects
|
|
|
189
168
|
export default config;
|
|
190
169
|
```
|
|
191
170
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
171
|
+
With `type: "url"`, the schema is fetched via introspection when the portal
|
|
172
|
+
builds, and the playground sends operations to that same URL by default.
|
|
173
|
+
Point `input` at the gateway route from the first half of this guide so
|
|
174
|
+
readers run real queries through your gateway — or keep the playground
|
|
175
|
+
separate from the schema source with `options.playground.endpoint`.
|
|
176
|
+
|
|
177
|
+
Have a GraphQL schema definition language (SDL) file instead of a live
|
|
178
|
+
endpoint? Use `type: "file"` and set `input` to the file's path (for example
|
|
179
|
+
`./schema.graphql`). A file-based schema doesn't tell the plugin where your
|
|
180
|
+
API lives, so also set `options.playground.endpoint` — without it the
|
|
181
|
+
reference pages still render, but the playground asks for an endpoint before
|
|
182
|
+
it can run operations.
|
|
197
183
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
playground defaults to that same URL. You can register the plugin more than
|
|
201
|
-
once to document several schemas, each with its own `path`.
|
|
184
|
+
You can register the plugin more than once to document several schemas, each
|
|
185
|
+
with its own `path`.
|
|
202
186
|
|
|
203
|
-
|
|
187
|
+
3. **Link it in the navigation**
|
|
204
188
|
|
|
205
189
|
Point a navigation link at the instance's `path`. Set `stack: true` so the
|
|
206
190
|
API's own pages render as a stacked sub-navigation instead of expanding
|
|
@@ -39,7 +39,8 @@ If you're not familiar with Zuplo, it's recommended to go through
|
|
|
39
39
|
|
|
40
40
|
1. Create an **MCP Server**
|
|
41
41
|
|
|
42
|
-
On your `routes.oas.json` file, choose **Add** and then **
|
|
42
|
+
On your `routes.oas.json` file, choose **Add** and then **Dynamic OpenAPI to
|
|
43
|
+
MCP Server**.
|
|
43
44
|
|
|
44
45
|

|
|
45
46
|
|
|
@@ -21,8 +21,12 @@ If you're not familiar with Zuplo, it's recommended to go through the
|
|
|
21
21
|
Let's import an OpenAPI document. You can download this one here
|
|
22
22
|
[todo-openapi.json](https://download-open-api-main-fae215f.d2.zuplo.dev/todo-openapi).
|
|
23
23
|
|
|
24
|
+
<ModalScreenshot size="sm">
|
|
25
|
+
|
|
24
26
|

|
|
25
27
|
|
|
28
|
+
</ModalScreenshot>
|
|
29
|
+
|
|
26
30
|
Select the **Code** tab (1), then choose the `routes.oas.json` file (2) and
|
|
27
31
|
choose **Import OpenAPI** (3).
|
|
28
32
|
|
|
@@ -49,7 +53,8 @@ If you're not familiar with Zuplo, it's recommended to go through the
|
|
|
49
53
|
|
|
50
54
|
1. Create an **MCP Server**
|
|
51
55
|
|
|
52
|
-
On your `routes.oas.json` file, choose **Add** and then **
|
|
56
|
+
On your `routes.oas.json` file, choose **Add** and then **Dynamic OpenAPI to
|
|
57
|
+
MCP Server** (3)
|
|
53
58
|
|
|
54
59
|

|
|
55
60
|
|
|
@@ -52,6 +52,190 @@ curl \
|
|
|
52
52
|
--header "Authorization: Bearer $ZAPI_KEY"
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
## Bucket monetization configuration
|
|
56
|
+
|
|
57
|
+
Each bucket has an optional `MonetizationConfiguration` that holds bucket-wide
|
|
58
|
+
behavior — multi-subscription support, plan display order, plan-level overrides,
|
|
59
|
+
and the default payment grace period. The configuration is read by the runtime
|
|
60
|
+
and the Developer Portal; it is not stored in OpenMeter.
|
|
61
|
+
|
|
62
|
+
### Read
|
|
63
|
+
|
|
64
|
+
```shell
|
|
65
|
+
curl \
|
|
66
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/monetization-configuration \
|
|
67
|
+
--header "Authorization: Bearer $ZAPI_KEY"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
When no configuration row exists for the bucket, the endpoint returns a default
|
|
71
|
+
body with `multipleSubscriptionsEnabled: false`, an empty `planOrder`, empty
|
|
72
|
+
`planSettings`, and `maxPaymentOverdueDays: 3`.
|
|
73
|
+
|
|
74
|
+
### Upsert
|
|
75
|
+
|
|
76
|
+
```shell
|
|
77
|
+
curl \
|
|
78
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/monetization-configuration \
|
|
79
|
+
--request PUT \
|
|
80
|
+
--header "Authorization: Bearer $ZAPI_KEY" \
|
|
81
|
+
--header "Content-Type: application/json" \
|
|
82
|
+
--data @- << EOF
|
|
83
|
+
{
|
|
84
|
+
"multipleSubscriptionsEnabled": false,
|
|
85
|
+
"planOrder": ["free", "starter", "pro", "enterprise"],
|
|
86
|
+
"planSettings": {
|
|
87
|
+
"pro": { "visiblePhases": ["default"] }
|
|
88
|
+
},
|
|
89
|
+
"maxPaymentOverdueDays": 7
|
|
90
|
+
}
|
|
91
|
+
EOF
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
| Field | Type | Description |
|
|
95
|
+
| ------------------------------ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
96
|
+
| `multipleSubscriptionsEnabled` | `boolean` | Stored on the bucket. Reserved for future multi-subscription rules; today the Developer Portal create-subscription path enforces a single active subscription per customer regardless of this flag. |
|
|
97
|
+
| `planOrder` | `string[]` | Ordered list of plan keys; drives pricing-page sort and upgrade/downgrade direction during plan changes |
|
|
98
|
+
| `planSettings` | `object` | Per-plan overrides keyed by plan key. The supported sub-key today is `visiblePhases` — an array of phase keys that should appear on the pricing page |
|
|
99
|
+
| `maxPaymentOverdueDays` | `integer` | Bucket-default payment grace period. Must be ≥ 0. Defaults to `3` when not set |
|
|
100
|
+
|
|
101
|
+
The request body must include at least one of these fields. All four fields are
|
|
102
|
+
optional in the request — the upsert preserves any field you don't send.
|
|
103
|
+
|
|
104
|
+
`planOrder` is consumed when a customer changes plans through the Developer
|
|
105
|
+
Portal: a target plan whose index is greater than or equal to the current plan's
|
|
106
|
+
index is treated as an upgrade (immediate timing); a lower index is treated as a
|
|
107
|
+
downgrade (next-billing-cycle timing). Plans not listed in `planOrder` default
|
|
108
|
+
to upgrade timing.
|
|
109
|
+
|
|
110
|
+
`maxPaymentOverdueDays` is the lowest-precedence default for the payment grace
|
|
111
|
+
period. See
|
|
112
|
+
[Subscription and payment validation](./monetization-policy.md#subscription-and-payment-validation)
|
|
113
|
+
for the full precedence chain (customer metadata → plan metadata → bucket
|
|
114
|
+
configuration → built-in default).
|
|
115
|
+
|
|
116
|
+
### Delete
|
|
117
|
+
|
|
118
|
+
```shell
|
|
119
|
+
curl \
|
|
120
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/monetization-configuration \
|
|
121
|
+
--request DELETE \
|
|
122
|
+
--header "Authorization: Bearer $ZAPI_KEY"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
After deletion, GET returns the default body again.
|
|
126
|
+
|
|
127
|
+
## Stripe setup and billing readiness
|
|
128
|
+
|
|
129
|
+
Most users connect Stripe through the
|
|
130
|
+
[Zuplo Portal](./stripe-integration.md#connecting-your-stripe-account). For
|
|
131
|
+
automated provisioning — CI scripts, infrastructure-as-code, or self-hosted
|
|
132
|
+
control planes — the same flow is available via these API endpoints.
|
|
133
|
+
|
|
134
|
+
### Install the Stripe app
|
|
135
|
+
|
|
136
|
+
Connect a Stripe account to a bucket and create the default billing profile in
|
|
137
|
+
one call:
|
|
138
|
+
|
|
139
|
+
```shell
|
|
140
|
+
curl \
|
|
141
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/setup/stripe \
|
|
142
|
+
--request POST \
|
|
143
|
+
--header "Authorization: Bearer $ZAPI_KEY" \
|
|
144
|
+
--header "Content-Type: application/json" \
|
|
145
|
+
--data @- << EOF
|
|
146
|
+
{
|
|
147
|
+
"apiKey": "rk_test_...",
|
|
148
|
+
"name": "Stripe Billing Profile",
|
|
149
|
+
"taxEnabled": false,
|
|
150
|
+
"taxEnforced": false,
|
|
151
|
+
"country": "US"
|
|
152
|
+
}
|
|
153
|
+
EOF
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The endpoint validates the Stripe key prefix against the bucket's environment:
|
|
157
|
+
|
|
158
|
+
- Working-copy and preview buckets accept `sk_test_*` or `rk_test_*`
|
|
159
|
+
- Production buckets accept `sk_live_*` or `rk_live_*`
|
|
160
|
+
|
|
161
|
+
The response returns the installed `appId`. The endpoint fails with a
|
|
162
|
+
`409 Conflict` if a Stripe app is already installed for the bucket.
|
|
163
|
+
|
|
164
|
+
### Read the current Stripe setup
|
|
165
|
+
|
|
166
|
+
```shell
|
|
167
|
+
curl \
|
|
168
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/setup/stripe \
|
|
169
|
+
--header "Authorization: Bearer $ZAPI_KEY"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Returns the connected Stripe app summary and the billing profiles linked to it.
|
|
173
|
+
|
|
174
|
+
### Create an additional billing profile
|
|
175
|
+
|
|
176
|
+
To attach more billing profiles to the same Stripe app:
|
|
177
|
+
|
|
178
|
+
```shell
|
|
179
|
+
curl \
|
|
180
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/setup/stripe/$STRIPE_APP_ID/billing-profile \
|
|
181
|
+
--request POST \
|
|
182
|
+
--header "Authorization: Bearer $ZAPI_KEY" \
|
|
183
|
+
--header "Content-Type: application/json" \
|
|
184
|
+
--data @- << EOF
|
|
185
|
+
{
|
|
186
|
+
"name": "EU Billing Profile",
|
|
187
|
+
"taxEnabled": true,
|
|
188
|
+
"taxEnforced": false,
|
|
189
|
+
"country": "DE"
|
|
190
|
+
}
|
|
191
|
+
EOF
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Check billing readiness
|
|
195
|
+
|
|
196
|
+
A lightweight check for tooling that gates deploys on Stripe being connected:
|
|
197
|
+
|
|
198
|
+
```shell
|
|
199
|
+
curl \
|
|
200
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/billing-readiness \
|
|
201
|
+
--header "Authorization: Bearer $ZAPI_KEY"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Response:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"hasStripeApp": true,
|
|
209
|
+
"stripeAppId": "app_01H...",
|
|
210
|
+
"hasDefaultBillingProfile": true,
|
|
211
|
+
"defaultBillingProfileId": "bp_01H..."
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Use this in setup wizards to gate the UI on whether Stripe is connected.
|
|
216
|
+
|
|
217
|
+
### Update a connected app
|
|
218
|
+
|
|
219
|
+
Rotate the Stripe key on an existing app, or update its name and metadata:
|
|
220
|
+
|
|
221
|
+
```shell
|
|
222
|
+
curl \
|
|
223
|
+
https://dev.zuplo.com/v3/metering/$BUCKET_ID/apps/$APP_ID \
|
|
224
|
+
--request PUT \
|
|
225
|
+
--header "Authorization: Bearer $ZAPI_KEY" \
|
|
226
|
+
--header "Content-Type: application/json" \
|
|
227
|
+
--data @- << EOF
|
|
228
|
+
{
|
|
229
|
+
"type": "stripe",
|
|
230
|
+
"name": "Stripe Billing Profile",
|
|
231
|
+
"secretAPIKey": "rk_test_..."
|
|
232
|
+
}
|
|
233
|
+
EOF
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The same key-prefix validation applies — a live key is rejected on a
|
|
237
|
+
non-production bucket and vice versa.
|
|
238
|
+
|
|
55
239
|
## API Reference
|
|
56
240
|
|
|
57
241
|
For complete API operations, see the API Reference documentation:
|
|
@@ -58,10 +58,10 @@ carries the quantity:
|
|
|
58
58
|
`subject` identifies _who_ consumed the subscription's entitlements on this
|
|
59
59
|
request — typically the API key's consumer name, the end-user id, or another
|
|
60
60
|
stable per-actor identifier. It is **not** the subscription id (use the
|
|
61
|
-
`subscription` field for that) and
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
`subscription` field for that) and does not route billing. Its purpose is to let
|
|
62
|
+
you break down usage within a subscription so you can see which key, user, or
|
|
63
|
+
agent drove the consumption — a single subscription will commonly emit events
|
|
64
|
+
with many different `subject` values. See
|
|
65
65
|
[Monetization Policy](./monetization-policy.md) for how usage is recorded.
|
|
66
66
|
|
|
67
67
|
:::
|
|
@@ -145,7 +145,10 @@ below it:
|
|
|
145
145
|
|
|
146
146
|
1. **Customer metadata** — `zuplo_max_payment_overdue_days` on the customer
|
|
147
147
|
2. **Plan metadata** — `zuplo_max_payment_overdue_days` on the plan
|
|
148
|
-
3. **
|
|
148
|
+
3. **Bucket configuration** —
|
|
149
|
+
[`maxPaymentOverdueDays`](./api-access.mdx#bucket-monetization-configuration)
|
|
150
|
+
on the bucket's monetization configuration
|
|
151
|
+
4. **Default** — `3` days
|
|
149
152
|
|
|
150
153
|
Set the value to `0` to block requests immediately when payment is overdue.
|
|
151
154
|
|
|
@@ -99,10 +99,9 @@ Save the returned `id` — you need it to publish and invite users.
|
|
|
99
99
|
|
|
100
100
|
:::note
|
|
101
101
|
|
|
102
|
-
The plan `id` is a 26-character ULID
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
require the `id`, not the `key`.
|
|
102
|
+
The plan `id` is a 26-character ULID. It's distinct from the human-friendly
|
|
103
|
+
`key` field. Use the `id` (not the `key`) when calling `/publish` and
|
|
104
|
+
`/plan-invites`.
|
|
106
105
|
|
|
107
106
|
:::
|
|
108
107
|
|
|
@@ -45,6 +45,15 @@ specifically Customers, Checkout Sessions, Customer Portal Sessions, Invoices,
|
|
|
45
45
|
and Tax Calculations. See
|
|
46
46
|
[What Zuplo creates in Stripe](#what-zuplo-creates-in-stripe) for the full list.
|
|
47
47
|
|
|
48
|
+
:::tip
|
|
49
|
+
|
|
50
|
+
To script the connection — for CI, infrastructure-as-code, or self-hosted
|
|
51
|
+
control planes — use the
|
|
52
|
+
[Stripe setup API endpoints](./api-access.mdx#stripe-setup-and-billing-readiness)
|
|
53
|
+
instead of the Portal flow.
|
|
54
|
+
|
|
55
|
+
:::
|
|
56
|
+
|
|
48
57
|
### Test mode vs. live mode
|
|
49
58
|
|
|
50
59
|
Connect with a Stripe **test** key (`sk_test_...`) first to validate your
|
|
@@ -67,8 +67,9 @@ curl -X POST https://dev.zuplo.com/v3/metering/{bucketId}/subscriptions \
|
|
|
67
67
|
-H "Authorization: Bearer {API_KEY}" \
|
|
68
68
|
-H "Content-Type: application/json" \
|
|
69
69
|
-d '{
|
|
70
|
-
"plan": { "key": "pro" },
|
|
71
|
-
"
|
|
70
|
+
"plan": { "key": "pro", "version": 1 },
|
|
71
|
+
"customerKey": "user_external_id",
|
|
72
|
+
"timing": "immediate"
|
|
72
73
|
}'
|
|
73
74
|
```
|
|
74
75
|
|
|
@@ -216,14 +217,15 @@ curl -X POST https://dev.zuplo.com/v3/metering/{bucketId}/subscriptions/{subscri
|
|
|
216
217
|
-H "Content-Type: application/json" \
|
|
217
218
|
-d '{
|
|
218
219
|
"timing": "immediate",
|
|
219
|
-
"plan": { "key": "enterprise" }
|
|
220
|
+
"plan": { "key": "enterprise", "version": 1 }
|
|
220
221
|
}'
|
|
221
222
|
```
|
|
222
223
|
|
|
223
224
|
`timing` accepts `"immediate"`, `"next_billing_cycle"`, or an RFC 3339
|
|
224
225
|
timestamp. Optional fields include `startingPhase`, `name`, `description`,
|
|
225
|
-
`metadata`, `alignment`, and `billingAnchor`.
|
|
226
|
-
|
|
226
|
+
`metadata`, `alignment`, and `billingAnchor`. The response includes both the
|
|
227
|
+
closed-out (`current`) and newly-started (`next`) subscriptions. To preview the
|
|
228
|
+
proration credit before committing, call
|
|
227
229
|
`POST /v3/metering/{bucketId}/subscriptions/{subscriptionId}/change/estimate-credit`
|
|
228
230
|
with the same body.
|
|
229
231
|
|
|
@@ -310,9 +312,7 @@ behavior does not apply.
|
|
|
310
312
|
curl -X POST https://dev.zuplo.com/v3/metering/{bucketId}/subscriptions/{subscriptionId}/cancel \
|
|
311
313
|
-H "Authorization: Bearer {API_KEY}" \
|
|
312
314
|
-H "Content-Type: application/json" \
|
|
313
|
-
-d '{
|
|
314
|
-
"timing": "next_billing_cycle"
|
|
315
|
-
}'
|
|
315
|
+
-d '{ "timing": "next_billing_cycle" }'
|
|
316
316
|
```
|
|
317
317
|
|
|
318
318
|
`timing` controls when the cancellation takes effect:
|
|
@@ -341,9 +341,10 @@ curl -X POST https://dev.zuplo.com/v3/metering/{bucketId}/subscriptions/{subscri
|
|
|
341
341
|
-H "Authorization: Bearer {API_KEY}"
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
This removes the pending cancellation. The subscription continues as normal.
|
|
345
|
-
|
|
346
|
-
|
|
344
|
+
This removes the pending cancellation. The subscription continues as normal.
|
|
345
|
+
|
|
346
|
+
If the subscription has already ended, create a new subscription rather than
|
|
347
|
+
restoring the old one.
|
|
347
348
|
|
|
348
349
|
## Subscriptions per customer
|
|
349
350
|
|
|
@@ -114,7 +114,9 @@ jobs:
|
|
|
114
114
|
run: npm install
|
|
115
115
|
|
|
116
116
|
- name: Deploy to Zuplo
|
|
117
|
-
run:
|
|
117
|
+
run:
|
|
118
|
+
npx zuplo deploy --api-key "$ZUPLO_API_KEY" --environment "${{
|
|
119
|
+
github.ref_name }}"
|
|
118
120
|
env:
|
|
119
121
|
ZUPLO_API_KEY: ${{ secrets.ZUPLO_API_KEY }}
|
|
120
122
|
```
|
|
@@ -171,8 +173,12 @@ jobs:
|
|
|
171
173
|
- name: Deploy to Zuplo
|
|
172
174
|
id: deploy
|
|
173
175
|
shell: bash
|
|
176
|
+
env:
|
|
177
|
+
# The PR's source branch — not the pull/<number>/merge ref that
|
|
178
|
+
# pull_request events check out
|
|
179
|
+
ENVIRONMENT: ${{ github.head_ref }}
|
|
174
180
|
run: |
|
|
175
|
-
OUTPUT=$(npx zuplo deploy --api-key "$ZUPLO_API_KEY" 2>&1)
|
|
181
|
+
OUTPUT=$(npx zuplo deploy --api-key "$ZUPLO_API_KEY" --environment "$ENVIRONMENT" 2>&1)
|
|
176
182
|
echo "$OUTPUT"
|
|
177
183
|
DEPLOYMENT_URL=$(echo "$OUTPUT" | grep -oP 'Deployed to \K(https://[^ ]+)')
|
|
178
184
|
echo "url=$DEPLOYMENT_URL" >> $GITHUB_OUTPUT
|
|
@@ -230,6 +236,18 @@ jobs:
|
|
|
230
236
|
--wait
|
|
231
237
|
```
|
|
232
238
|
|
|
239
|
+
:::caution
|
|
240
|
+
|
|
241
|
+
The deploy step passes `--environment` with the PR's source branch name
|
|
242
|
+
(`github.head_ref`). Workflows triggered by `pull_request` check out the PR
|
|
243
|
+
merge ref (`refs/pull/<number>/merge`), so without `--environment` the CLI names
|
|
244
|
+
the environment after that ref instead of your branch — and any other deploy of
|
|
245
|
+
the same branch creates a second environment with a different URL. See
|
|
246
|
+
[PR Preview Environments](./ci-cd-github/pr-preview-environments.mdx) for
|
|
247
|
+
details.
|
|
248
|
+
|
|
249
|
+
:::
|
|
250
|
+
|
|
233
251
|
### Secrets and environment variables
|
|
234
252
|
|
|
235
253
|
Store your Zuplo API key as a GitHub Actions secret:
|
|
@@ -10,8 +10,8 @@ tags:
|
|
|
10
10
|
|
|
11
11
|
Sometimes multiple types of authentication are needed on an API. For example, an
|
|
12
12
|
API could support JWT Authentication and API Key authentication or two different
|
|
13
|
-
OAuth providers (for example
|
|
14
|
-
Configuring multiple policies in Zuplo can be done in several ways.
|
|
13
|
+
OAuth providers (for example Microsoft Entra ID for employees and Auth0 for
|
|
14
|
+
partners). Configuring multiple policies in Zuplo can be done in several ways.
|
|
15
15
|
|
|
16
16
|
## JWT and API Key Authentication
|
|
17
17
|
|
|
@@ -15,7 +15,8 @@ this is an OpenAPI document used for routing.
|
|
|
15
15
|
You can use the Route Designer to build your routes, which will be creating an
|
|
16
16
|
OpenAPI document in the background for you (check it out in the **JSON View**).
|
|
17
17
|
|
|
18
|
-
You can also **import an OpenAPI** document by clicking the **
|
|
18
|
+
You can also **import an OpenAPI** document by clicking the **Import** button in
|
|
19
|
+
the Route Designer.
|
|
19
20
|
|
|
20
21
|

|
|
21
22
|
|
|
@@ -39,8 +40,12 @@ document and will keep your Zuplo settings intact, while overwriting everything
|
|
|
39
40
|
else from your imported OpenAPI docs. This creates a great workflow, whatever
|
|
40
41
|
toolset you use.
|
|
41
42
|
|
|
43
|
+
<ModalScreenshot>
|
|
44
|
+
|
|
42
45
|

|
|
43
46
|
|
|
47
|
+
</ModalScreenshot>
|
|
48
|
+
|
|
44
49
|
What's more, you can now have more confidence that your OpenAPI represents the
|
|
45
50
|
truth of your API implementation - because it now drives the configuration of
|
|
46
51
|
your gateway.
|
|
@@ -23,8 +23,12 @@ disconnect the project from Source Control.
|
|
|
23
23
|
Next create a new project in the correct account if moving accounts or with the
|
|
24
24
|
correct name. Choose the `Advanced` option on the new project dialog.
|
|
25
25
|
|
|
26
|
+
<ModalScreenshot>
|
|
27
|
+
|
|
26
28
|

|
|
27
29
|
|
|
30
|
+
</ModalScreenshot>
|
|
31
|
+
|
|
28
32
|
You should see a list of organizations and repositories - pick the source
|
|
29
33
|
repository you wanted to move and click **Create Project from repository**.
|
|
30
34
|
|
|
@@ -29,8 +29,12 @@ Open the **Settings** section of your project and select **Environment
|
|
|
29
29
|
Variables**. Create a new variable and name it `BACKEND_SECRET`. Set the value
|
|
30
30
|
to a secure, random value. Ensure that the value is marked as a secret.
|
|
31
31
|
|
|
32
|
+
<ModalScreenshot>
|
|
33
|
+
|
|
32
34
|

|
|
33
35
|
|
|
36
|
+
</ModalScreenshot>
|
|
37
|
+
|
|
34
38
|
### Step 2: Create a set header policy
|
|
35
39
|
|
|
36
40
|
Create a policy that sets the `BACKEND_SECRET` as a header on the request to
|
|
@@ -40,8 +44,12 @@ is sent to your backend.
|
|
|
40
44
|
Navigate to the route you want to secure and add a new policy. Select the **Add
|
|
41
45
|
or Set Request Headers** policy type and configure it as follows:
|
|
42
46
|
|
|
47
|
+
<ModalScreenshot>
|
|
48
|
+
|
|
43
49
|

|
|
44
50
|
|
|
51
|
+
</ModalScreenshot>
|
|
52
|
+
|
|
45
53
|
The configuration uses the environment variable via the `$env(BACKEND_SECRET)`
|
|
46
54
|
selector as shown below.
|
|
47
55
|
|
|
@@ -98,10 +106,10 @@ interested in using this option please contact us at `support@zuplo.com`.
|
|
|
98
106
|
Utilize the IAM controls provided by your Cloud host to secure inbound requests
|
|
99
107
|
and allow only authorized service principals access to your service.
|
|
100
108
|
|
|
101
|
-
- For Azure users, you can
|
|
109
|
+
- For Azure users, you can use the
|
|
102
110
|
[Upstream Azure AD Service Auth](../policies/upstream-azure-ad-service-auth-inbound.mdx)
|
|
103
|
-
policy. This uses Azure AD App registrations to
|
|
104
|
-
|
|
111
|
+
policy. This uses Microsoft Entra ID (formerly Azure AD) App registrations to
|
|
112
|
+
create a token that Zuplo sends with requests to Azure.
|
|
105
113
|
|
|
106
114
|
- For GCP users, you can use our
|
|
107
115
|
[Upstream GCP Service AUth](../policies/upstream-gcp-service-auth-inbound.mdx)
|
|
@@ -130,8 +130,12 @@ If you have an existing GitHub repository that contains a Zuplo project, you can
|
|
|
130
130
|
connect to that repository when you create a new project. Select **Import
|
|
131
131
|
existing project** then select your GitHub organization and repository.
|
|
132
132
|
|
|
133
|
+
<ModalScreenshot>
|
|
134
|
+
|
|
133
135
|

|
|
134
136
|
|
|
137
|
+
</ModalScreenshot>
|
|
138
|
+
|
|
135
139
|
## What's Included
|
|
136
140
|
|
|
137
141
|
With GitHub connected, you get:
|
|
@@ -226,8 +226,8 @@ period of inactivity is slow. Subsequent requests are fast.
|
|
|
226
226
|
|
|
227
227
|
### Analytics Dashboard
|
|
228
228
|
|
|
229
|
-
Zuplo's analytics dashboard
|
|
230
|
-
performance. Use it to:
|
|
229
|
+
Zuplo's analytics dashboard, in the **Observability** tab of your project,
|
|
230
|
+
provides at-a-glance visibility into your API's performance. Use it to:
|
|
231
231
|
|
|
232
232
|
- Identify slow endpoints by reviewing request latency data
|
|
233
233
|
- Filter by route, API key, or time period to isolate patterns
|
|
@@ -177,9 +177,9 @@ const response = await fetch("https://api.example.com/data", {
|
|
|
177
177
|
### Portal live logs
|
|
178
178
|
|
|
179
179
|
The Zuplo Portal provides real-time log viewing for deployed environments. Open
|
|
180
|
-
the
|
|
181
|
-
|
|
182
|
-
|
|
180
|
+
the **Observability** tab in your project — the **Logs** view opens by default —
|
|
181
|
+
then use the **Environment** filter to select the deployed environment and see
|
|
182
|
+
live request logs and any messages logged with `context.log`.
|
|
183
183
|
|
|
184
184
|
### Using context.log
|
|
185
185
|
|
package/docs/cli/deploy.mdx
CHANGED
|
@@ -122,6 +122,38 @@ zuplo deploy --project my-project
|
|
|
122
122
|
zuplo deploy --project my-project --environment my-env-name
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
+
### Deploying from CI/CD
|
|
126
|
+
|
|
127
|
+
Without `--environment`, the CLI names the environment after the current git
|
|
128
|
+
branch. CI systems usually check out a detached HEAD, in which case the CLI
|
|
129
|
+
resolves the branch from the remote branches that contain the checked-out
|
|
130
|
+
commit. Two cases break this inference:
|
|
131
|
+
|
|
132
|
+
- On GitHub Actions `pull_request` events, the checkout is the pull request
|
|
133
|
+
merge ref (`refs/pull/<number>/merge`) — a commit that doesn't exist on any
|
|
134
|
+
branch — so the environment is named after that ref instead of your branch.
|
|
135
|
+
- When the checked-out commit exists on more than one branch, the first match
|
|
136
|
+
wins, which may not be the branch that triggered the build.
|
|
137
|
+
|
|
138
|
+
Always pass `--environment` explicitly in CI so that every trigger deploys the
|
|
139
|
+
same, predictably named environment:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# GitHub Actions: github.head_ref is the source branch on pull_request
|
|
143
|
+
# events; github.ref_name is the branch on push events
|
|
144
|
+
zuplo deploy --project my-project --environment "$BRANCH_NAME"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Deploying the same environment name always updates the same environment and
|
|
148
|
+
keeps its URL stable across deploys. This matters whenever an external system
|
|
149
|
+
must match the URL exactly — an OIDC token audience, a webhook registration, or
|
|
150
|
+
an allowlist. Capture the URL from the deploy output (`Deployed to
|
|
151
|
+
https://...`) rather than constructing it from the branch name: the URL
|
|
152
|
+
hostname uses a normalized, truncated form of the environment name plus a
|
|
153
|
+
unique identifier. See
|
|
154
|
+
[Branch-Based Deployments](../articles/branch-based-deployments.mdx) for the
|
|
155
|
+
naming rules.
|
|
156
|
+
|
|
125
157
|
## Polling timeout
|
|
126
158
|
|
|
127
159
|
By default, the deploy command polls the status of the deployment every second
|