Conversation
- Add Go quickstart guide with stdlib, Gin, and Echo examples - Add Python quickstart guide with FastAPI, Flask, Django - Add Go cookbook: stdlib, Gin, Echo middleware recipes - Add Python cookbook: FastAPI rate limiting recipe All content uses Unkey v2 API only.
- Add Go and Python quickstart guides to Framework Guides - Add Go and Python cookbook recipes to Recipes section - Remove duplicate 5-minutes quickstart file
- Add Go code examples to /quickstart/quickstart.mdx for key creation and verification - Reorganize cookbook recipes into subsections: TypeScript, Go, Python, General - Keep existing TypeScript and Python examples in quickstart
- Fix int to string conversion in go-gin-middleware (use strconv) - Fix middleware composition in go-stdlib-middleware - Fix wait calculation in python-fastapi-ratelimit (use total_seconds) - Fix headers attachment in python-fastapi-ratelimit (use JSONResponse) - Fix nil pointer dereference in quickstart/go - Fix unsafe type assertion in quickstart/go
- Use verify_key_async in Python async route - Add nil check for result.Code in Go quickstart
- Fix GetUnkeyResult type assertion in go-gin-middleware - Fix imports in python-fastapi-ratelimit (add JSONResponse, remove unused timedelta) - Update basic rate limit example to use async API with context manager - Add missing os import in Django settings snippet
- Fix RequirePermission in go-echo-middleware with safe type assertion - Fix GetUnkeyResult in go-echo-middleware with safe type assertion - Fix RequirePermission in go-gin-middleware with safe type assertion
- Replace outdated /apis/features/analytics.mdx with minimal reference page - Remove analytics from API Keys sidebar in docs.json - Add redirect from /apis/features/analytics to /analytics/overview
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
📝 WalkthroughWalkthroughThe PR updates documentation infrastructure by rewriting the Analytics feature documentation to focus on SQL-centric querying, adding comprehensive Go and Python API authentication guides with middleware examples for multiple frameworks (stdlib, Gin, Echo), updating the cookbook index and navigation configuration, adding Go code examples to the quickstart, and replacing the Mintlify build tool with Mint. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
- Store pointer to struct in context (not value) for type assertion compatibility - Add checked type assertion in RequireRole with proper error handling
…ocs-python-go-sdks
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (1)
web/apps/docs/quickstart/apis/python.mdx (1)
53-69: Use async SDK methods for FastAPI handlers.The code correctly uses
async defbut blocks the event loop with synchronousverify_key()calls. The Unkey Python SDK supports async operations viaverify_key_async(), which should be used in async handlers. Switch toasync with Unkey(...)andawait verify_key_async(key=...)to maintain non-blocking behavior.Recommended async pattern
`@app.get`("/api/protected") async def protected_route(x_api_key: str = Header(..., alias="X-API-Key")): - with Unkey(bearer_auth=os.environ["UNKEY_ROOT_KEY"]) as unkey: - res = unkey.keys.verify_key(request={"key": x_api_key}) + async with Unkey(bearer_auth=os.environ["UNKEY_ROOT_KEY"]) as unkey: + res = await unkey.keys.verify_key_async(key=x_api_key) result = res.data🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/apps/docs/quickstart/apis/python.mdx` around lines 53 - 69, The protected_route handler is using synchronous SDK calls which block the event loop; switch to the async SDK pattern by using async with Unkey(bearer_auth=os.environ["UNKEY_ROOT_KEY"]) as unkey and await unkey.keys.verify_key_async(key=x_api_key) (keep the Header alias and x_api_key param), then use the returned result (result.valid, result.code, result.key_id, result.remaining) as before and raise HTTPException based on result.code; this ensures the FastAPI async handler stays non-blocking.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/apps/docs/apis/features/analytics.mdx`:
- Around line 32-55: The "Per API Metrics" and "Per Key Metrics" sections
currently list identical bullets, which is confusing; update the "Per API
Metrics" and/or "Per Key Metrics" sections under the headings "Per API Metrics"
and "Per Key Metrics" so they either (a) merge into a single shared "Metrics"
list (removing the duplicate section) or (b) provide distinct metrics for each
scope (e.g., per-API: "Active API endpoints", "Average latency per endpoint",
"Error rate by endpoint"; per-key: "Usage per key", "Monthly quota", "Last seen
timestamp"), and ensure the <Frame caption="Per API Analytics"> example image
and captions reflect the chosen change.
In `@web/apps/docs/cookbook/go-echo-middleware.mdx`:
- Around line 186-193: The /profile handler dereferences result.KeyID (from
GetUnkeyResult) without a nil check, risking a nil pointer panic; update the
api.GET("/profile"...) handler to check if result.KeyID is nil before
dereferencing and handle the nil case (e.g., omit "key_id", return null, or use
a safe default) when building the JSON response so that "key_id" is only
dereferenced when result.KeyID != nil.
- Around line 276-288: The example dereferences result.KeyID without checking
it; update the handler that calls GetUnkeyResult (used with
UnkeyAuthWithConfig/AuthConfig{Optional: true}) to ensure result.KeyID is
non-nil before using *result.KeyID — e.g., only include "key_id" in the JSON
when result != nil && result.KeyID != nil, otherwise fallback to the anonymous
response; this mirrors the safe nil-check pattern used in the main examples.
In `@web/apps/docs/cookbook/go-gin-middleware.mdx`:
- Around line 217-219: Update the section heading currently written as "## Rate
Limiting Integration" to use a hyphenated compound adjective, e.g., change the
heading string to "## Rate-Limiting Integration" (or use a non-breaking hyphen
"Rate‑Limiting Integration") so the compound adjective is correctly hyphenated
in the document.
In `@web/apps/docs/cookbook/go-stdlib-middleware.mdx`:
- Around line 60-98: The middleware currently sets Content-Type globally and
returns plain JSON errors; update the middleware returned by the outer function
so it does NOT set w.Header().Set("Content-Type", "application/json") at the
top, and instead set that header only when writing error responses; replace each
plain map error payload (e.g., the Missing API key branch and the VerifyKey
error branch that call json.NewEncoder(w).Encode(...)) with an RFC 7807-style
problem+json envelope (wrap under an "error" or "meta.error" envelope per v2
spec) containing fields title, detail, status, type and optional errors array,
and ensure the status code (http.StatusUnauthorized,
http.StatusServiceUnavailable, etc.) matches the status field; update the blocks
around options.headerName/options.required and the unkeyClient.Keys.VerifyKey
error handling to encode and write that RFC7807 payload while setting
Content-Type to "application/problem+json" (or "application/json" per spec) only
for those error responses.
In `@web/apps/docs/package.json`:
- Around line 6-11: The package.json devDependencies references a non-existent
mint version ("mint": "4.2.314") which prevents installing the Mintlify CLI;
update the "mint" entry under devDependencies to a valid published version
(e.g., a 4.2.2xx release) or run npm update mint to set the latest secure
release, and ensure the "dev" script ("dev": "mint dev") continues to work with
the chosen version; modify the "mint" value in package.json accordingly and run
npm install to verify resolution.
In `@web/apps/docs/quickstart/quickstart.mdx`:
- Around line 182-201: The verify example incorrectly reads fields from
V2KeysVerifyKeyResponseBody; update the code to read from the nested Data field
(e.g., use res.V2KeysVerifyKeyResponseBody.Data), reference Valid and Code
directly from that Data (Code is a V2KeysVerifyKeyResponseDataCode value, not a
pointer, so do not dereference), and use the correct KeyId field name (KeyId,
not KeyID) when printing; adjust any local variables (e.g., result) to point to
the Data object and fix uses of Code and KeyId accordingly.
---
Nitpick comments:
In `@web/apps/docs/quickstart/apis/python.mdx`:
- Around line 53-69: The protected_route handler is using synchronous SDK calls
which block the event loop; switch to the async SDK pattern by using async with
Unkey(bearer_auth=os.environ["UNKEY_ROOT_KEY"]) as unkey and await
unkey.keys.verify_key_async(key=x_api_key) (keep the Header alias and x_api_key
param), then use the returned result (result.valid, result.code, result.key_id,
result.remaining) as before and raise HTTPException based on result.code; this
ensures the FastAPI async handler stays non-blocking.
| ## Dashboard Analytics | ||
|
|
||
| Query keys sorted by verification count to identify power users or potential abuse. | ||
| ### Per API Metrics | ||
|
|
||
| ### Tracking feature adoption | ||
| The dashboard shows aggregate metrics for each API: | ||
|
|
||
| Tag verifications with feature names to see which features are most used: | ||
| - **Total Verifications**: Total number of API key verifications | ||
| - **Success Rate**: Percentage of successful verifications | ||
| - **Rate Limit Exceeded**: Number of rate limit exceeded errors | ||
| - **Invalid Key**: Number of invalid key errors | ||
|
|
||
| ```typescript | ||
| const tags = data.meta?.features ?? []; | ||
| // tags: ["feature=export", "feature=bulk-upload"] | ||
| ``` | ||
| <Frame caption="Per API Analytics"> | ||
| <img src="/images/per-api-analytics.png" alt="Per API Analytics"/> | ||
| </Frame> | ||
|
|
||
| ### Billing and usage reports | ||
| ### Per Key Metrics | ||
|
|
||
| Combine verification counts with custom costs to generate accurate usage reports for billing. | ||
| The dashboard shows aggregate metrics for each API key: | ||
|
|
||
| ## Next steps | ||
| - **Total Verifications**: Total number of API key verifications | ||
| - **Success Rate**: Percentage of successful verifications | ||
| - **Rate Limit Exceeded**: Number of rate limit exceeded errors | ||
| - **Invalid Key**: Number of invalid key errors | ||
|
|
There was a problem hiding this comment.
Per‑API and Per‑Key metric sections are identical.
Both lists repeat the same bullets; readers will expect distinct per‑API vs per‑key details. Consider merging into one shared list or adding differentiating metrics for each section.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/apps/docs/apis/features/analytics.mdx` around lines 32 - 55, The "Per API
Metrics" and "Per Key Metrics" sections currently list identical bullets, which
is confusing; update the "Per API Metrics" and/or "Per Key Metrics" sections
under the headings "Per API Metrics" and "Per Key Metrics" so they either (a)
merge into a single shared "Metrics" list (removing the duplicate section) or
(b) provide distinct metrics for each scope (e.g., per-API: "Active API
endpoints", "Average latency per endpoint", "Error rate by endpoint"; per-key:
"Usage per key", "Monthly quota", "Last seen timestamp"), and ensure the <Frame
caption="Per API Analytics"> example image and captions reflect the chosen
change.
| api.GET("/profile", func(c echo.Context) error { | ||
| result := GetUnkeyResult(c) | ||
| return c.JSON(http.StatusOK, map[string]any{ | ||
| "key_id": *result.KeyID, | ||
| "permissions": result.Permissions, | ||
| "roles": result.Roles, | ||
| }) | ||
| }) |
There was a problem hiding this comment.
Same nil pointer dereference pattern on KeyID.
Line 189 has the same issue as the /data endpoint - dereferencing result.KeyID without a nil check.
🛡️ Proposed fix
api.GET("/profile", func(c echo.Context) error {
result := GetUnkeyResult(c)
+ keyID := ""
+ if result.KeyID != nil {
+ keyID = *result.KeyID
+ }
return c.JSON(http.StatusOK, map[string]any{
- "key_id": *result.KeyID,
+ "key_id": keyID,
"permissions": result.Permissions,
"roles": result.Roles,
})
})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| api.GET("/profile", func(c echo.Context) error { | |
| result := GetUnkeyResult(c) | |
| return c.JSON(http.StatusOK, map[string]any{ | |
| "key_id": *result.KeyID, | |
| "permissions": result.Permissions, | |
| "roles": result.Roles, | |
| }) | |
| }) | |
| api.GET("/profile", func(c echo.Context) error { | |
| result := GetUnkeyResult(c) | |
| keyID := "" | |
| if result.KeyID != nil { | |
| keyID = *result.KeyID | |
| } | |
| return c.JSON(http.StatusOK, map[string]any{ | |
| "key_id": keyID, | |
| "permissions": result.Permissions, | |
| "roles": result.Roles, | |
| }) | |
| }) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/apps/docs/cookbook/go-echo-middleware.mdx` around lines 186 - 193, The
/profile handler dereferences result.KeyID (from GetUnkeyResult) without a nil
check, risking a nil pointer panic; update the api.GET("/profile"...) handler to
check if result.KeyID is nil before dereferencing and handle the nil case (e.g.,
omit "key_id", return null, or use a safe default) when building the JSON
response so that "key_id" is only dereferenced when result.KeyID != nil.
| e.GET("/api/public", func(c echo.Context) error { | ||
| result := GetUnkeyResult(c) | ||
| if result != nil { | ||
| return c.JSON(http.StatusOK, map[string]any{ | ||
| "message": "Authenticated", | ||
| "key_id": *result.KeyID, | ||
| }) | ||
| } | ||
| return c.JSON(http.StatusOK, map[string]string{ | ||
| "message": "Anonymous", | ||
| }) | ||
| }, UnkeyAuthWithConfig(AuthConfig{Optional: true})) | ||
| ``` |
There was a problem hiding this comment.
Same nil pointer dereference in custom config example.
Line 281 dereferences result.KeyID without a nil check, consistent with the pattern in the main examples. Consider adding a nil check for completeness of the documentation example.
🛡️ Proposed fix
// Usage with custom config
e.GET("/api/public", func(c echo.Context) error {
result := GetUnkeyResult(c)
if result != nil {
+ keyID := ""
+ if result.KeyID != nil {
+ keyID = *result.KeyID
+ }
return c.JSON(http.StatusOK, map[string]any{
"message": "Authenticated",
- "key_id": *result.KeyID,
+ "key_id": keyID,
})
}
return c.JSON(http.StatusOK, map[string]string{
"message": "Anonymous",
})
}, UnkeyAuthWithConfig(AuthConfig{Optional: true}))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| e.GET("/api/public", func(c echo.Context) error { | |
| result := GetUnkeyResult(c) | |
| if result != nil { | |
| return c.JSON(http.StatusOK, map[string]any{ | |
| "message": "Authenticated", | |
| "key_id": *result.KeyID, | |
| }) | |
| } | |
| return c.JSON(http.StatusOK, map[string]string{ | |
| "message": "Anonymous", | |
| }) | |
| }, UnkeyAuthWithConfig(AuthConfig{Optional: true})) | |
| ``` | |
| e.GET("/api/public", func(c echo.Context) error { | |
| result := GetUnkeyResult(c) | |
| if result != nil { | |
| keyID := "" | |
| if result.KeyID != nil { | |
| keyID = *result.KeyID | |
| } | |
| return c.JSON(http.StatusOK, map[string]any{ | |
| "message": "Authenticated", | |
| "key_id": keyID, | |
| }) | |
| } | |
| return c.JSON(http.StatusOK, map[string]string{ | |
| "message": "Anonymous", | |
| }) | |
| }, UnkeyAuthWithConfig(AuthConfig{Optional: true})) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/apps/docs/cookbook/go-echo-middleware.mdx` around lines 276 - 288, The
example dereferences result.KeyID without checking it; update the handler that
calls GetUnkeyResult (used with UnkeyAuthWithConfig/AuthConfig{Optional: true})
to ensure result.KeyID is non-nil before using *result.KeyID — e.g., only
include "key_id" in the JSON when result != nil && result.KeyID != nil,
otherwise fallback to the anonymous response; this mirrors the safe nil-check
pattern used in the main examples.
| ## Rate Limiting Integration | ||
|
|
||
| Combine with Unkey's rate limiting: |
There was a problem hiding this comment.
Hyphenate the compound adjective in the heading.
LanguageTool flagged this; consider “Rate‑Limiting Integration”.
Suggested edit
-## Rate Limiting Integration
+## Rate-Limiting Integration📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## Rate Limiting Integration | |
| Combine with Unkey's rate limiting: | |
| ## Rate-Limiting Integration | |
| Combine with Unkey's rate limiting: |
🧰 Tools
🪛 LanguageTool
[uncategorized] ~217-~217: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... }) } r.Run(":8080") } ``` ## Rate Limiting Integration Combine with Unkey's rate ...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/apps/docs/cookbook/go-gin-middleware.mdx` around lines 217 - 219, Update
the section heading currently written as "## Rate Limiting Integration" to use a
hyphenated compound adjective, e.g., change the heading string to "##
Rate-Limiting Integration" (or use a non-breaking hyphen "Rate‑Limiting
Integration") so the compound adjective is correctly hyphenated in the document.
| return func(next http.Handler) http.Handler { | ||
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| w.Header().Set("Content-Type", "application/json") | ||
|
|
||
| // Extract API key | ||
| authHeader := r.Header.Get(options.headerName) | ||
| if authHeader == "" { | ||
| if options.required { | ||
| w.WriteHeader(http.StatusUnauthorized) | ||
| json.NewEncoder(w).Encode(map[string]string{ | ||
| "error": "Missing API key", | ||
| "code": "MISSING_KEY", | ||
| }) | ||
| return | ||
| } | ||
| // Auth not required, continue without verification | ||
| next.ServeHTTP(w, r) | ||
| return | ||
| } | ||
|
|
||
| apiKey := strings.TrimPrefix(authHeader, options.prefix) | ||
|
|
||
| // Verify with Unkey | ||
| ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) | ||
| defer cancel() | ||
|
|
||
| res, err := unkeyClient.Keys.VerifyKey(ctx, components.V2KeysVerifyKeyRequestBody{ | ||
| Key: apiKey, | ||
| }) | ||
|
|
||
| if err != nil { | ||
| w.WriteHeader(http.StatusServiceUnavailable) | ||
| json.NewEncoder(w).Encode(map[string]string{ | ||
| "error": "Verification service unavailable", | ||
| "code": "SERVICE_ERROR", | ||
| "message": err.Error(), | ||
| }) | ||
| return | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check if the file exists and read the relevant section
cat -n web/apps/docs/cookbook/go-stdlib-middleware.mdx | head -100Repository: unkeyed/unkey
Length of output: 3635
🏁 Script executed:
# Search for how error responses are documented in other middleware examples
rg -n "application/json|application/problem\+json" web/apps/docs/cookbook -A 2 -B 2Repository: unkeyed/unkey
Length of output: 535
🏁 Script executed:
# Check if there are other error response examples in the docs
rg -n "WriteHeader|Encode.*error" web/apps/docs/cookbook -A 1 -B 1Repository: unkeyed/unkey
Length of output: 1511
🏁 Script executed:
# Check if there are any RFC 7807 or application/problem+json examples in the docs or SDK
rg -i "problem\+json|rfc.*7807" web/apps/docs -A 2 -B 2Repository: unkeyed/unkey
Length of output: 1970
🏁 Script executed:
# Look for error response patterns in OpenAPI specs
fd -e yaml -e json . "web/apps/docs" | xargs grep -l "error" | head -5Repository: unkeyed/unkey
Length of output: 80
🏁 Script executed:
# Check the Go SDK to see how Unkey errors are typically structured
fd -n "error" "sdks/api/go" | head -10Repository: unkeyed/unkey
Length of output: 287
🏁 Script executed:
# Get the v2 errors documentation to see the RFC 7807 format
head -150 web/apps/docs/api-reference/v2/errors.mdxRepository: unkeyed/unkey
Length of output: 3988
Update middleware error responses to match v2 API specification.
The middleware example has two issues:
-
Content-Type header placement: Setting it globally can override handlers returning non-JSON. Move it into error response handlers only.
-
Error response format: The example uses a plain JSON structure, but Unkey v2 requires RFC 7807 format with a
meta/errorenvelope. Error responses should includetitle,detail,status,type, and optionallyerrorsarray.
Corrected implementation
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
+ writeError := func(status int, title, detail string) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(status)
+ json.NewEncoder(w).Encode(map[string]any{
+ "meta": map[string]string{
+ "requestId": r.Header.Get("x-request-id"),
+ },
+ "error": map[string]any{
+ "title": title,
+ "detail": detail,
+ "status": status,
+ "type": "https://unkey.com/docs/errors/" + strings.ToLower(strings.ReplaceAll(title, " ", "-")),
+ },
+ })
+ }
// Extract API key
authHeader := r.Header.Get(options.headerName)
if authHeader == "" {
if options.required {
- w.WriteHeader(http.StatusUnauthorized)
- json.NewEncoder(w).Encode(map[string]string{
- "error": "Missing API key",
- "code": "MISSING_KEY",
- })
+ writeError(http.StatusUnauthorized, "Unauthorized", "Missing API key")
return
}
// Auth not required, continue without verification
next.ServeHTTP(w, r)
return
}
if err != nil {
- w.WriteHeader(http.StatusServiceUnavailable)
- json.NewEncoder(w).Encode(map[string]string{
- "error": "Verification service unavailable",
- "code": "SERVICE_ERROR",
- "message": err.Error(),
- })
+ writeError(http.StatusServiceUnavailable, "Service Unavailable", "Verification service unavailable")
return
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/apps/docs/cookbook/go-stdlib-middleware.mdx` around lines 60 - 98, The
middleware currently sets Content-Type globally and returns plain JSON errors;
update the middleware returned by the outer function so it does NOT set
w.Header().Set("Content-Type", "application/json") at the top, and instead set
that header only when writing error responses; replace each plain map error
payload (e.g., the Missing API key branch and the VerifyKey error branch that
call json.NewEncoder(w).Encode(...)) with an RFC 7807-style problem+json
envelope (wrap under an "error" or "meta.error" envelope per v2 spec) containing
fields title, detail, status, type and optional errors array, and ensure the
status code (http.StatusUnauthorized, http.StatusServiceUnavailable, etc.)
matches the status field; update the blocks around
options.headerName/options.required and the unkeyClient.Keys.VerifyKey error
handling to encode and write that RFC7807 payload while setting Content-Type to
"application/problem+json" (or "application/json" per spec) only for those error
responses.
| "dev": "mint dev" | ||
| }, | ||
| "keywords": [], | ||
| "author": "Andreas Thomas & James Perkins", | ||
| "devDependencies": { | ||
| "mintlify": "4.2.314" | ||
| "mint": "4.2.314" |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Mintlify CLI npm package mint
💡 Result:
- Mintlify CLI npm package:
mint(global CLI command:mint) on npm. Install:npm i -g mint(or run once withnpx mint dev). [1][2] - Common usage: from a Mintlify docs repo (has
docs.json), runmint devto preview locally (defaulthttp://localhost:3000, configurable via--port). [1][2] - Update CLI:
mint update. [1][2] - Troubleshooting note: If you still have the old/other global package
mintlifyinstalled, Mintlify recommends uninstalling it and reinstallingmint. [2] - Security note (historical): Mintlify reported a brief npm dependency supply-chain exposure on Nov 24, 2025 and recommends updating to a secure version (they note 4.2.210 as the secure publish at the time). [3]
Sources: [1] npm: mint package page, [2] Mintlify docs: CLI installation, [3] Mintlify blog post on SHA1-Hulud impact.
🌐 Web query:
mint npm package version 4.2.314
💡 Result:
I couldn’t find any evidence that mint (the Mintlify CLI on npm) has a published version 4.2.314.
Third-party package indexes that track npm releases show the latest mint version in the 4.2.2xx–4.2.2xx range (e.g., 4.2.280 on Snyk and 4.2.249 on Socket), not 4.2.314. [1] [2]
To verify from your environment / registry directly:
npm view mint versions --json | jq -r '.[]' | grep -F '4.2.314' || echo "not found"
# or
npm view mint@4.2.314 versionSources: Snyk package page for mint (latest shown: 4.2.280) [1]; Socket package page for mint (version shown: 4.2.249) [2].
🌐 Web query:
Mintlify CLI documentation official
💡 Result:
Official Mintlify CLI docs (Mintlify Docs):
- Install the CLI: prerequisites, install, local preview, ports,
mint newflags, and updating the CLI. [1] - Quickstart (uses the CLI): end-to-end flow (install CLI → clone repo →
mint dev→ push to deploy). [2]
Key commands from the official docs:
- Install:
npm i -g mint(Node.js v20.17.0+ required) [1] - Local preview:
mint dev(ornpx mint dev) [1] - Update CLI:
mint update(or reinstall latest) [1]
Sources: [1] (mintlify.com) [2] (mintlify.com)
Citations:
- 1: https://www.mintlify.com/docs/installation?utm_source=openai
- 2: https://www.mintlify.com/docs/es/quickstart?utm_source=openai
Update mint dependency to a valid version.
The npm package mint is the correct Mintlify CLI and mint dev is the correct command. However, version 4.2.314 does not appear to exist in the npm registry (latest available versions are in the 4.2.2xx range, e.g., 4.2.280). Update the version in devDependencies to a valid release or use npm update mint to install the latest secure version.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/apps/docs/package.json` around lines 6 - 11, The package.json
devDependencies references a non-existent mint version ("mint": "4.2.314") which
prevents installing the Mintlify CLI; update the "mint" entry under
devDependencies to a valid published version (e.g., a 4.2.2xx release) or run
npm update mint to set the latest secure release, and ensure the "dev" script
("dev": "mint dev") continues to work with the chosen version; modify the "mint"
value in package.json accordingly and run npm install to verify resolution.
| res, err := client.Keys.VerifyKey(ctx, components.V2KeysVerifyKeyRequestBody{ | ||
| Key: "THE_KEY_FROM_STEP_3", | ||
| }) | ||
|
|
||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| result := res.V2KeysVerifyKeyResponseBody | ||
|
|
||
| if !result.Valid { | ||
| code := "unknown" | ||
| if result.Code != nil { | ||
| code = *result.Code | ||
| } | ||
| fmt.Println("Denied:", code) | ||
| return | ||
| } | ||
|
|
||
| fmt.Println("Key ID:", result.KeyID) |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Unkey Go SDK V2KeysVerifyKeyResponseBody structure
💡 Result:
In the Unkey Go SDK (v2), V2KeysVerifyKeyResponseBody is:
type V2KeysVerifyKeyResponseBody struct {
Data V2KeysVerifyKeyResponseData `json:"data"`
Meta Meta `json:"meta"` // Meta has requestId
}[1]
Where data (V2KeysVerifyKeyResponseData) is:
type V2KeysVerifyKeyResponseData struct {
Code V2KeysVerifyKeyResponseDataCode `json:"code"` // e.g. VALID, NOT_FOUND, FORBIDDEN, ...
Credits *int32 `json:"credits,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
Expires int64 `json:"expires,omitempty"` // unix ms
Identity *Identity `json:"identity,omitempty"`
KeyId string `json:"keyId,omitempty"`
Meta map[string]any `json:"meta,omitempty"`
Name string `json:"name,omitempty"`
Permissions []string `json:"permissions,omitempty"`
Ratelimits []VerifyKeyRatelimitData `json:"ratelimits,omitempty"`
Roles []string `json:"roles,omitempty"`
Valid bool `json:"valid"`
}[1]
And meta is:
type Meta struct {
RequestId string `json:"requestId"`
}[1]
Note: the endpoint returns HTTP 200 even for invalid keys—check data.valid and/or data.code. [2]
Sources: [1] [2]
Go verify example requires .Data field access and field name corrections.
The current code accesses V2KeysVerifyKeyResponseBody fields directly, but the response structure wraps the data in a Data field. The code will not compile as written because:
Valid,Code, andKeyIdexist onV2KeysVerifyKeyResponseBody.Data, not on the body itselfCodeis of typeV2KeysVerifyKeyResponseDataCode(not a pointer), so dereferencing it will fail- The field name is
KeyId, notKeyID
- result := res.V2KeysVerifyKeyResponseBody
-
+ result := res.V2KeysVerifyKeyResponseBody.Data
+
if !result.Valid {
code := "unknown"
- if result.Code != nil {
- code = *result.Code
- }
+ code = string(result.Code)
fmt.Println("Denied:", code)
return
}
- fmt.Println("Key ID:", result.KeyID)
+ fmt.Println("Key ID:", result.KeyId)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/apps/docs/quickstart/quickstart.mdx` around lines 182 - 201, The verify
example incorrectly reads fields from V2KeysVerifyKeyResponseBody; update the
code to read from the nested Data field (e.g., use
res.V2KeysVerifyKeyResponseBody.Data), reference Valid and Code directly from
that Data (Code is a V2KeysVerifyKeyResponseDataCode value, not a pointer, so do
not dereference), and use the correct KeyId field name (KeyId, not KeyID) when
printing; adjust any local variables (e.g., result) to point to the Data object
and fix uses of Code and KeyId accordingly.


What does this PR do?
Adding some guides to cookbooks and also adding Go into the Quickstart.
Fixes # (issue)
If there is not an issue for this, please create one first. This is used to tracking purposes and also helps us understand why this PR exists
Type of change
How should this be tested?
Checklist
Required
pnpm buildpnpm fmtmake fmton/godirectoryconsole.logsgit pull origin mainAppreciated