@withpica/mcp-sdk 3.23.0 → 3.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [3.24.0] - 2026-10-09
15
+
16
+ ### Added
17
+
18
+ - `works.getThemes`, `works.setThemes`, `works.proposeThemes`, `works.reviewThemes` and
19
+ `directory.untaggedThemes` for a song's directory topics.
20
+
21
+ ### Changed — needs a MINOR bump at release
22
+
23
+ - ⚠️ **`PaginatedResult.total` is now `number | null`** (type change). An
24
+ explicit `pagination.total: null` from the server means "unknown" — a
25
+ platform-wide registry the route will not count, or a filter applied
26
+ after the read — and is passed through as `null` instead of being turned
27
+ into the page length. Code that does arithmetic on `total` must handle
28
+ `null`.
29
+ - `requestPaginated`'s fallback `has_more` (when the server sends none) is
30
+ now `offset + page < total`; it ignored the offset, so every last page of
31
+ a multi-page result reported more (row-cap T3).
32
+
33
+ ### Added
34
+
35
+ - **`syncFit` resource**: `query({ work_id?, screen_project_id?,
36
+ song_facts?, limit?, offset? })` (GET `/admin/sync-fit`), with the
37
+ `SyncFitPage`, `SyncFitRow`, `SyncFitProduction`, `SyncFitSongFacts` and
38
+ `SyncFitMeasured` types.
39
+ - `works.getThemes`, `works.setThemes`, `works.proposeThemes`, `works.reviewThemes` and
40
+ `directory.untaggedThemes` for a song's directory topics.
41
+ - Page methods that return `{ data, total, hasMore }` — the real total —
42
+ alongside the existing `list()` calls, whose return types are unchanged:
43
+ `agreements.listPage`, `bookings.listPage`, `licensing.listEnquiriesPage`,
44
+ `partyClaims.listPage`, `releases.listPage`, `sessions.listPage`,
45
+ `collaborators.listInvitesPage` / `listIncomingPage`,
46
+ `publishers.listPage` and `labels.listPage` (total `null`: platform-wide
47
+ rows are not counted; `labels.listPage` also takes `ids` for a lookup by
48
+ id). `custody.list` takes `offset`.
49
+ - `works.getAgreements(workId)` — the agreements linked to one work.
50
+ - `enrichment.previewBulkRejectProposals(input)` — what a bulk reject
51
+ would reject, resolved by the same server-side resolver, writing nothing.
52
+
53
+ ## [3.23.1] - 2026-10-07
54
+
55
+ ### Fixed
56
+
57
+ - `imports.getTemplate()` and `catalogStats()` go through the shared request
58
+ path. Both were bare `fetch()` calls without the
59
+ `x-vercel-protection-bypass` header, so on a protected Vercel preview they
60
+ never reached PICA: `getTemplate` returned Vercel's login page as the CSV
61
+ (or failed when that hop answered 500). They also skipped the timeout,
62
+ retry and typed errors.
63
+ - `requestText()` refuses a `text/html` body instead of returning it as the
64
+ file.
65
+
14
66
  ## [3.23.0] - 2026-10-04
15
67
 
16
68
  ### Added
package/dist/index.d.ts CHANGED
@@ -264,7 +264,12 @@ interface PicaClientConfig {
264
264
  }
265
265
  interface PaginatedResult<T> {
266
266
  data: T[];
267
- total: number;
267
+ /**
268
+ * The real total, or null when the server says it is unknown (a
269
+ * platform-wide registry it will not count, or a filter applied after
270
+ * the read). Never the page length dressed up as a total (row-cap T3).
271
+ */
272
+ total: number | null;
268
273
  hasMore: boolean;
269
274
  /**
270
275
  * Server-provided next-step guidance when a search legitimately returns
@@ -943,13 +948,20 @@ declare class BaseResource {
943
948
  * for routes that stream a generated file (e.g. `text/csv`) rather than
944
949
  * `{success, data}`. `request()` unconditionally calls `response.json()`,
945
950
  * which throws a SyntaxError parsing CSV text; every such route needs this
946
- * method instead (see `ImportResource.getTemplate()` for the prior
947
- * precedent this generalises).
951
+ * method instead (`ImportResource.getTemplate()`, `ExportResource.catalogCsv()`).
948
952
  *
949
953
  * `fetchWithRetry` already throws `ApiError` for non-2xx responses (reading
950
954
  * the body as text), so reaching here means `response.ok`. Still guard
951
955
  * against a 2xx JSON error envelope (`{success:false}`) via content-type,
952
956
  * since a route can commit to status 200 before a later validation step.
957
+ *
958
+ * An HTML page is refused. Neither route that uses this
959
+ * (`/admin/import/template`, `/admin/works/export` CSV formats) answers
960
+ * `text/html`, so one means something in front of PICA answered (on a
961
+ * protected Vercel preview, a missing bypass header ends on Vercel's
962
+ * login page with status 200). Returning that page as the file read as a
963
+ * success (2026-10-06, pica_import_template). Locked by
964
+ * `mcp-server/src/__tests__/sdk-request-text-and-bare-fetch.test.ts`.
953
965
  */
954
966
  protected requestText(method: string, path: string): Promise<string>;
955
967
  /**
@@ -1025,6 +1037,12 @@ declare class WorksResource extends BaseResource {
1025
1037
  */
1026
1038
  has_lyrics?: boolean;
1027
1039
  }): Promise<PaginatedResult<Work>>;
1040
+ /**
1041
+ * The agreements linked to ONE work (GET /admin/works/:id/agreements).
1042
+ * Inspect used `agreements.list()`, which returned the org's first page of
1043
+ * agreements under a work's heading (row-cap T3).
1044
+ */
1045
+ getAgreements(workId: string): Promise<any[]>;
1028
1046
  get(id: string): Promise<Work>;
1029
1047
  create(data: Partial<Work> & {
1030
1048
  create_twin?: boolean;
@@ -1170,6 +1188,49 @@ declare class WorksResource extends BaseResource {
1170
1188
  person_id?: string;
1171
1189
  }>;
1172
1190
  }>;
1191
+ /** A song's directory topics: approved, proposed, moods awaiting review, settings. */
1192
+ getThemes(workId: string): Promise<WorkThemeState>;
1193
+ /** Set the song's approved topics directly, and/or its switch and lyric visibility. */
1194
+ setThemes(workId: string, body: {
1195
+ themes?: string[];
1196
+ themes_enabled?: boolean;
1197
+ lyrics_visibility?: "themes" | "snippet" | "full";
1198
+ }): Promise<WorkThemeState>;
1199
+ /** Propose topics (and recording moods) for the owner to review. Nothing goes public. */
1200
+ proposeThemes(workId: string, body: {
1201
+ themes?: string[];
1202
+ moods?: Array<{
1203
+ recording_id: string;
1204
+ moods: string[];
1205
+ }>;
1206
+ }): Promise<WorkThemeState>;
1207
+ /** The owner's review of proposed topics and moods. */
1208
+ reviewThemes(workId: string, body: {
1209
+ approve?: string[] | "all";
1210
+ reject?: string[];
1211
+ approve_moods_for?: string[] | "all";
1212
+ reject_moods_for?: string[] | "all";
1213
+ }): Promise<WorkThemeState>;
1214
+ }
1215
+ /** GET /api/admin/works/[id]/themes (lib/services/directory/themes.ts ThemeState). */
1216
+ export interface WorkThemeState {
1217
+ work_id: string;
1218
+ title: string;
1219
+ has_lyrics: boolean;
1220
+ themes_enabled: boolean;
1221
+ lyrics_visibility: "themes" | "snippet" | "full";
1222
+ approved: Array<{
1223
+ theme: string;
1224
+ source: "owner" | "assistant";
1225
+ }>;
1226
+ proposed: Array<{
1227
+ theme: string;
1228
+ source: "owner" | "assistant";
1229
+ }>;
1230
+ proposed_moods: Array<{
1231
+ recording_id: string;
1232
+ moods: string[];
1233
+ }>;
1173
1234
  }
1174
1235
  declare class PeopleResource extends BaseResource {
1175
1236
  list(params?: {
@@ -1249,6 +1310,14 @@ declare class PeopleResource extends BaseResource {
1249
1310
  musicbrainz_id?: string;
1250
1311
  }): Promise<Record<string, unknown>>;
1251
1312
  }
1313
+ export interface LicenseEnquiryListParams {
1314
+ work_id?: string;
1315
+ status?: string;
1316
+ project_type?: string;
1317
+ territory?: string;
1318
+ limit?: number;
1319
+ offset?: number;
1320
+ }
1252
1321
  declare class LicensingResource extends BaseResource {
1253
1322
  /**
1254
1323
  * Search for sync-licensable tracks by audio characteristics
@@ -1259,16 +1328,16 @@ declare class LicensingResource extends BaseResource {
1259
1328
  */
1260
1329
  submitEnquiry(enquiry: LicenseEnquiryInput): Promise<LicenseEnquiry>;
1261
1330
  /**
1262
- * List license enquiries with optional filters
1331
+ * List license enquiries with optional filters (one page, the bare array;
1332
+ * see listEnquiriesPage for the real total).
1263
1333
  */
1264
- listEnquiries(params?: {
1265
- work_id?: string;
1266
- status?: string;
1267
- project_type?: string;
1268
- territory?: string;
1269
- limit?: number;
1270
- offset?: number;
1271
- }): Promise<LicenseEnquiry[]>;
1334
+ listEnquiries(params?: LicenseEnquiryListParams): Promise<LicenseEnquiry[]>;
1335
+ /**
1336
+ * One page of license enquiries WITH the real total and has_more
1337
+ * (row-cap T3): `listEnquiries()` returns the bare array, so callers
1338
+ * reported the page length as the total.
1339
+ */
1340
+ listEnquiriesPage(params?: LicenseEnquiryListParams): Promise<PaginatedResult<LicenseEnquiry>>;
1272
1341
  /**
1273
1342
  * Get a specific license enquiry by ID
1274
1343
  */
@@ -1290,20 +1359,27 @@ declare class LicensingResource extends BaseResource {
1290
1359
  * bookings, distinct from `LicensingResource`'s sync-license enquiries).
1291
1360
  * Wraps `/admin/bookings` + `/admin/bookings/[id]`.
1292
1361
  */
1362
+ export interface BookingListParams {
1363
+ status?: string;
1364
+ priority?: string;
1365
+ query?: string;
1366
+ enquiry_type?: string;
1367
+ follow_up_required?: boolean;
1368
+ limit?: number;
1369
+ offset?: number;
1370
+ }
1293
1371
  declare class BookingsResource extends BaseResource {
1294
1372
  /**
1295
- * List/search booking enquiries. `GET /admin/bookings` returns the raw
1296
- * array (not `{data, count}`) — `request()` unwraps to that array.
1373
+ * One page of booking enquiries (the bare array; see listPage for the real
1374
+ * total). `request()` unwraps the route's `{ data, count }` envelope.
1297
1375
  */
1298
- list(params?: {
1299
- status?: string;
1300
- priority?: string;
1301
- query?: string;
1302
- enquiry_type?: string;
1303
- follow_up_required?: boolean;
1304
- limit?: number;
1305
- offset?: number;
1306
- }): Promise<BookingEnquiry[]>;
1376
+ list(params?: BookingListParams): Promise<BookingEnquiry[]>;
1377
+ /**
1378
+ * One page of booking enquiries WITH the real total and has_more
1379
+ * (row-cap T3): `list()` returns the bare array, so callers reported the
1380
+ * page length as the total.
1381
+ */
1382
+ listPage(params?: BookingListParams): Promise<PaginatedResult<BookingEnquiry>>;
1307
1383
  get(id: string): Promise<BookingEnquiry>;
1308
1384
  /**
1309
1385
  * `PATCH /admin/bookings/[id]` only processes ONE update mode per call
@@ -1820,36 +1896,44 @@ declare class MultimediaResource extends BaseResource {
1820
1896
  }): Promise<MultimediaItem>;
1821
1897
  linkWork(id: string, workId: string, relationshipType: string, notes?: string): Promise<Record<string, unknown>>;
1822
1898
  }
1899
+ export interface AgreementListParams {
1900
+ query?: string;
1901
+ agreement_type?: string;
1902
+ status?: string;
1903
+ party_name?: string;
1904
+ includeWorkCounts?: boolean;
1905
+ /**
1906
+ * ADR-289 Wave B1 item 4 — filter to agreements in `pending_signature`
1907
+ * or `partially_signed` (ports the bespoke assistant's
1908
+ * `list_pending_signatures`). Maps to `?awaiting_signature=true` on the
1909
+ * route, which already had multi-status filtering (`statuses[]`) under
1910
+ * the hood.
1911
+ */
1912
+ awaiting_signature?: boolean;
1913
+ /** Agreements with start_date on/after this ISO date (YYYY-MM-DD). */
1914
+ start_date_from?: string;
1915
+ /** Agreements with start_date on/before this ISO date. */
1916
+ start_date_to?: string;
1917
+ /** Agreements with end_date on/after this ISO date. */
1918
+ end_date_from?: string;
1919
+ /** Agreements with end_date on/before this ISO date. */
1920
+ end_date_to?: string;
1921
+ /** Active agreements whose end_date falls within N days from today. */
1922
+ expiring_within_days?: number;
1923
+ /** true → only agreements that have an end_date; false → only open-ended. */
1924
+ has_end_date?: boolean;
1925
+ limit?: number;
1926
+ offset?: number;
1927
+ }
1823
1928
  declare class AgreementsResource extends BaseResource {
1824
- list(params?: {
1825
- query?: string;
1826
- agreement_type?: string;
1827
- status?: string;
1828
- party_name?: string;
1829
- includeWorkCounts?: boolean;
1830
- /**
1831
- * ADR-289 Wave B1 item 4 — filter to agreements in `pending_signature`
1832
- * or `partially_signed` (ports the bespoke assistant's
1833
- * `list_pending_signatures`). Maps to `?awaiting_signature=true` on the
1834
- * route, which already had multi-status filtering (`statuses[]`) under
1835
- * the hood.
1836
- */
1837
- awaiting_signature?: boolean;
1838
- /** Agreements with start_date on/after this ISO date (YYYY-MM-DD). */
1839
- start_date_from?: string;
1840
- /** Agreements with start_date on/before this ISO date. */
1841
- start_date_to?: string;
1842
- /** Agreements with end_date on/after this ISO date. */
1843
- end_date_from?: string;
1844
- /** Agreements with end_date on/before this ISO date. */
1845
- end_date_to?: string;
1846
- /** Active agreements whose end_date falls within N days from today. */
1847
- expiring_within_days?: number;
1848
- /** true → only agreements that have an end_date; false → only open-ended. */
1849
- has_end_date?: boolean;
1850
- limit?: number;
1851
- offset?: number;
1852
- }): Promise<Agreement[]>;
1929
+ /** One page of agreements (the bare array; see listPage for the real total). */
1930
+ list(params?: AgreementListParams): Promise<Agreement[]>;
1931
+ /**
1932
+ * One page of agreements WITH the real total and has_more (row-cap T3):
1933
+ * `list()` returns the bare array, so callers reported the page length
1934
+ * as the total.
1935
+ */
1936
+ listPage(params?: AgreementListParams): Promise<PaginatedResult<Agreement>>;
1853
1937
  get(id: string): Promise<{
1854
1938
  agreement: Agreement;
1855
1939
  signatureStatus: unknown;
@@ -1914,6 +1998,59 @@ declare class AgreementsResource extends BaseResource {
1914
1998
  expires_in_days?: number;
1915
1999
  }): Promise<AgreementSendForSignatureResult>;
1916
2000
  }
2001
+ /** One production behind a sync-fit match (TMDB and Wikidata facts). */
2002
+ export interface SyncFitProduction {
2003
+ tmdb_id: number | null;
2004
+ release_date: string | null;
2005
+ genres: string[];
2006
+ themes: string[];
2007
+ countries: string[];
2008
+ language: string | null;
2009
+ companies: string[];
2010
+ networks: string[];
2011
+ }
2012
+ /** One analysed master's measured facts (the MCPs' shared `measured` names). */
2013
+ export interface SyncFitMeasured {
2014
+ audio_file_id: string;
2015
+ tempo_bpm: number | null;
2016
+ key: string | null;
2017
+ mode: "major" | "minor" | null;
2018
+ duration_seconds: number | null;
2019
+ }
2020
+ export interface SyncFitSongFacts {
2021
+ genres: string[];
2022
+ language: string | null;
2023
+ measured: SyncFitMeasured[];
2024
+ }
2025
+ export interface SyncFitRow {
2026
+ work_id: string;
2027
+ screen_project_id: string;
2028
+ work_title: string | null;
2029
+ production_title: string | null;
2030
+ production_type: string | null;
2031
+ production_status: string | null;
2032
+ band: "strong" | "possible";
2033
+ reasons: string[];
2034
+ production: SyncFitProduction;
2035
+ song?: SyncFitSongFacts;
2036
+ }
2037
+ export interface SyncFitPage {
2038
+ rows: SyncFitRow[];
2039
+ total: number;
2040
+ songs: number;
2041
+ offset: number;
2042
+ limit: number;
2043
+ }
2044
+ /** Sync fit: GET /admin/sync-fit, the same read as /inspect/sync. */
2045
+ declare class SyncFitResource extends BaseResource {
2046
+ query(params?: {
2047
+ work_id?: string;
2048
+ screen_project_id?: string;
2049
+ song_facts?: boolean;
2050
+ limit?: number;
2051
+ offset?: number;
2052
+ }): Promise<SyncFitPage>;
2053
+ }
1917
2054
  declare class SyncPlacementsResource extends BaseResource {
1918
2055
  list(params?: SyncPlacementQueryParams): Promise<PaginatedResult<SyncPlacement>>;
1919
2056
  get(id: string): Promise<SyncPlacementWithRelations>;
@@ -2332,6 +2469,26 @@ declare class EnrichmentResource extends BaseResource {
2332
2469
  rejected: number;
2333
2470
  skipped: string[];
2334
2471
  }>;
2472
+ /**
2473
+ * What bulkRejectProposals would reject, without rejecting: the route
2474
+ * resolves the same pending set the real call would (row-cap T3).
2475
+ */
2476
+ previewBulkRejectProposals(input: {
2477
+ proposal_ids?: string[];
2478
+ filter?: {
2479
+ rule_id?: string;
2480
+ source?: string;
2481
+ max_confidence?: number;
2482
+ };
2483
+ }): Promise<{
2484
+ dry_run: true;
2485
+ would_affect: string[];
2486
+ /** null when exceeds_cap: the count past the cap is not read. */
2487
+ count: number | null;
2488
+ skipped: string[];
2489
+ exceeds_cap: boolean;
2490
+ cap: number;
2491
+ }>;
2335
2492
  /**
2336
2493
  * Apply many pending proposals in one call — the accept side of the
2337
2494
  * /inspect/found queue.
@@ -4024,6 +4181,22 @@ declare class CollaboratorsResource extends BaseResource {
4024
4181
  workId?: string;
4025
4182
  limit?: number;
4026
4183
  }): Promise<CollaboratorInvite[]>;
4184
+ /**
4185
+ * One page of the invites this org sent WITH the real total and has_more
4186
+ * (row-cap T3). `listInvites()` is typed as an array but the route nests
4187
+ * its rows as `data: { data, count }`, so it never carried a usable total.
4188
+ */
4189
+ listInvitesPage(params?: {
4190
+ status?: "pending" | "verified" | "confirmed" | "expired" | "cancelled" | "disputed";
4191
+ workId?: string;
4192
+ limit?: number;
4193
+ offset?: number;
4194
+ }): Promise<PaginatedResult<CollaboratorInvite>>;
4195
+ /**
4196
+ * Reads a collaborator list route, whose rows sit at `data.data` (kept
4197
+ * for published SDKs) with the total in the top-level `pagination`.
4198
+ */
4199
+ private requestNestedPage;
4027
4200
  resendInvite(inviteId: string): Promise<Record<string, unknown>>;
4028
4201
  /**
4029
4202
  * ADR-157 warm path — list invites addressed to the authenticated
@@ -4039,6 +4212,20 @@ declare class CollaboratorsResource extends BaseResource {
4039
4212
  credit_type: string;
4040
4213
  percentage_split: number | null;
4041
4214
  }>>;
4215
+ /**
4216
+ * One page of the invites addressed to the caller WITH the real total and
4217
+ * has_more (row-cap T3: `listIncoming()` returns only the rows).
4218
+ */
4219
+ listIncomingPage(params?: {
4220
+ status?: "pending" | "verified" | "confirmed" | "expired" | "cancelled" | "disputed";
4221
+ limit?: number;
4222
+ offset?: number;
4223
+ }): Promise<PaginatedResult<CollaboratorInvite & {
4224
+ work_title: string | null;
4225
+ inviter_org_name: string | null;
4226
+ credit_type: string;
4227
+ percentage_split: number | null;
4228
+ }>>;
4042
4229
  /**
4043
4230
  * ADR-157 warm path — accept an invite addressed to the authenticated
4044
4231
  * user, and flip its status to confirmed. The credit write is
@@ -4272,6 +4459,15 @@ declare class DirectoryResource extends BaseResource {
4272
4459
  eligible_work_count: number;
4273
4460
  }>;
4274
4461
  updateSettings(updates: Partial<DirectorySettings>): Promise<DirectorySettings>;
4462
+ /** Listed songs with lyrics and topics on, but no approved topic yet. */
4463
+ untaggedThemes(): Promise<{
4464
+ count: number;
4465
+ songs: Array<{
4466
+ work_id: string;
4467
+ title: string;
4468
+ pending_proposals: number;
4469
+ }>;
4470
+ }>;
4275
4471
  }
4276
4472
  declare class ProjectsResource extends BaseResource {
4277
4473
  list(params?: {
@@ -4594,6 +4790,15 @@ declare class RecordingSplitsResource extends BaseResource {
4594
4790
  verify(recordingId: string, splitId: string): Promise<any>;
4595
4791
  }
4596
4792
  declare class PublishersResource extends BaseResource {
4793
+ /**
4794
+ * One page of the publisher registry with an honest has_more. The total
4795
+ * is null: the route does not count the platform-wide registry.
4796
+ */
4797
+ listPage(params?: {
4798
+ query?: string;
4799
+ limit?: number;
4800
+ offset?: number;
4801
+ }): Promise<PaginatedResult<any>>;
4597
4802
  list(params?: {
4598
4803
  query?: string;
4599
4804
  limit?: number;
@@ -4622,6 +4827,18 @@ export interface LabelIdentifiers {
4622
4827
  deezer_label_id?: string;
4623
4828
  }
4624
4829
  declare class LabelsResource extends BaseResource {
4830
+ /**
4831
+ * One page of label/distributor organisations with an honest has_more.
4832
+ * The total is null: the route does not count platform-wide rows.
4833
+ */
4834
+ listPage(params?: {
4835
+ query?: string;
4836
+ limit?: number;
4837
+ offset?: number;
4838
+ org_type?: "label" | "distributor";
4839
+ /** Only these organisation ids — a lookup by id. */
4840
+ ids?: string[];
4841
+ }): Promise<PaginatedResult<LabelOrganisation>>;
4625
4842
  list(params?: {
4626
4843
  query?: string;
4627
4844
  limit?: number;
@@ -4677,6 +4894,12 @@ export interface PartyClaimInviteResult {
4677
4894
  * Typed against the UNWRAPPED reality (ADR-265 lesson): BaseResource.request
4678
4895
  * auto-unwraps the `{success,data}` envelope, so methods see `data` itself.
4679
4896
  */
4897
+ export interface PartyClaimListParams {
4898
+ target_organisation_id?: string;
4899
+ status?: string;
4900
+ limit?: number;
4901
+ offset?: number;
4902
+ }
4680
4903
  declare class PartyClaimsResource extends BaseResource {
4681
4904
  invite(params: {
4682
4905
  target_organisation_id: string;
@@ -4684,11 +4907,13 @@ declare class PartyClaimsResource extends BaseResource {
4684
4907
  release_id?: string;
4685
4908
  recording_id?: string;
4686
4909
  }): Promise<PartyClaimInviteResult | null>;
4687
- list(params?: {
4688
- target_organisation_id?: string;
4689
- status?: string;
4690
- limit?: number;
4691
- }): Promise<PartyClaimInviteSummary[]>;
4910
+ list(params?: PartyClaimListParams): Promise<PartyClaimInviteSummary[]>;
4911
+ /**
4912
+ * One page of sent claim invites WITH the real total and has_more
4913
+ * (row-cap T3): `list()` returns the bare array, so callers reported the
4914
+ * page length as the total.
4915
+ */
4916
+ listPage(params?: PartyClaimListParams): Promise<PaginatedResult<PartyClaimInviteSummary>>;
4692
4917
  }
4693
4918
  /** One person's outcome from POST /admin/people/claim-invites. */
4694
4919
  export interface ProfileClaimInviteOutcome {
@@ -4747,16 +4972,25 @@ declare class ProfileClaimsResource extends BaseResource {
4747
4972
  limit?: number;
4748
4973
  }): Promise<ProfileClaimStatusResult>;
4749
4974
  }
4975
+ export interface ReleaseListParams {
4976
+ limit?: number;
4977
+ offset?: number;
4978
+ query?: string;
4979
+ upc?: string;
4980
+ spotify_album_id?: string;
4981
+ release_date_from?: string;
4982
+ release_date_to?: string;
4983
+ }
4750
4984
  declare class ReleasesResource extends BaseResource {
4751
- list(params?: {
4752
- limit?: number;
4753
- offset?: number;
4754
- query?: string;
4755
- upc?: string;
4756
- spotify_album_id?: string;
4757
- release_date_from?: string;
4758
- release_date_to?: string;
4759
- }): Promise<any>;
4985
+ /** One page of releases (the bare array; see listPage for the real total). */
4986
+ list(params?: ReleaseListParams): Promise<any>;
4987
+ /**
4988
+ * One page of releases WITH the real total and has_more (row-cap T3):
4989
+ * `list()` returns the bare array, so callers guessed has_more from "the
4990
+ * page came back full". `total` is null when the server cannot count (a
4991
+ * title search past its match cap); has_more is the server's own answer.
4992
+ */
4993
+ listPage(params?: ReleaseListParams): Promise<PaginatedResult<any>>;
4760
4994
  get(id: string): Promise<any>;
4761
4995
  /**
4762
4996
  * ADR-208 Phase 3 Primitive D — fetch a server-resized ≤512px JPEG
@@ -4890,10 +5124,20 @@ declare class ReleasesResource extends BaseResource {
4890
5124
  }): Promise<any>;
4891
5125
  }
4892
5126
  declare class SessionsResource extends BaseResource {
5127
+ /** One page of upcoming sessions (see listPage for the real total). */
4893
5128
  list(params?: {
4894
5129
  limit?: number;
4895
5130
  offset?: number;
4896
5131
  }): Promise<any>;
5132
+ /**
5133
+ * One page of the next 7 days' sessions WITH the real total and has_more
5134
+ * (row-cap T3): `list()` returns the bare array, so callers could only
5135
+ * guess has_more from "the page came back full".
5136
+ */
5137
+ listPage(params?: {
5138
+ limit?: number;
5139
+ offset?: number;
5140
+ }): Promise<PaginatedResult<any>>;
4897
5141
  get(id: string): Promise<any>;
4898
5142
  create(data: Record<string, any>): Promise<any>;
4899
5143
  update(id: string, data: Record<string, any>): Promise<any>;
@@ -5202,10 +5446,16 @@ declare class CustodyResource extends BaseResource {
5202
5446
  action: "accept" | "decline" | "dispute";
5203
5447
  reason?: string;
5204
5448
  }): Promise<any>;
5449
+ /**
5450
+ * Custody claims, one page per direction. Since row-cap T3 the result also
5451
+ * carries `totals: { incoming, outgoing }` (null for a direction not asked
5452
+ * for), `has_more: { incoming, outgoing }`, `limit` and `offset`.
5453
+ */
5205
5454
  list(params?: {
5206
5455
  direction?: "incoming" | "outgoing" | "both";
5207
5456
  status?: string;
5208
5457
  limit?: number;
5458
+ offset?: number;
5209
5459
  }): Promise<any>;
5210
5460
  history(params: {
5211
5461
  work_id: string;
@@ -5452,6 +5702,7 @@ export declare class PicaClient {
5452
5702
  multimedia: MultimediaResource;
5453
5703
  agreements: AgreementsResource;
5454
5704
  syncPlacements: SyncPlacementsResource;
5705
+ syncFit: SyncFitResource;
5455
5706
  workspace: WorkspaceResource;
5456
5707
  memory: MemoryResource;
5457
5708
  audit: AuditResource;