Skip to content

Split openapi.json into per-domain OpenAPI specs#98

Closed
recoup-coding-agent wants to merge 1 commit intomainfrom
feat/split-openapi-specs
Closed

Split openapi.json into per-domain OpenAPI specs#98
recoup-coding-agent wants to merge 1 commit intomainfrom
feat/split-openapi-specs

Conversation

@recoup-coding-agent
Copy link
Copy Markdown
Collaborator

@recoup-coding-agent recoup-coding-agent commented Apr 2, 2026

Summary

  • Splits the monolithic api-reference/openapi.json (10K+ LOC, 69 endpoints, 227 schemas) into 9 domain-specific spec files under api-reference/openapi/
  • Each file is a standalone valid OpenAPI 3.1 spec: chats.json, tasks.json, accounts.json, admins.json, artists.json, social.json, content.json, sandboxes.json, general.json
  • Updates docs.json to use Mintlify's openapi.source + directory config for auto-generated API pages
  • Removes all frontmatter-only MDX files that are now redundant (Mintlify auto-generates from specs)
  • Schemas are duplicated per file as required (Mintlify only supports internal $ref)

Test plan

  • Verify docs.json is valid Mintlify config
  • Run npx mintlify@latest dev locally to confirm all endpoints render
  • Check Mintlify deployment preview for correct navigation and page generation
  • Verify Guides tab links still resolve

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Consolidated API reference documentation into centralized OpenAPI specification files organized by domain for improved structure and clarity.

Replace the single 10K+ line openapi.json with 9 domain-specific spec
files (chats, tasks, accounts, admins, artists, social, content,
sandboxes, general) under api-reference/openapi/. Each file is a
standalone valid OpenAPI 3.1 spec with its own paths, schemas, and
security definitions.

Update docs.json to use Mintlify's openapi.source + directory config
for auto-generated API pages, removing all handwritten frontmatter-only
MDX files that are now redundant.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

This PR migrates API reference documentation from individual MDX files with frontmatter metadata to centralized, per-domain OpenAPI 3.1 JSON specification files. The change removes frontmatter headers from 100+ existing MDX pages and introduces nine new OpenAPI spec files covering accounts, admins, artists, chats, content, general, sandboxes, social, and tasks APIs. The docs.json navigation configuration was updated to reference these OpenAPI sources instead of explicit page arrays.

Changes

