Skip to content

docs: align 7 research response schemas with actual API behavior#140

Merged
sweetmantech merged 1 commit into
mainfrom
docs/research-schema-drift-fixes
Apr 16, 2026
Merged

docs: align 7 research response schemas with actual API behavior#140
sweetmantech merged 1 commit into
mainfrom
docs/research-schema-drift-fixes

Conversation

@sweetmantech
Copy link
Copy Markdown
Collaborator

@sweetmantech sweetmantech commented Apr 16, 2026

Summary

Surfaced while comparing the merged OpenAPI spec against a full re-test of every research endpoint on recoupable/api#366's preview deployment (test comments: 1 / 2 / 3 / 4 / 5 / 6). Tested with artist "El Gran Combo de Puerto Rico" (Chartmetric id 207089) across 44 captured response bodies.

All changes are spec-only — no api behavior change.

Changes at a glance

Endpoint Change
/research/track Document cm_statistics, tempo, moods, activities
/research/playlist Drop curator_name/num_tracks (never returned) → use owner_name/num_track; add 15+ real fields
/research/charts data is an array (not object); add length
/research/profile Drop hometown/sp_followers/sp_monthly_listeners/tags (use /research/metrics for longitudinal platform metrics); add 15+ real fields
/research/metrics Replace {data: [...]} wrapper with flat per-platform time-series fields (followers/listeners/popularity/followers_to_listeners_ratio)
/research/audience Add the full audience_likers_* field family + engagement aggregates (followers, avg_likes_per_post, engagement_rate)
/research/curator Drop followers/num_playlists; add per-platform follower fields (instagram_followers, facebook_followers, etc.) + cm_statistics

Why

Every docs/actual drift item from the audit falls into one of two buckets:

  1. Spec advertises fields that never appear — e.g. /playlist advertising curator_name when the real field is owner_name, /profile advertising sp_followers when longitudinal platform metrics live behind /research/metrics. These mislead integrators into writing code against fields that never populate.
  2. Spec omits fields that always appear — e.g. the audience_likers_* family on /audience, cm_statistics on /track//profile//curator, per-platform follower fields on /curator. Not strictly wrong (additionalProperties: true lets them through), but LLM/SDK consumers won't know to use them.

Each schema now matches what the PR #366 preview actually returns, spot-checked against El Gran Combo de Puerto Rico responses.

Test plan

  • Mintlify preview renders all 7 endpoint pages without errors
  • Response-schema sections on each page show the updated field set
  • Spot-check against the JSON bodies captured in the api PR test comments (linked above)

🤖 Generated with Claude Code


Summary by cubic

Aligns the OpenAPI docs for seven research endpoints with actual API responses. Adds missing fields, removes unused ones, and fixes response shapes; no API behavior changes.

  • Schema updates
    • Corrected shapes: /research/charts uses a data array and adds length; /research/metrics returns root-level time-series arrays of {timestp, value} (link, followers, listeners, popularity, followers_to_listeners_ratio).
    • Added real fields: /research/track (cm_statistics, tempo, moods, activities); /research/playlist (owner/IDs, image/editorial/personalized, country/catalog, activity ratio, suspicion/deltas/timestamps, tags/genres/moods/activities); /research/profile (identity/geo, ranks, cm_statistics, career status, genre ranks/ordering, moods/activities, contacts, collaborators); /research/audience (likers fields, engagement aggregates, timestp, notable followers, ethnicities/interests); /research/curator (per-platform follower metrics, user_id/submithub_id, suspicion_score, tags/social URLs, cm_statistics).
    • Removed fields that never appear: /research/playlist (curator_name, num_tracksowner_name, num_track), /research/profile (sp_followers, sp_monthly_listeners, tags), /research/curator (followers, num_playlists).

Written for commit aab48da. Summary will update on new commits.

Summary by CodeRabbit

  • Documentation
    • Expanded audience response with engagement metrics, demographic breakdowns, and notable followers data
    • Enhanced curator profiles with platform follower counts, tags, and Chartmetric statistics
    • Restructured metrics response into time-series format for followers, listeners, and popularity trends
    • Enriched artist profiles with rank scores, career status, and comprehensive statistical data
    • Added comprehensive playlist metadata including genres, moods, activities, and quality indicators
    • Included tempo and mood/activity arrays in track responses

Surfaced while comparing the merged docs to a full re-test of the
research endpoints on the recoupable/api#366 preview (see
recoupable/api#366 (comment)
through #issuecomment-4263097490). Each of the schemas below either
advertised fields that never appear in responses or omitted fields
that always do.

All changes are spec-only — no api behavior change.

/research/track response
- Document `cm_statistics` (nested platform stats blob)
- Document tempo / moods / activities (common nullable fields)

/research/playlist response
- Drop `curator_name` (never returned) → surface as `owner_name`
- Drop `num_tracks` (never returned) → real field is `num_track`
- Add playlist_id (platform-native), owner_id, user_id, image_url,
  editorial, personalized, catalog, code2, active_ratio,
  suspicion_score, fdiff_week/month, last_updated, sys_last_updated,
  genres/moods/activities + their smart-ordered counterparts, tags

/research/charts response
- `data` is an array, not an object (50 entries in practice)
- Document `length` (total entry count)

/research/profile response
- Drop `hometown`, `sp_followers`, `sp_monthly_listeners`, `tags` —
  none are returned (longitudinal platform metrics live behind
  /research/metrics; use `hometown_city`/`current_city` for geography)
- Add: band/band_members, gender fields, code2, isni,
  cover_url, hometown_city, current_city(_id),
  cm_artist_rank/cm_artist_score, cm_statistics, career_status,
  genreRank/subGenreRank1/2, genre_smart_ordered, moods, activities,
  booking_agent, press_contact, general_manager, topSongwriterCollaborators

/research/metrics response
- Replace documented `{data: [...]}` wrapper with flat per-platform
  time-series fields. For Spotify: `link`, `followers`, `listeners`,
  `popularity`, `followers_to_listeners_ratio` — each an array of
  `{timestp, value}` points.

/research/audience response
- Add the likers/engagement field family: audience_likers_genders
  (+per_age), audience_likers_ethnicities, audience_likers_interests,
  audience_likers_brand_affinities, likers_top_countries,
  likers_top_cities, notable_followers, followers,
  avg_likes_per_post, avg_commments_per_post (sic — upstream typo),
  engagement_rate, timestp
- Add audience_ethnicities, audience_interests

/research/curator response
- Drop `followers` / `num_playlists` (neither returned)
- Add per-platform follower fields: instagram_followers,
  facebook_followers/fans, twitter_followers/retweets,
  youtube_subscribers/views, soundcloud_followers,
  tiktok_followers/likes (all nullable)
- Add user_id, submithub_id, last_updated, suspicion_score, tags,
  tag_ids, tag_names, spotifySocialUrls, cm_statistics

/research/extract response
- No change. Prior audit flagged errors as drift, but the field is
  already correctly optional (not in `required`) with a description
  noting conditional presence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

Updated OpenAPI schemas for six Research API responses to document expanded Chartmetric payloads, adding audience engagement metrics, platform follower counts, identity fields, curator/playlist metadata, time-series structures for metrics, and track analysis data across multiple schema definitions.

Changes

Cohort / File(s) Summary
Audience & Engagement Metrics
api-reference/openapi/research.jsonResearchAudienceResponse
Added audience snapshot timestamp, follower counts, engagement aggregates, likers demographic breakdowns (countries, cities, ethnicities, interests, brand affinities), and notable followers array.
Data Structure Conversions
api-reference/openapi/research.jsonResearchChartsResponse, ResearchMetricsResponse
Transformed ResearchChartsResponse.data from single object to typed-array with length field; restructured ResearchMetricsResponse as root-level time-series envelope with separate arrays for followers, listeners, popularity, and computed ratios.
Creator & Profile Enrichment
api-reference/openapi/research.jsonResearchCuratorResponse, ResearchProfileResponse
Expanded curator schema with identity, tag, platform follower counts, and statistics fields; significantly enhanced profile schema with identity/geography, Chartmetric rank/score, career status, converted genres to object structure, added smart-ordered genre/mood/activity arrays, and personnel contact fields.
Playlist Metadata
api-reference/openapi/research.jsonResearchPlaylistResponse
Added ownership, editorial/personalized flags, catalog/country fields, suspicion/active-ratio scores, temporal deltas, renamed num_tracks to num_track, and introduced genre/mood/activity/tag smart-ordered arrays.
Track Analysis
api-reference/openapi/research.jsonResearchTrackResponse
Added Chartmetric statistics, tempo, and moods/activities arrays to track response schema.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Schemas bloom with richer tales,
New fields dance down audit trails—
Audiences, charts, and metrics bright,
Curators gleaming in the light,
Our API now tells stories right! 🌟

🚥 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 title clearly summarizes the main change: updating OpenAPI schemas for seven research endpoints to match actual API behavior, which is the primary purpose of this documentation-only pull request.
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 docs/research-schema-drift-fixes

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: 1

🤖 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/openapi/research.json`:
- Around line 4893-4912: Add explicit type declarations for the two permissive
schema entries: for band_members, change the schema to declare its type as
["array","null"] and ensure the array items are typed as objects (e.g., items: {
type: "object", additionalProperties: true }) while retaining nullable
semantics; for hometown_city, declare its type as ["object","null"] and add
additionalProperties: true to represent the Chartmetric hometown-city object.
Update the definitions that currently only have "nullable": true and
"description" so they include these explicit "type" and "additionalProperties"
(and "items" for band_members) entries.
🪄 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: c5399f2a-cf9b-4128-b42e-739a913deacf

📥 Commits

Reviewing files that changed from the base of the PR and between e6281b9 and aab48da.

📒 Files selected for processing (1)
  • api-reference/openapi/research.json

Comment on lines +4893 to +4912
"band_members": {
"nullable": true,
"description": "Band-member objects when known."
},
"gender": {
"type": "string",
"nullable": true
},
"gender_title": {
"type": "string",
"nullable": true
},
"pronoun_title": {
"type": "string",
"nullable": true
},
"hometown_city": {
"nullable": true,
"description": "Chartmetric hometown-city object (null when unknown)."
},
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

🏁 Script executed:

# First, examine the actual file to confirm the current state
head -n 4920 api-reference/openapi/research.json | tail -n 50

Repository: recoupable/docs

Length of output: 1463


🏁 Script executed:

# Search for test fixtures or example API responses containing band_members
rg "band_members" --type json -A 3 -B 3

Repository: recoupable/docs

Length of output: 574


🏁 Script executed:

# Search for test fixtures or example API responses containing hometown_city
rg "hometown_city" --type json -A 3 -B 3

Repository: recoupable/docs

Length of output: 537


🏁 Script executed:

# Look for other properties in the file that also lack explicit `type` but have `nullable`
rg '"nullable"\s*:\s*true' api-reference/openapi/research.json | head -20

Repository: recoupable/docs

Length of output: 644


🏁 Script executed:

# Check the OpenAPI spec version and overall schema structure
head -n 20 api-reference/openapi/research.json

Repository: recoupable/docs

Length of output: 834


🏁 Script executed:

# Search for test fixtures or example data files
find . -type f \( -name "*fixture*" -o -name "*example*" -o -name "*mock*" \) -name "*.json" | head -20

Repository: recoupable/docs

Length of output: 41


🏁 Script executed:

# Search for any TypeScript/JS type definitions or interface files that might document these fields
rg "band_members|hometown_city" --type ts --type tsx --type js -B 2 -A 2

Repository: recoupable/docs

Length of output: 86


🏁 Script executed:

# Look for any documentation or comments about the structure of these fields
rg "Band-member|hometown" -i --type md

Repository: recoupable/docs

Length of output: 41


🏁 Script executed:

# Check if there are git changes that show what this looked like before
git log --oneline -20 -- api-reference/openapi/research.json

Repository: recoupable/docs

Length of output: 131


🏁 Script executed:

# Examine the recent commit that changed the research.json
git show aab48da --stat | head -30

Repository: recoupable/docs

Length of output: 1452


🏁 Script executed:

# Look at the diff for the specific properties we're concerned with
git show aab48da -- api-reference/openapi/research.json | grep -A 10 -B 10 "band_members\|hometown_city" | head -80

Repository: recoupable/docs

Length of output: 2359


🏁 Script executed:

# Check if there's any backend code or API implementation in the repo
find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" \) | grep -E "(research|api)" | head -20

Repository: recoupable/docs

Length of output: 41


Add explicit type declarations for band_members and hometown_city.

Both properties declare only nullable: true + description with no type, making the schema permissive to any value. Based on the descriptions and OpenAPI 3.1.0 semantics, these should declare explicit types:

  • band_members: "Band-member objects when known" → likely "type": ["array", "null"] with array items typed as objects
  • hometown_city: "Chartmetric hometown-city object" → likely "type": ["object", "null"]

For consistency with the surrounding nullable: true style, add type alongside additionalProperties: true:

Suggested changes
          "band_members": {
+           "type": "array",
            "nullable": true,
+           "items": { "type": "object", "additionalProperties": true },
            "description": "Band-member objects when known."
          },
          "hometown_city": {
+           "type": "object",
            "nullable": true,
+           "additionalProperties": true,
            "description": "Chartmetric hometown-city object (null when unknown)."
          },
📝 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
"band_members": {
"nullable": true,
"description": "Band-member objects when known."
},
"gender": {
"type": "string",
"nullable": true
},
"gender_title": {
"type": "string",
"nullable": true
},
"pronoun_title": {
"type": "string",
"nullable": true
},
"hometown_city": {
"nullable": true,
"description": "Chartmetric hometown-city object (null when unknown)."
},
"band_members": {
"type": "array",
"nullable": true,
"items": { "type": "object", "additionalProperties": true },
"description": "Band-member objects when known."
},
"gender": {
"type": "string",
"nullable": true
},
"gender_title": {
"type": "string",
"nullable": true
},
"pronoun_title": {
"type": "string",
"nullable": true
},
"hometown_city": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Chartmetric hometown-city object (null when unknown)."
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/research.json` around lines 4893 - 4912, Add explicit
type declarations for the two permissive schema entries: for band_members,
change the schema to declare its type as ["array","null"] and ensure the array
items are typed as objects (e.g., items: { type: "object", additionalProperties:
true }) while retaining nullable semantics; for hometown_city, declare its type
as ["object","null"] and add additionalProperties: true to represent the
Chartmetric hometown-city object. Update the definitions that currently only
have "nullable": true and "description" so they include these explicit "type"
and "additionalProperties" (and "items" for band_members) entries.

@sweetmantech sweetmantech merged commit 4f9824d into main Apr 16, 2026
3 checks passed
@sweetmantech sweetmantech deleted the docs/research-schema-drift-fixes branch April 16, 2026 21:17
recoupableorg pushed a commit that referenced this pull request Apr 20, 2026
Combine the design/narrative overhaul (new 8-tab IA, deprecation notices,
rebuilt Agent Onboarding, achromatic design system) with all API doc updates
shipped to main since the branch diverged:

- 8 research PRs (#132-#140): schema hardening, /research/track id-proxy,
  /research/curator Chartmetric contract, /research/track/playlists, error
  responses aligned with handler enforcement
- Artist surface rename: /api/artist/socials -> /api/artists/{id}/socials
- New endpoints: artists/pin, artists/unpin, admins/agent-signups
- Removed dead surfaces: artist/segments, chat/segment, segment/fans
- Caption length default -> none

Conflict resolutions:
- docs.json: kept design IA (Overview/Chat/Research/Artists/Catalog/Content/
  Automation/Accounts), spliced in all new endpoints from main, removed
  stale nav refs to deleted surfaces
- index.mdx, quickstart.mdx: kept design copy (richer, superseded main's
  verbose endpoint listing with card-based IA)
- openapi/content.json: auto-merge preserved design's deprecation of
  /api/content/create alongside main's untouched body

research.json, accounts.json, releases.json are byte-identical to main.
131 API mdx files / 131 nav entries / 0 orphans / 0 broken intra-doc links.

Made-with: Cursor
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.

1 participant