Cohort / File(s) Summary
MDX Frontmatter Removal
api-reference/accounts/*, api-reference/admins/*, api-reference/artist/*, api-reference/artists/*, api-reference/chat/*, api-reference/comments/*, api-reference/connectors/*, api-reference/content/*, api-reference/content-agent/*, api-reference/fans/*, api-reference/image/*, api-reference/instagram/*, api-reference/notifications/*, api-reference/organizations/*, api-reference/post/*, api-reference/posts/*, api-reference/pulses/*, api-reference/sandboxes/*, api-reference/segment/*, api-reference/social/*, api-reference/songs/*, api-reference/spotify/*, api-reference/subscriptions/*, api-reference/tasks/*, api-reference/transcribe/*, api-reference/workspaces/*, api-reference/x/*
Removed YAML frontmatter (title and openapi fields) from ~120 MDX documentation files across all API reference sections. These pages are now auto-generated from OpenAPI specs rather than manually maintained.
New OpenAPI Specifications
api-reference/openapi/accounts.json, api-reference/openapi/admins.json, api-reference/openapi/artists.json, api-reference/openapi/chats.json, api-reference/openapi/content.json, api-reference/openapi/general.json, api-reference/openapi/sandboxes.json, api-reference/openapi/social.json, api-reference/openapi/tasks.json
Added nine comprehensive OpenAPI 3.1 specification files defining consolidated API endpoints per domain. Specs include full path definitions, request/response schemas, security schemes, server configuration, and component schemas. Total: ~12,000 lines of structured API documentation.
Configuration Updates
docs.json, api-reference/introduction.mdx
Updated navigation configuration to replace explicit pages arrays with openapi source references and target directories for Chat, Tasks, Accounts, Admins, Artists, Social, Content, Sandboxes, and General APIs. Updated introduction card to reference per-domain specifications instead of single spec file.

Sequence Diagram(s)

No sequence diagrams generated. The changes represent a documentation architecture migration (configuration and schema reorganization) rather than a functional control flow modification involving multiple runtime components.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • sweetmantech

🐰 Hop along this migration, dear friend,
From scattered pages to specs that blend—
OpenAPI JSONs now lead the way,
As docs unite in organized display!
A grand refactor, tidy and bright, 🎉
Where fragments converge into single sight.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Split openapi.json into per-domain OpenAPI specs' directly and clearly describes the main structural refactoring: consolidating a monolithic OpenAPI spec into nine domain-specific files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/split-openapi-specs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api-reference/introduction.mdx`:
- Around line 10-15: The Card component's href currently points to the wrong
repository (sweetmantech/docs); update the Card with title "View OpenAPI
Specifications" to point at the current repository's OpenAPI directory by
changing the href prop to the recoupable/docs location (e.g., the GitHub URL for
recoupable/docs/tree/main/api-reference/openapi or a relative path like
/api-reference/openapi), so the Card's link targets the correct repo; modify the
href prop on the Card element accordingly.

In `@api-reference/openapi/artists.json`:
- Around line 16-20: The root OpenAPI "security" declaration currently lists
only "apiKeyAuth" but omits the "bearerAuth" scheme; update the root security
array to include both "apiKeyAuth" and "bearerAuth" so endpoints like GET
/api/artists that allow "API key or Bearer token" are correctly represented;
locate the top-level "security" block (the snippet containing "apiKeyAuth") and
add an entry for "bearerAuth" that matches the name defined under
components.securitySchemes ("bearerAuth").
- Around line 140-158: Update the OpenAPI parameter schemas for the "page" and
"limit" query parameters in this artists.json to enforce 1-based positive
pagination: add "minimum": 1 to each "page" schema and to each "limit" schema
(both those with "maximum": 100 and the one without a max) across all six
endpoint definitions where "page" and "limit" appear so the schema matches the
descriptions and prevents zero/negative values.

In `@api-reference/openapi/content.json`:
- Around line 1063-1067: The OpenAPI spec references the security requirement
callbackSecret for the /api/content-agent/callback endpoint but never declares
it; add a new security scheme entry named callbackSecret under
components.securitySchemes (similar to existing bearerAuth/apiKeyAuth) that
matches the intended auth type (e.g., apiKey in header or http bearer) so the
security requirement resolves; update components.securitySchemes to include
callbackSecret and ensure its name/type/in parameter align with how the callback
endpoint expects the secret.
- Around line 16-20: The endpoint definition for /api/content-agent/{platform}
is inheriting the file-level "apiKeyAuth" security requirement; update the
operation's security to override this by setting "security": [] in the operation
object for the /api/content-agent/{platform} path so that the API-key
requirement is cleared and consumers see no apiKeyAuth for this Slack webhook
(it will instead rely on Slack headers X-Slack-Request-Timestamp and
X-Slack-Signature).

In `@api-reference/openapi/general.json`:
- Around line 16-20: The OpenAPI operation for /api/notifications states the
recipient can be resolved from the API key or Bearer token but the file-level
"security" block only lists "apiKeyAuth"; update the operation's security to
include "bearerAuth" (or remove "Bearer" from the endpoint description) so
Mintlify publishes both methods; locate the /api/notifications operation and add
"bearerAuth" alongside "apiKeyAuth" in its security array to match the
description (ensure the security references the same "bearerAuth" scheme name
used in the document).

In `@api-reference/openapi/sandboxes.json`:
- Around line 16-20: The root "security" array currently only lists the Security
Requirement Object with "apiKeyAuth"; update that array to include a second
Security Requirement Object for "bearerAuth" so both "apiKeyAuth": [] and
"bearerAuth": [] appear as separate objects (OR semantics) in the security
array; modify the top-level "security" value in sandboxes.json to include both
security requirement objects to ensure generated docs/clients show either
x-api-key or Authorization: Bearer as supported auth methods.
- Around line 507-510: The schemas use the removed OpenAPI 3.1 `nullable: true`;
replace those occurrences with 3.1-native null modeling: for properties that are
$ref (e.g., deleted_snapshot referencing UpdateSnapshotResponse) replace
`nullable: true` with an anyOf that includes the $ref and a null type ({
"anyOf": [ { "$ref": "#/components/schemas/UpdateSnapshotResponse" }, { "type":
"null" } ] }); for primitive properties (e.g., snapshot_id, github_repo,
filetree, created_at) replace `nullable: true` with a type array including null
(e.g., "type": ["string","null"] or the appropriate primitive type plus "null");
apply this pattern to all six affected properties so they are correctly modeled
in OpenAPI 3.1.

In `@api-reference/openapi/social.json`:
- Around line 351-359: Add "minItems: 1" to the array schema for the query
parameters "postUrls" and "handles" in the OpenAPI document so empty arrays are
rejected; locate the "postUrls" parameter (schema.type = "array", items.type =
"string") and insert minItems: 1 into its schema, and do the same for the
"handles" parameter schema to enforce non-empty batch arrays.
- Around line 931-934: The OpenAPI 3.1 schema is still using nullable: true;
replace those with JSON Schema 2020-12 native nullable forms: for primitive
properties like the "error" property (currently "type": "string" + "nullable":
true) change the type to a union including null (e.g., type: ["string","null"]);
for properties that use $ref (e.g., references to SpotifyArtistObject) replace
nullable refs with an anyOf combining the $ref and { "type": "null" }; also
update any object-typed error fields that used nullable to use an anyOf with the
object schema and { "type": "null" } so all nullable usages conform to OpenAPI
3.1 / JSON Schema 2020-12.

In `@docs.json`:
- Around line 46-107: Multiple OpenAPI sources and the intro page advertise
conflicting base URLs; standardize by setting a single canonical server URL and
removing per-operation overrides: update every OpenAPI file listed
(api-reference/openapi/*.json — e.g., artists.json, content.json, social.json,
chats.json, accounts.json, admins.json, sandboxes.json, tasks.json,
general.json) to include a top-level "servers": [{ "url":
"https://api.recoupable.com/api" }] and remove any operation-level "servers"
entries, and also update api-reference/introduction.mdx to use the exact same
canonical URL so all generated samples and docs use one consistent host.
- Around line 88-92: The link in the content description currently points to
/api-reference/songs/analyze-presets which will 404 because docs.json maps the
OpenAPI for "Content" to api-reference/content; update the reference in
content.json (the description string that mentions [List Analyze Presets]) to
/api-reference/content/analyze-presets so it matches the directory mapping
declared in docs.json (openapi.source: "api-reference/openapi/content.json" and
directory: "api-reference/content").
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1116923a-8a20-4798-8d41-292086011aa5

📥 Commits

Reviewing files that changed from the base of the PR and between c6913b3 and 8ca2cfc.

📒 Files selected for processing (101)
  • api-reference/accounts/add-artist.mdx
  • api-reference/accounts/create.mdx
  • api-reference/accounts/get.mdx
  • api-reference/accounts/id.mdx
  • api-reference/accounts/update.mdx
  • api-reference/admins/check.mdx
  • api-reference/admins/coding-agent-slack-tags.mdx
  • api-reference/admins/coding-pr.mdx
  • api-reference/admins/content-slack-tags.mdx
  • api-reference/admins/emails.mdx
  • api-reference/admins/privy.mdx
  • api-reference/admins/sandboxes-orgs.mdx
  • api-reference/admins/sandboxes.mdx
  • api-reference/apify/scraper.mdx
  • api-reference/artist/profile.mdx
  • api-reference/artist/segments.mdx
  • api-reference/artist/socials-scrape.mdx
  • api-reference/artist/socials.mdx
  • api-reference/artists/create.mdx
  • api-reference/artists/list.mdx
  • api-reference/chat/artist.mdx
  • api-reference/chat/chats.mdx
  • api-reference/chat/compact.mdx
  • api-reference/chat/create.mdx
  • api-reference/chat/delete.mdx
  • api-reference/chat/generate.mdx
  • api-reference/chat/messages-copy.mdx
  • api-reference/chat/messages-trailing-delete.mdx
  • api-reference/chat/messages.mdx
  • api-reference/chat/segment.mdx
  • api-reference/chat/stream.mdx
  • api-reference/chat/update.mdx
  • api-reference/comments/get.mdx
  • api-reference/connectors/authorize.mdx
  • api-reference/connectors/disconnect.mdx
  • api-reference/connectors/list.mdx
  • api-reference/content-agent/callback.mdx
  • api-reference/content-agent/webhook.mdx
  • api-reference/content/create.mdx
  • api-reference/content/estimate.mdx
  • api-reference/content/templates.mdx
  • api-reference/content/validate.mdx
  • api-reference/fans/get.mdx
  • api-reference/image/generation.mdx
  • api-reference/instagram/comments.mdx
  • api-reference/instagram/profiles.mdx
  • api-reference/introduction.mdx
  • api-reference/notifications/create.mdx
  • api-reference/openapi.json
  • api-reference/openapi/accounts.json
  • api-reference/openapi/admins.json
  • api-reference/openapi/artists.json
  • api-reference/openapi/chats.json
  • api-reference/openapi/content.json
  • api-reference/openapi/general.json
  • api-reference/openapi/sandboxes.json
  • api-reference/openapi/social.json
  • api-reference/openapi/tasks.json
  • api-reference/organizations/add-artist.mdx
  • api-reference/organizations/create.mdx
  • api-reference/organizations/list.mdx
  • api-reference/post/comments.mdx
  • api-reference/posts/get.mdx
  • api-reference/pulses/list.mdx
  • api-reference/pulses/update.mdx
  • api-reference/sandboxes/create.mdx
  • api-reference/sandboxes/delete.mdx
  • api-reference/sandboxes/file.mdx
  • api-reference/sandboxes/list.mdx
  • api-reference/sandboxes/setup.mdx
  • api-reference/sandboxes/snapshot.mdx
  • api-reference/sandboxes/upload.mdx
  • api-reference/segment/fans.mdx
  • api-reference/social/posts.mdx
  • api-reference/social/scrape.mdx
  • api-reference/songs/analyze-presets.mdx
  • api-reference/songs/analyze.mdx
  • api-reference/songs/catalog-songs-add.mdx
  • api-reference/songs/catalog-songs-delete.mdx
  • api-reference/songs/catalog-songs.mdx
  • api-reference/songs/catalogs-create.mdx
  • api-reference/songs/catalogs-delete.mdx
  • api-reference/songs/catalogs.mdx
  • api-reference/songs/create.mdx
  • api-reference/songs/songs.mdx
  • api-reference/spotify/album.mdx
  • api-reference/spotify/artist-albums.mdx
  • api-reference/spotify/artist-top-tracks.mdx
  • api-reference/spotify/artist.mdx
  • api-reference/spotify/search.mdx
  • api-reference/subscriptions/get.mdx
  • api-reference/tasks/create.mdx
  • api-reference/tasks/delete.mdx
  • api-reference/tasks/get.mdx
  • api-reference/tasks/runs.mdx
  • api-reference/tasks/update.mdx
  • api-reference/transcribe/audio.mdx
  • api-reference/workspaces/create.mdx
  • api-reference/x/search.mdx
  • api-reference/x/trends.mdx
  • docs.json
💤 Files with no reviewable changes (89)
  • api-reference/artist/profile.mdx
  • api-reference/chat/messages.mdx
  • api-reference/accounts/create.mdx
  • api-reference/content/create.mdx
  • api-reference/artists/create.mdx
  • api-reference/accounts/update.mdx
  • api-reference/organizations/create.mdx
  • api-reference/chat/artist.mdx
  • api-reference/admins/privy.mdx
  • api-reference/accounts/add-artist.mdx
  • api-reference/chat/generate.mdx
  • api-reference/chat/create.mdx
  • api-reference/chat/compact.mdx
  • api-reference/admins/coding-pr.mdx
  • api-reference/admins/content-slack-tags.mdx
  • api-reference/admins/sandboxes.mdx
  • api-reference/connectors/list.mdx
  • api-reference/artists/list.mdx
  • api-reference/connectors/authorize.mdx
  • api-reference/apify/scraper.mdx
  • api-reference/chat/messages-copy.mdx
  • api-reference/content/validate.mdx
  • api-reference/organizations/list.mdx
  • api-reference/content/templates.mdx
  • api-reference/artist/segments.mdx
  • api-reference/chat/update.mdx
  • api-reference/fans/get.mdx
  • api-reference/chat/chats.mdx
  • api-reference/chat/delete.mdx
  • api-reference/sandboxes/file.mdx
  • api-reference/connectors/disconnect.mdx
  • api-reference/admins/emails.mdx
  • api-reference/instagram/comments.mdx
  • api-reference/chat/stream.mdx
  • api-reference/posts/get.mdx
  • api-reference/accounts/id.mdx
  • api-reference/social/posts.mdx
  • api-reference/sandboxes/create.mdx
  • api-reference/chat/messages-trailing-delete.mdx
  • api-reference/content-agent/callback.mdx
  • api-reference/content/estimate.mdx
  • api-reference/accounts/get.mdx
  • api-reference/organizations/add-artist.mdx
  • api-reference/sandboxes/setup.mdx
  • api-reference/chat/segment.mdx
  • api-reference/tasks/create.mdx
  • api-reference/admins/coding-agent-slack-tags.mdx
  • api-reference/transcribe/audio.mdx
  • api-reference/spotify/album.mdx
  • api-reference/subscriptions/get.mdx
  • api-reference/admins/sandboxes-orgs.mdx
  • api-reference/tasks/delete.mdx
  • api-reference/post/comments.mdx
  • api-reference/pulses/update.mdx
  • api-reference/content-agent/webhook.mdx
  • api-reference/songs/create.mdx
  • api-reference/sandboxes/upload.mdx
  • api-reference/songs/analyze.mdx
  • api-reference/tasks/get.mdx
  • api-reference/spotify/artist-albums.mdx
  • api-reference/spotify/artist.mdx
  • api-reference/songs/catalog-songs-delete.mdx
  • api-reference/songs/songs.mdx
  • api-reference/social/scrape.mdx
  • api-reference/songs/analyze-presets.mdx
  • api-reference/songs/catalog-songs.mdx
  • api-reference/admins/check.mdx
  • api-reference/songs/catalogs-create.mdx
  • api-reference/artist/socials-scrape.mdx
  • api-reference/segment/fans.mdx
  • api-reference/sandboxes/list.mdx
  • api-reference/songs/catalog-songs-add.mdx
  • api-reference/pulses/list.mdx
  • api-reference/sandboxes/delete.mdx
  • api-reference/workspaces/create.mdx
  • api-reference/tasks/update.mdx
  • api-reference/comments/get.mdx
  • api-reference/tasks/runs.mdx
  • api-reference/sandboxes/snapshot.mdx
  • api-reference/spotify/artist-top-tracks.mdx
  • api-reference/songs/catalogs-delete.mdx
  • api-reference/x/search.mdx
  • api-reference/songs/catalogs.mdx
  • api-reference/notifications/create.mdx
  • api-reference/instagram/profiles.mdx
  • api-reference/x/trends.mdx
  • api-reference/spotify/search.mdx
  • api-reference/artist/socials.mdx
  • api-reference/image/generation.mdx

Comment on lines 10 to +15
<Card
title="View OpenAPI Specification"
title="View OpenAPI Specifications"
icon="code"
href="https://github.com/sweetmantech/docs/blob/main/api-reference/openapi.json"
href="https://github.com/sweetmantech/docs/tree/main/api-reference/openapi"
>
View the OpenAPI specification file on GitHub
View the per-domain OpenAPI specification files on GitHub
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Point this card at the current repository.

This page is part of recoupable/docs, but the new href sends readers to sweetmantech/docs. That will take users to the wrong repo once this page ships.

🔗 Suggested fix
-  href="https://github.com/sweetmantech/docs/tree/main/api-reference/openapi"
+  href="https://github.com/recoupable/docs/tree/main/api-reference/openapi"
📝 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.

Suggested change
<Card
title="View OpenAPI Specification"
title="View OpenAPI Specifications"
icon="code"
href="https://github.com/sweetmantech/docs/blob/main/api-reference/openapi.json"
href="https://github.com/sweetmantech/docs/tree/main/api-reference/openapi"
>
View the OpenAPI specification file on GitHub
View the per-domain OpenAPI specification files on GitHub
<Card
title="View OpenAPI Specifications"
icon="code"
href="https://github.com/recoupable/docs/tree/main/api-reference/openapi"
>
View the per-domain OpenAPI specification files on GitHub
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/introduction.mdx` around lines 10 - 15, The Card component's
href currently points to the wrong repository (sweetmantech/docs); update the
Card with title "View OpenAPI Specifications" to point at the current
repository's OpenAPI directory by changing the href prop to the recoupable/docs
location (e.g., the GitHub URL for
recoupable/docs/tree/main/api-reference/openapi or a relative path like
/api-reference/openapi), so the Card's link targets the correct repo; modify the
href prop on the Card element accordingly.

Comment on lines +16 to +20
"security": [
{
"apiKeyAuth": []
}
],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In OpenAPI 3.1, how should a spec declare that an operation can be authenticated with either an API key header or an HTTP bearer token? Please explain the OR vs AND semantics of the security array.

💡 Result:

In OpenAPI 3.1, declare security schemes in the components.securitySchemes section, then reference them in the security field of the OpenAPI Object (global) or Operation Object using an array of Security Requirement Objects. To allow authentication with either an API key header OR HTTP bearer token: 1. Define the schemes: components: securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-API-Key BearerAuth: type: http scheme: bearer 2. Reference for OR (either one satisfies): security: - ApiKeyAuth: [] # OR - BearerAuth: [] The security array uses OR semantics: only one Security Requirement Object in the array needs to be satisfied. Within a single Security Requirement Object, multiple schemes use AND semantics: all must be satisfied (e.g., [{ApiKeyAuth: [], BearerAuth: []}] requires both). This applies to both global and per-operation security. An empty array [] removes inherited security; [{}] makes it optional. Example full operation: paths: /example: get: security: - ApiKeyAuth: [] - BearerAuth: [] responses: '200': description: OK

Citations:


🏁 Script executed:

# First, check if the file exists and get its size
wc -l api-reference/openapi/artists.json

Repository: recoupable/docs

Length of output: 98


🏁 Script executed:

# Read the beginning of the file to see the security definitions and structure
head -80 api-reference/openapi/artists.json

Repository: recoupable/docs

Length of output: 2732


🏁 Script executed:

# Search for the securitySchemes section to verify bearerAuth definition
rg -n "securitySchemes" api-reference/openapi/artists.json -A 20

Repository: recoupable/docs

Length of output: 438


bearerAuth is defined but not advertised in root security.

GET /api/artists explicitly states authentication can use "API key or Bearer token", yet the root security block (lines 16–20) only includes apiKeyAuth. The bearerAuth scheme is defined in components.securitySchemes (line 1873) but omitted from the security declaration, making generated API documentation incomplete.

Suggested fix
   "security": [
     {
       "apiKeyAuth": []
+    },
+    {
+      "bearerAuth": []
     }
   ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/artists.json` around lines 16 - 20, The root OpenAPI
"security" declaration currently lists only "apiKeyAuth" but omits the
"bearerAuth" scheme; update the root security array to include both "apiKeyAuth"
and "bearerAuth" so endpoints like GET /api/artists that allow "API key or
Bearer token" are correctly represented; locate the top-level "security" block
(the snippet containing "apiKeyAuth") and add an entry for "bearerAuth" that
matches the name defined under components.securitySchemes ("bearerAuth").

Comment on lines +140 to +158
"name": "page",
"in": "query",
"description": "The page number to retrieve (default: 1)",
"required": false,
"schema": {
"type": "integer",
"default": 1
}
},
{
"name": "limit",
"in": "query",
"description": "The number of records per page (default: 20, max: 100)",
"required": false,
"schema": {
"type": "integer",
"default": 20,
"maximum": 100
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

In OpenAPI 3.1, if a query parameter is documented as 1-based pagination or a positive limit, should the schema add minimum: 1 so generated docs and clients enforce that contract?

💡 Result:

Yes, in OpenAPI 3.1, if a query parameter is documented as 1-based pagination (e.g., page) or a positive limit, you should add minimum: 1 to the schema. This enforces the contract in generated documentation (e.g., Swagger UI shows validation errors for values <1) and client/server code generators that support JSON Schema validation. The official OpenAPI 3.1 spec uses JSON Schema 2020-12 Draft for parameter schemas, where minimum: 1 for integer types constrains values to >=1. While the spec examples show basic integer schemas without minimum, authoritative guides and best practices universally recommend it for pagination: - Bump.sh OpenAPI v3.1/v3.2 guides: page and limit schemas include minimum: 1 [2,6,15]. - Speakeasy OpenAPI best practices: page/limit with minimum: 1 [5,7]. - Swagger docs (applicable to 3.1): limit with minimum: 1 [4,18]. This prevents invalid requests like ?page=0 or ?limit=0, improves UX in interactive docs, and ensures generated clients validate inputs.

Citations:


🏁 Script executed:

# Check if the file exists and get its line count
if [ -f "api-reference/openapi/artists.json" ]; then
  echo "File found"
  wc -l api-reference/openapi/artists.json
else
  echo "File not found in root, searching..."
  find . -name "artists.json" -type f
fi

Repository: recoupable/docs

Length of output: 109


🏁 Script executed:

# Read lines 140-158 to verify the snippet
sed -n '140,158p' api-reference/openapi/artists.json

Repository: recoupable/docs

Length of output: 639


🏁 Script executed:

# Check the other mentioned locations
echo "=== Lines 325-343 ==="
sed -n '325,343p' api-reference/openapi/artists.json
echo ""
echo "=== Lines 391-409 ==="
sed -n '391,409p' api-reference/openapi/artists.json
echo ""
echo "=== Lines 457-475 ==="
sed -n '457,475p' api-reference/openapi/artists.json
echo ""
echo "=== Lines 523-541 ==="
sed -n '523,541p' api-reference/openapi/artists.json
echo ""
echo "=== Lines 599-616 ==="
sed -n '599,616p' api-reference/openapi/artists.json

Repository: recoupable/docs

Length of output: 3033


🏁 Script executed:

# Search for all instances of "page" and "limit" parameters to see the full context
rg -n '"name":\s*"(page|limit)"' api-reference/openapi/artists.json -A 10

Repository: recoupable/docs

Length of output: 4180


Add minimum: 1 constraint to pagination parameters in OpenAPI schemas.

The descriptions explicitly state 1-based pagination and positive limits, but the schemas allow 0 and negative values. This inconsistency means generated documentation and SDKs will advertise invalid inputs. In OpenAPI 3.1, add minimum: 1 to the page and limit schemas across all six endpoint definitions in this file to enforce the documented contract.

Suggested fixes

For page parameter (lines 140-158, 325-343, 391-409, 457-475, 523-541, 599-616):

             "schema": {
               "type": "integer",
-              "default": 1
+              "default": 1,
+              "minimum": 1
             }

For limit parameter with max constraint (lines 140-158, 325-343, 391-409, 457-475, 523-541):

             "schema": {
               "type": "integer",
               "default": 20,
+              "minimum": 1,
               "maximum": 100
             }

For limit parameter without max constraint (lines 599-616):

             "schema": {
               "type": "integer",
               "default": 10,
+              "minimum": 1
             }
📝 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.

Suggested change
"name": "page",
"in": "query",
"description": "The page number to retrieve (default: 1)",
"required": false,
"schema": {
"type": "integer",
"default": 1
}
},
{
"name": "limit",
"in": "query",
"description": "The number of records per page (default: 20, max: 100)",
"required": false,
"schema": {
"type": "integer",
"default": 20,
"maximum": 100
}
"name": "page",
"in": "query",
"description": "The page number to retrieve (default: 1)",
"required": false,
"schema": {
"type": "integer",
"default": 1,
"minimum": 1
}
},
{
"name": "limit",
"in": "query",
"description": "The number of records per page (default: 20, max: 100)",
"required": false,
"schema": {
"type": "integer",
"default": 20,
"minimum": 1,
"maximum": 100
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/artists.json` around lines 140 - 158, Update the
OpenAPI parameter schemas for the "page" and "limit" query parameters in this
artists.json to enforce 1-based positive pagination: add "minimum": 1 to each
"page" schema and to each "limit" schema (both those with "maximum": 100 and the
one without a max) across all six endpoint definitions where "page" and "limit"
appear so the schema matches the descriptions and prevents zero/negative values.

Comment on lines +16 to +20
"security": [
{
"apiKeyAuth": []
}
],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the file structure and size
wc -l api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 98


🏁 Script executed:

# Read the file around lines 1-30 to see the context and file-level security
sed -n '1,35p' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 1369


🏁 Script executed:

# Read around lines 914-963 to check the secondary location
sed -n '910,970p' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 2585


🏁 Script executed:

# Count lines in the security block at the top of file
sed -n '16,20p' api-reference/openapi/content.json | cat -n

Repository: recoupable/docs

Length of output: 149


🏁 Script executed:

# Verify the exact content matches lines 16-20
sed -n '16,20p' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 114


🏁 Script executed:

# Find the /api/content-agent endpoint and see what lines it spans
rg -n '/api/content-agent' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 142


🏁 Script executed:

# Check lines 914-920 specifically
sed -n '914,920p' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 732


🏁 Script executed:

# Get the full endpoint definition from line 913 to 964 to confirm no local security block
sed -n '913,964p' api-reference/openapi/content.json | head -60

Repository: recoupable/docs

Length of output: 1962


🏁 Script executed:

# Check if there's a security property anywhere in the /api/content-agent/{platform} endpoint
sed -n '913,964p' api-reference/openapi/content.json | grep -i "security"

Repository: recoupable/docs

Length of output: 41


Clear the inherited API-key auth on the Slack webhook at /api/content-agent/{platform}.

This endpoint inherits the file-level apiKeyAuth security requirement but should not. It's a Slack webhook that expects signature headers (X-Slack-Request-Timestamp and X-Slack-Signature), not API keys. Publishing x-api-key as required will mislead consumers. Set "security": [] to override the inheritance.

🪑 Suggested fix
    "/api/content-agent/{platform}": {
      "post": {
+       "security": [],
        "description": "Webhook endpoint for the Recoup Content Agent Slack bot. Receives `@mention` events from Slack and triggers content generation for the mentioned artist. The bot parses the mention text for `<artist_account_id> [template] [batch=N] [lipsync]`, validates the artist, calls POST /api/content/create, and starts a background polling task that reports results back to the Slack thread.\n\nFor Slack, also handles `url_verification` challenges during app setup.",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/content.json` around lines 16 - 20, The endpoint
definition for /api/content-agent/{platform} is inheriting the file-level
"apiKeyAuth" security requirement; update the operation's security to override
this by setting "security": [] in the operation object for the
/api/content-agent/{platform} path so that the API-key requirement is cleared
and consumers see no apiKeyAuth for this Slack webhook (it will instead rely on
Slack headers X-Slack-Request-Timestamp and X-Slack-Signature).

Comment on lines +1063 to +1067
"security": [
{
"callbackSecret": []
}
],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, check the file size and read the lines in question
wc -l api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 98


🏁 Script executed:

# Read the specific lines mentioned in the review comment (1063-1067)
sed -n '1063,1067p' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 148


🏁 Script executed:

# Search for where "callbackSecret" is referenced in the file
rg '"callbackSecret"' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 91


🏁 Script executed:

# Check the components.securitySchemes section to see all declared schemes
rg '"securitySchemes"' api-reference/openapi/content.json -A 50

Repository: recoupable/docs

Length of output: 368


🏁 Script executed:

# Also check the "Also applies to" lines mentioned: 2492-2503
sed -n '2492,2503p' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 362


🏁 Script executed:

# Find the endpoint that uses callbackSecret to confirm it's the callback endpoint
rg -B 10 '"callbackSecret"' api-reference/openapi/content.json | head -30

Repository: recoupable/docs

Length of output: 326


🏁 Script executed:

# Search for all security references to ensure no other undeclared schemes are used
rg '"security"' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 140


🏁 Script executed:

# Get more detailed context for each security reference
rg '"security"' api-reference/openapi/content.json -A 5

Repository: recoupable/docs

Length of output: 508


Define callbackSecret in components.securitySchemes.

The /api/content-agent/callback endpoint references callbackSecret in its security requirement, but this security scheme is never declared. The spec only defines bearerAuth and apiKeyAuth under components.securitySchemes, making the document invalid. OpenAPI validators will flag this error, and generated documentation will fail to render the callback endpoint's security details.

Add the missing security scheme definition:

Fix
     "securitySchemes": {
+      "callbackSecret": {
+        "type": "apiKey",
+        "in": "header",
+        "name": "x-callback-secret",
+        "description": "Shared secret for the internal content-agent callback endpoint."
+      },
       "bearerAuth": {
         "type": "http",
         "scheme": "bearer"
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/content.json` around lines 1063 - 1067, The OpenAPI
spec references the security requirement callbackSecret for the
/api/content-agent/callback endpoint but never declares it; add a new security
scheme entry named callbackSecret under components.securitySchemes (similar to
existing bearerAuth/apiKeyAuth) that matches the intended auth type (e.g.,
apiKey in header or http bearer) so the security requirement resolves; update
components.securitySchemes to include callbackSecret and ensure its name/type/in
parameter align with how the callback endpoint expects the secret.

Comment on lines +507 to +510
"deleted_snapshot": {
"nullable": true,
"description": "The snapshot record that was deleted. Null if no snapshot existed for the account.",
"$ref": "#/components/schemas/UpdateSnapshotResponse"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In OpenAPI 3.1 / JSON Schema 2020-12, is nullable: truestill the correct way to model null values? If not, what should be used instead for primitive properties and for$ref properties?

💡 Result:

No, nullable: true is not the correct way in OpenAPI 3.1 / JSON Schema 2020-12. The nullable keyword was removed from OpenAPI 3.1 as it aligns fully with JSON Schema 2020-12, where nullability is expressed using the null type in the type array. For primitive properties (e.g., string, number, boolean, etc.): Use type: ["string", "null"] (or type: ['string', 'null'] in YAML/JSON). Type-specific keywords like maxLength, format, etc., apply only when the instance matches that type (e.g., string constraints are ignored for null). Example: type: ['string', 'null'] maxLength: 255 format: uri For $ref properties: Use anyOf (preferred over oneOf to avoid issues if the referenced schema allows null): anyOf: - type: 'null' - $ref: '#/components/schemas/MySchema' allOf with $ref + type: ['object', 'null'] may work in some cases but anyOf is more explicit and reliable. nullable: true is ignored or invalid in strict 3.1 validators.

Citations:


🏁 Script executed:

# First, check if the file exists and get its total line count
wc -l api-reference/openapi/sandboxes.json

Repository: recoupable/docs

Length of output: 99


🏁 Script executed:

# Examine the specific line ranges mentioned
echo "=== Lines 507-510 ==="
sed -n '507,510p' api-reference/openapi/sandboxes.json

echo -e "\n=== Lines 669-679 ==="
sed -n '669,679p' api-reference/openapi/sandboxes.json

echo -e "\n=== Lines 775-785 ==="
sed -n '775,785p' api-reference/openapi/sandboxes.json

Repository: recoupable/docs

Length of output: 1374


🏁 Script executed:

# Count all instances of "nullable" in the file
echo "Total instances of 'nullable' in file:"
rg 'nullable' api-reference/openapi/sandboxes.json | wc -l

echo -e "\nAll occurrences with line numbers:"
rg -n 'nullable' api-reference/openapi/sandboxes.json

Repository: recoupable/docs

Length of output: 337


🏁 Script executed:

# Check line 683 and context
sed -n '680,690p' api-reference/openapi/sandboxes.json

Repository: recoupable/docs

Length of output: 457


🏁 Script executed:

# Let's also verify the overall structure - check the OpenAPI version declared
head -5 api-reference/openapi/sandboxes.json

Repository: recoupable/docs

Length of output: 241


Replace nullable: true with 3.1-native null modeling.

This file declares openapi: 3.1.0, but these schemas still rely on nullable, which was removed in OpenAPI 3.1. Many 3.1 tools treat it as a no-op, so fields like deleted_snapshot, snapshot_id, github_repo, filetree, and created_at can be rendered or generated as non-nullable.

For primitive properties, use type: ["string", "null"] (or appropriate type). For properties with $ref, use anyOf with a null type alternative:

"anyOf": [
  { "$ref": "#/components/schemas/UpdateSnapshotResponse" },
  { "type": "null" }
]

Affects 6 instances in this file: lines 508, 673, 679, 683, 777, 784.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/sandboxes.json` around lines 507 - 510, The schemas use
the removed OpenAPI 3.1 `nullable: true`; replace those occurrences with
3.1-native null modeling: for properties that are $ref (e.g., deleted_snapshot
referencing UpdateSnapshotResponse) replace `nullable: true` with an anyOf that
includes the $ref and a null type ({ "anyOf": [ { "$ref":
"#/components/schemas/UpdateSnapshotResponse" }, { "type": "null" } ] }); for
primitive properties (e.g., snapshot_id, github_repo, filetree, created_at)
replace `nullable: true` with a type array including null (e.g., "type":
["string","null"] or the appropriate primitive type plus "null"); apply this
pattern to all six affected properties so they are correctly modeled in OpenAPI
3.1.

Comment on lines +351 to +359
"name": "postUrls",
"in": "query",
"description": "Array of Instagram post URLs to fetch comments for",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

In OpenAPI 3.1, does required: trueon an array query parameter prevent empty arrays, or do we needminItems: 1 to document a non-empty batch request?

💡 Result:

In OpenAPI 3.1, required: true on an array query parameter requires the parameter to be present in the request but does not prevent empty arrays. An empty array is a valid value for the parameter unless minItems: 1 is specified in the schema. To document a non-empty batch request, use both required: true and minItems: 1.

Citations:


🏁 Script executed:

# First, let's check the file exists and its size
wc -l api-reference/openapi/social.json

Repository: recoupable/docs

Length of output: 97


🏁 Script executed:

# Read the sections mentioned in the review
echo "=== Lines 351-359 (postUrls) ==="
sed -n '351,359p' api-reference/openapi/social.json

echo -e "\n=== Lines 419-427 (handles) ==="
sed -n '419,427p' api-reference/openapi/social.json

Repository: recoupable/docs

Length of output: 719


🏁 Script executed:

# Search for all array parameters with "required": true to find all batch parameters
rg -A 10 '"required":\s*true' api-reference/openapi/social.json | head -100

Repository: recoupable/docs

Length of output: 2789


Add minItems: 1 to enforce non-empty batch arrays.

In OpenAPI 3.1, required: true only means the parameter must be present; it does not prevent empty arrays. An empty array is a valid value unless minItems: 1 is specified in the schema. For postUrls and handles, this generates docs/clients that accept batches with no work to do.

Suggested fix
             "schema": {
               "type": "array",
+              "minItems": 1,
               "items": {
                 "type": "string"
               }
             },

Also applies to: lines 419-427 (handles parameter)

🧰 Tools
🪛 Checkov (3.2.510)

[medium] 355-359: Ensure that arrays have a maximum number of items

(CKV_OPENAPI_21)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/social.json` around lines 351 - 359, Add "minItems: 1"
to the array schema for the query parameters "postUrls" and "handles" in the
OpenAPI document so empty arrays are rejected; locate the "postUrls" parameter
(schema.type = "array", items.type = "string") and insert minItems: 1 into its
schema, and do the same for the "handles" parameter schema to enforce non-empty
batch arrays.

Comment on lines +931 to +934
"error": {
"type": "string",
"nullable": true,
"description": "Error message if the run failed (null if successful)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In OpenAPI 3.1 / JSON Schema 2020-12, is nullable: truestill the correct way to model null values? If not, what should be used instead for primitive properties and for$ref properties?

💡 Result:

No, nullable: true is not the correct way in OpenAPI 3.1 / JSON Schema 2020-12. The nullable keyword was removed from OpenAPI 3.1 in favor of native JSON Schema support for the null type. For primitive properties, use type: ["string", "null"] (or other primitive with "null"). Type-specific keywords like format or maxLength apply only when the instance matches that type (e.g., string constraints are ignored for null). For $ref properties, wrap in anyOf or oneOf: anyOf: - $ref: '#/components/schemas/Foo' - type: null (or type: ["object", "null"] if the ref targets an object, etc.). nullable may be ignored or cause tooling issues as it's not part of JSON Schema 2020-12.

Citations:


🏁 Script executed:

# Check if the file exists
fd 'social.json' api-reference/

Repository: recoupable/docs

Length of output: 92


🏁 Script executed:

# Count lines in the file to verify line numbers are within bounds
wc -l api-reference/openapi/social.json

Repository: recoupable/docs

Length of output: 97


🏁 Script executed:

# Extract the flagged sections
echo "=== Lines 931-934 ===" && sed -n '931,934p' api-reference/openapi/social.json
echo "=== Lines 1422-1425 ===" && sed -n '1422,1425p' api-reference/openapi/social.json
echo "=== Lines 1647-1655 ===" && sed -n '1647,1655p' api-reference/openapi/social.json

Repository: recoupable/docs

Length of output: 792


🏁 Script executed:

# Find the openapi version declaration
head -20 api-reference/openapi/social.json | grep -i openapi

Repository: recoupable/docs

Length of output: 80


🏁 Script executed:

# Get more context around the $ref case to understand the structure
sed -n '1645,1665p' api-reference/openapi/social.json

Repository: recoupable/docs

Length of output: 694


Replace nullable: true with OpenAPI 3.1 / JSON Schema 2020-12 native syntax.

This spec declares openapi: 3.1.0, but uses nullable: true which was removed in favor of native JSON Schema support. For primitive properties, use type: ["string", "null"] (or other primitive). For $ref properties, use anyOf with the reference and null type. Tooling may ignore or misinterpret nullable.

For primitive properties (lines 931-934, 1422-1425):

"type": ["string", "null"]

For $ref properties (line 1649-1650):

"anyOf": [
  { "$ref": "#/components/schemas/SpotifyArtistObject" },
  { "type": "null" }
]

Also check line 1651-1654 (error field, type: object) for similar fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/social.json` around lines 931 - 934, The OpenAPI 3.1
schema is still using nullable: true; replace those with JSON Schema 2020-12
native nullable forms: for primitive properties like the "error" property
(currently "type": "string" + "nullable": true) change the type to a union
including null (e.g., type: ["string","null"]); for properties that use $ref
(e.g., references to SpotifyArtistObject) replace nullable refs with an anyOf
combining the $ref and { "type": "null" }; also update any object-typed error
fields that used nullable to use an anyOf with the object schema and { "type":
"null" } so all nullable usages conform to OpenAPI 3.1 / JSON Schema 2020-12.

Comment on lines 46 to 107
"group": "Chat",
"pages": [
"api-reference/chat/chats",
"api-reference/chat/artist",
"api-reference/chat/segment",
"api-reference/chat/messages",
"api-reference/chat/messages-copy",
"api-reference/chat/messages-trailing-delete",
"api-reference/chat/create",
"api-reference/chat/update",
"api-reference/chat/delete",
"api-reference/chat/generate",
"api-reference/chat/stream",
"api-reference/chat/compact"
]
},
{
"group": "Pulses",
"pages": [
"api-reference/pulses/list",
"api-reference/pulses/update"
]
"openapi": {
"source": "api-reference/openapi/chats.json",
"directory": "api-reference/chat"
}
},
{
"group": "Tasks",
"pages": [
"api-reference/tasks/get",
"api-reference/tasks/create",
"api-reference/tasks/update",
"api-reference/tasks/delete",
"api-reference/tasks/runs"
]
"openapi": {
"source": "api-reference/openapi/tasks.json",
"directory": "api-reference/tasks"
}
},
{
"group": "Accounts",
"pages": [
"api-reference/accounts/get",
"api-reference/accounts/id",
"api-reference/accounts/create",
"api-reference/accounts/update",
"api-reference/accounts/add-artist"
]
"openapi": {
"source": "api-reference/openapi/accounts.json",
"directory": "api-reference/accounts"
}
},
{
"group": "Admins",
"pages": [
"api-reference/admins/check",
"api-reference/admins/sandboxes",
"api-reference/admins/sandboxes-orgs",
"api-reference/admins/emails",
"api-reference/admins/privy",
"api-reference/admins/coding-agent-slack-tags",
"api-reference/admins/coding-pr",
"api-reference/admins/content-slack-tags"
]
"openapi": {
"source": "api-reference/openapi/admins.json",
"directory": "api-reference/admins"
}
},
{
"group": "Artists",
"pages": [
"api-reference/artists/list",
"api-reference/artists/create",
"api-reference/artist/segments",
"api-reference/artist/socials",
"api-reference/artist/socials-scrape",
"api-reference/artist/profile"
]
},
{
"group": "Segment",
"pages": [
"api-reference/segment/fans"
]
},
{
"group": "Fans",
"pages": [
"api-reference/fans/get"
]
},
{
"group": "Posts",
"pages": [
"api-reference/posts/get"
]
},
{
"group": "Post",
"pages": [
"api-reference/post/comments"
]
},
{
"group": "Comments",
"pages": [
"api-reference/comments/get"
]
},
{
"group": "Organizations",
"pages": [
"api-reference/organizations/list",
"api-reference/organizations/create",
"api-reference/organizations/add-artist"
]
},
{
"group": "Workspaces",
"pages": [
"api-reference/workspaces/create"
]
},
{
"group": "Spotify",
"pages": [
"api-reference/spotify/search",
"api-reference/spotify/artist",
"api-reference/spotify/artist-albums",
"api-reference/spotify/artist-top-tracks",
"api-reference/spotify/album"
]
},
{
"group": "Instagram",
"pages": [
"api-reference/instagram/comments",
"api-reference/instagram/profiles"
]
},
{
"group": "X (Twitter)",
"pages": [
"api-reference/x/search",
"api-reference/x/trends"
]
"openapi": {
"source": "api-reference/openapi/artists.json",
"directory": "api-reference/artists"
}
},
{
"group": "Social",
"pages": [
"api-reference/social/scrape",
"api-reference/social/posts"
]
},
{
"group": "Image",
"pages": [
"api-reference/image/generation"
]
},
{
"group": "Transcribe",
"pages": [
"api-reference/transcribe/audio"
]
},
{
"group": "Songs & Catalogs",
"pages": [
"api-reference/songs/songs",
"api-reference/songs/create",
"api-reference/songs/analyze",
"api-reference/songs/analyze-presets",
"api-reference/songs/catalogs",
"api-reference/songs/catalogs-create",
"api-reference/songs/catalogs-delete",
"api-reference/songs/catalog-songs",
"api-reference/songs/catalog-songs-add",
"api-reference/songs/catalog-songs-delete"
]
},
{
"group": "Subscriptions",
"pages": [
"api-reference/subscriptions/get"
]
},
{
"group": "Notifications",
"pages": [
"api-reference/notifications/create"
]
"openapi": {
"source": "api-reference/openapi/social.json",
"directory": "api-reference/social"
}
},
{
"group": "Apify",
"pages": [
"api-reference/apify/scraper"
]
"group": "Content",
"openapi": {
"source": "api-reference/openapi/content.json",
"directory": "api-reference/content"
}
},
{
"group": "Sandboxes",
"pages": [
"api-reference/sandboxes/list",
"api-reference/sandboxes/create",
"api-reference/sandboxes/snapshot",
"api-reference/sandboxes/delete",
"api-reference/sandboxes/setup",
"api-reference/sandboxes/file",
"api-reference/sandboxes/upload"
]
"openapi": {
"source": "api-reference/openapi/sandboxes.json",
"directory": "api-reference/sandboxes"
}
},
{
"group": "Connectors",
"pages": [
"api-reference/connectors/list",
"api-reference/connectors/authorize",
"api-reference/connectors/disconnect"
]
},
{
"group": "Content",
"pages": [
"api-reference/content/create",
"api-reference/content/templates",
"api-reference/content/validate",
"api-reference/content/estimate"
]
},
{
"group": "Content Agent",
"pages": [
"api-reference/content-agent/webhook",
"api-reference/content-agent/callback"
]
"group": "General",
"openapi": {
"source": "api-reference/openapi/general.json",
"directory": "api-reference/general"
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "docs.json" -o -name "introduction.mdx" | head -20

Repository: recoupable/docs

Length of output: 103


🏁 Script executed:

git ls-files | grep -E "(docs\.json|api-reference)" | head -30

Repository: recoupable/docs

Length of output: 411


🏁 Script executed:

cat -n docs.json | head -120

Repository: recoupable/docs

Length of output: 4004


🏁 Script executed:

cat -n api-reference/introduction.mdx

Repository: recoupable/docs

Length of output: 2236


🏁 Script executed:

for file in api-reference/openapi/*.json; do echo "=== $file ==="; head -30 "$file"; done

Repository: recoupable/docs

Length of output: 9044


🏁 Script executed:

for file in api-reference/openapi/*.json; do
  echo "=== $file ==="
  grep -n '"servers"' "$file" | head -10
done

Repository: recoupable/docs

Length of output: 1253


🏁 Script executed:

# Check operation-level server overrides in accounts.json
sed -n '411,415p' api-reference/openapi/accounts.json

# Check operation-level server overrides in artists.json
for line in 307 373 439 505 571; do
  echo "--- Line $line ---"
  sed -n "${line},$((line+3))p" api-reference/openapi/artists.json
done

# Check a few from content.json
for line in 235 297; do
  echo "--- Line $line ---"
  sed -n "${line},$((line+3))p" api-reference/openapi/content.json
done

# Check all from social.json (since we already saw one)
for line in 24 109 153 237 290 343 411 460 530; do
  echo "--- Line $line ---"
  sed -n "${line},$((line+3))p" api-reference/openapi/social.json
done

Repository: recoupable/docs

Length of output: 1921


The generated reference advertises three conflicting base URLs.

The OpenAPI specs define global servers pointing to https://recoup-api.vercel.app, but many operations have individual servers overrides pointing to https://api.recoupable.com (without /api suffix), and api-reference/introduction.mdx documents the base URL as https://api.recoupable.com/api. This causes generated samples to show different hosts depending on which endpoint is displayed:

  • Most endpoints in General, Admins, Sandboxes, Tasks groups: https://recoup-api.vercel.app
  • Endpoints in Artists, Content, Social, Chats, Accounts groups with overrides: https://api.recoupable.com
  • Documentation introduction page: https://api.recoupable.com/api

Clients will see inconsistent hosts across the API reference, with some endpoints directing them to the Vercel staging URL instead of the production endpoint.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs.json` around lines 46 - 107, Multiple OpenAPI sources and the intro page
advertise conflicting base URLs; standardize by setting a single canonical
server URL and removing per-operation overrides: update every OpenAPI file
listed (api-reference/openapi/*.json — e.g., artists.json, content.json,
social.json, chats.json, accounts.json, admins.json, sandboxes.json, tasks.json,
general.json) to include a top-level "servers": [{ "url":
"https://api.recoupable.com/api" }] and remove any operation-level "servers"
entries, and also update api-reference/introduction.mdx to use the exact same
canonical URL so all generated samples and docs use one consistent host.

Comment on lines +88 to +92
"group": "Content",
"openapi": {
"source": "api-reference/openapi/content.json",
"directory": "api-reference/content"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let me locate and examine docs.json around lines 88-92
fd -type f -name "docs.json" | head -20

Repository: recoupable/docs

Length of output: 229


🏁 Script executed:

# Search for openapi content configuration files
fd -type f -name "content.json" | grep -E "(openapi|api-reference)"

Repository: recoupable/docs

Length of output: 229


🏁 Script executed:

# Look for any configuration or reference files that might contain API paths
fd -type f -name "*.json" | grep -E "(docs|openapi|api)" | head -20

Repository: recoupable/docs

Length of output: 229


🏁 Script executed:

# Find docs.json and content.json files
fd -t f docs.json
fd -t f -path "*openapi*" "content.json"
fd -t f -name "*.json" | grep -E "(docs|openapi|api)"

Repository: recoupable/docs

Length of output: 485


🏁 Script executed:

# List repository structure to understand layout
git ls-files | head -50

Repository: recoupable/docs

Length of output: 671


🏁 Script executed:

# Get full directory tree overview
tree -L 3 -I 'node_modules' 2>/dev/null || find . -maxdepth 3 -type f -name "*.json" | head -30

Repository: recoupable/docs

Length of output: 733


🏁 Script executed:

# Read docs.json and show lines around 88-92
cat -n docs.json | sed -n '80,100p'

Repository: recoupable/docs

Length of output: 835


🏁 Script executed:

# Check the full docs.json to understand structure
wc -l docs.json
cat -n docs.json | head -50

Repository: recoupable/docs

Length of output: 1571


🏁 Script executed:

# Read content.json to check for hard-coded paths
wc -l api-reference/openapi/content.json
cat api-reference/openapi/content.json | head -100

Repository: recoupable/docs

Length of output: 3850


🏁 Script executed:

# Search for hard-coded /api-reference/songs paths in content.json
rg -i "api-reference/songs" api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 377


🏁 Script executed:

# Search more broadly for any hard-coded paths in all openapi specs
rg -i "api-reference" api-reference/openapi/ -t json

Repository: recoupable/docs

Length of output: 5408


🏁 Script executed:

# Extract servers from each openapi spec file
for spec in api-reference/openapi/*.json; do
  echo "=== $(basename $spec) ==="
  rg -o '"url":\s*"[^"]*"' "$spec" | head -1
done

Repository: recoupable/docs

Length of output: 595


🏁 Script executed:

# Check for any redirects configuration in docs.json or other config files
rg -i "redirect" . --type json

Repository: recoupable/docs

Length of output: 494


🏁 Script executed:

# Check if songs.json exists
fd -t f "songs.json"

Repository: recoupable/docs

Length of output: 41


🏁 Script executed:

# Check what endpoints are in content.json related to songs
rg "/api/songs" api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 868


🏁 Script executed:

# Search the entire docs for any references to old songs routes
rg "api-reference/songs" . --type mdx --type json

Repository: recoupable/docs

Length of output: 86


🏁 Script executed:

# Check the git history to see if songs.json was removed or consolidated
git log --oneline --all -- "api-reference/openapi/songs.json" 2>/dev/null | head -5

Repository: recoupable/docs

Length of output: 41


🏁 Script executed:

# Search for /api-reference/songs references more broadly
rg "api-reference/songs" .

Repository: recoupable/docs

Length of output: 414


🏁 Script executed:

# Check if there are any .mdx files referencing songs
find . -name "*.mdx" -exec rg "songs" {} + | head -20

Repository: recoupable/docs

Length of output: 242


🏁 Script executed:

# Look at the actual generated navigation - what pages would be created by content.json
# List all paths in content.json to understand what docs pages are generated
rg '"/api/' api-reference/openapi/content.json | grep -o '"/api/[^"]*"' | sort -u

Repository: recoupable/docs

Length of output: 356


🏁 Script executed:

# Check the introduction page to see what server URLs are documented
cat api-reference/introduction.mdx

Repository: recoupable/docs

Length of output: 1767


🏁 Script executed:

# Verify what the actual generated page URL would be for the songs endpoints
# List all paths in content.json and confirm they'll be under api-reference/content/
rg '"operationId"' api-reference/openapi/content.json | head -20

Repository: recoupable/docs

Length of output: 759


🏁 Script executed:

# Specifically check the analyze-presets endpoint details
rg -A 5 'analyze/presets' api-reference/openapi/content.json | head -30

Repository: recoupable/docs

Length of output: 1286


🏁 Script executed:

# Check if there's documentation on how Mintlify generates URLs from operationId
cat docs.json | rg -A 2 -B 2 '"directory"'

Repository: recoupable/docs

Length of output: 1559


🏁 Script executed:

# Verify the exact impact - how would Mintlify generate the URL for analyze-presets?
# Get the full analyze-presets endpoint definition
rg -B 5 '"operationId": "analyze-presets"' api-reference/openapi/content.json | head -10

Repository: recoupable/docs

Length of output: 170


🏁 Script executed:

# Check if there are other hard-coded internal links in content.json that will break
rg '\[.*\]\(/api-reference/songs' api-reference/openapi/content.json
rg '\[.*\]\(/api-reference/catalogs' api-reference/openapi/content.json
rg '\[.*\]\(/api-reference/transcribe' api-reference/openapi/content.json

Repository: recoupable/docs

Length of output: 377


🏁 Script executed:

# Confirm the discrepancy between intro docs and actual server URLs
echo "=== Documented base URL in introduction.mdx ==="
rg -A 2 "Base URL" api-reference/introduction.mdx
echo ""
echo "=== Actual server URLs in specs ==="
echo "All specs use: https://recoup-api.vercel.app"

Repository: recoupable/docs

Length of output: 237


Update the hard-coded documentation link that will break after consolidation.

The description in content.json references [List Analyze Presets](/api-reference/songs/analyze-presets), but Mintlify will generate this endpoint under /api-reference/content/analyze-presets based on the directory mapping in docs.json. This link will be 404 after publishing. Update the reference to /api-reference/content/analyze-presets before consolidating.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs.json` around lines 88 - 92, The link in the content description
currently points to /api-reference/songs/analyze-presets which will 404 because
docs.json maps the OpenAPI for "Content" to api-reference/content; update the
reference in content.json (the description string that mentions [List Analyze
Presets]) to /api-reference/content/analyze-presets so it matches the directory
mapping declared in docs.json (openapi.source:
"api-reference/openapi/content.json" and directory: "api-reference/content").

@sweetmantech
Copy link
Copy Markdown
Collaborator

Closing in favor of a simpler approach: split the JSON but keep MDX files with updated frontmatter paths. See new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants