@gscdump/contracts 1.4.0 → 1.4.2

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.
Files changed (38) hide show
  1. package/dist/analytics.d.mts +5 -3
  2. package/dist/analytics.mjs +3 -3
  3. package/dist/archetypes.d.mts +1 -1
  4. package/dist/file-resolution.d.mts +155 -0
  5. package/dist/index.d.mts +6 -3
  6. package/dist/index.mjs +4 -2
  7. package/dist/onboarding.d.mts +113 -0
  8. package/dist/onboarding.mjs +122 -0
  9. package/dist/partner.d.mts +6 -4
  10. package/dist/partner.mjs +5 -3
  11. package/dist/routes.d.mts +88 -0
  12. package/dist/{_chunks/schemas.d.mts → schemas.d.mts} +1 -88
  13. package/dist/{_chunks/schemas.mjs → schemas.mjs} +3 -137
  14. package/dist/{_chunks/types.d.mts → types.d.mts} +3 -266
  15. package/dist/v1/browser.d.mts +437 -0
  16. package/dist/v1/browser.mjs +218 -0
  17. package/dist/v1/documents.d.mts +4 -0
  18. package/dist/v1/documents.mjs +227 -0
  19. package/dist/v1/http-core.d.mts +95 -0
  20. package/dist/v1/http-core.mjs +163 -0
  21. package/dist/v1/http.d.mts +4 -0
  22. package/dist/v1/http.mjs +4 -0
  23. package/dist/v1/index.d.mts +6 -12440
  24. package/dist/v1/index.mjs +6 -5107
  25. package/dist/v1/operations.d.mts +11713 -0
  26. package/dist/v1/operations.mjs +4095 -0
  27. package/dist/v1/realtime.d.mts +670 -0
  28. package/dist/v1/realtime.mjs +468 -0
  29. package/dist/v1/server.d.mts +6 -0
  30. package/dist/v1/server.mjs +6 -0
  31. package/dist/v1/version.d.mts +2 -0
  32. package/dist/v1/version.mjs +2 -0
  33. package/dist/webhook-constants.mjs +16 -0
  34. package/package.json +26 -1
  35. package/dist/{_chunks/endpoints.d.mts → endpoints.d.mts} +0 -0
  36. package/dist/{_chunks/endpoints.mjs → endpoints.mjs} +1 -1
  37. /package/dist/{_chunks/routes.mjs → routes.mjs} +0 -0
  38. /package/dist/{_chunks/webhook-constants.d.mts → webhook-constants.d.mts} +0 -0
@@ -0,0 +1,4095 @@
1
+ import { addPartnerTeamMemberSchema, bindPartnerSiteTeamSchema, bindPartnerTeamCatalogResponseSchema, bindPartnerTeamCatalogSchema, builderStateSchema, createPartnerTeamSchema, gscComparisonFilterSchema, gscdumpAnalysisBundleResponseSchema, gscdumpAnalysisPresetSchema, gscdumpAnalysisResponseSchema, gscdumpAvailableSiteSchema, gscdumpCanonicalMismatchesResponseSchema, gscdumpDataDetailResponseSchema, gscdumpDataResponseSchema, gscdumpDeletePartnerUserResponseSchema, gscdumpIndexPercentResponseSchema, gscdumpIndexingDiagnosticsResponseSchema, gscdumpIndexingResponseSchema, gscdumpKeywordSparklinesResponseSchema, gscdumpPageTrendResponseSchema, gscdumpQueryTrendResponseSchema, gscdumpSiteRegistrationSchema, gscdumpSitemapChangesResponseSchema, gscdumpSitemapMembershipParamsSchema, gscdumpSitemapMembershipResponseSchema, gscdumpSitemapsResponseSchema, gscdumpTeamRoleSchema, gscdumpTopAssociationResponseSchema, gscdumpUserRegistrationSchema, indexingUrlsResponseSchema, partnerSiteTeamBindingResponseSchema, partnerSitemapActionResponseSchema, partnerSitemapActionSchema, partnerTeamCreatedResponseSchema, partnerTeamDeletedResponseSchema, partnerTeamMemberAddedResponseSchema, partnerTeamMemberRemovedResponseSchema, partnerTeamMemberRoleResponseSchema, partnerTeamMembersResponseSchema, partnerTeamRenamedResponseSchema, registerPartnerSiteSchema, registerPartnerUserSchema, renamePartnerTeamSchema, searchTypeSchema, siteIntIdCrosswalkResponseSchema, teamCatalogRefSchema, updatePartnerUserTokensSchema } from "../schemas.mjs";
2
+ import "./version.mjs";
3
+ import { HTTP_V1_ERROR_CODES, defineHttpOperation, defineHttpSurface, defineResponseObject, defineSuccessResponse } from "./http-core.mjs";
4
+ import { GSCDUMP_REALTIME_ACK_POLICY, GSCDUMP_REALTIME_CLOSE_CODES, GSCDUMP_REALTIME_CONNECTION_POLICY, GSCDUMP_REALTIME_LIMITS, GSCDUMP_REALTIME_PING, GSCDUMP_REALTIME_PONG, GSCDUMP_REALTIME_REPLAY_POLICY, GSCDUMP_REALTIME_SUBPROTOCOL, GSCDUMP_REALTIME_TICKET_AUDIENCE, GSCDUMP_REALTIME_TICKET_ISSUER, GSCDUMP_REALTIME_TICKET_POLICY, GSCDUMP_REALTIME_TICKET_PREFIX, REALTIME_V1_EVENT_SEMANTICS, createRealtimeV1Schemas } from "./realtime.mjs";
5
+ import { GSCDUMP_V1_ANALYTICS_DIMENSIONS, createGscdumpV1BrowserSchemas } from "./browser.mjs";
6
+ import { z } from "zod";
7
+ function errorEnvelopeSchemas(codes, publicRequestId) {
8
+ const errorDetails = z.record(z.string(), z.json());
9
+ const producer = z.strictObject({
10
+ code: z.enum(codes),
11
+ message: z.string().min(1),
12
+ requestId: publicRequestId,
13
+ retryable: z.boolean(),
14
+ details: errorDetails
15
+ });
16
+ const client = z.looseObject({
17
+ code: z.enum(codes),
18
+ message: z.string().min(1),
19
+ requestId: publicRequestId,
20
+ retryable: z.boolean(),
21
+ details: errorDetails
22
+ });
23
+ return defineResponseObject({ error: producer }, { error: client });
24
+ }
25
+ function createGscdumpV1Protocol() {
26
+ const realtimeSchemas = createRealtimeV1Schemas();
27
+ const browserSchemas = createGscdumpV1BrowserSchemas(realtimeSchemas);
28
+ const surfaceSchema = z.enum([
29
+ "partner",
30
+ "analytics",
31
+ "realtime"
32
+ ]);
33
+ const responseMeta = defineResponseObject({
34
+ requestId: realtimeSchemas.publicRequestId,
35
+ surface: surfaceSchema,
36
+ version: z.literal("1.0")
37
+ });
38
+ const partnerResponseMeta = defineResponseObject({
39
+ requestId: realtimeSchemas.publicRequestId,
40
+ surface: z.literal("partner"),
41
+ version: z.literal("1.0")
42
+ });
43
+ const realtimeResponseMeta = defineResponseObject({
44
+ requestId: realtimeSchemas.publicRequestId,
45
+ surface: z.literal("realtime"),
46
+ version: z.literal("1.0")
47
+ });
48
+ const requestMetadata = z.strictObject({
49
+ requestId: realtimeSchemas.publicRequestId,
50
+ surface: surfaceSchema,
51
+ version: z.literal("1.0")
52
+ });
53
+ const requestHeaders = z.strictObject({ "x-request-id": realtimeSchemas.publicRequestId.optional() });
54
+ const errorEnvelope = errorEnvelopeSchemas(HTTP_V1_ERROR_CODES, realtimeSchemas.publicRequestId);
55
+ const { analyticsRowsRequest, analyticsRowsResponse, lifecycleResponse } = browserSchemas;
56
+ const dimensions = GSCDUMP_V1_ANALYTICS_DIMENSIONS;
57
+ const analyticsMeta = defineResponseObject({
58
+ requestId: realtimeSchemas.publicRequestId,
59
+ surface: z.literal("analytics"),
60
+ version: z.literal("1.0"),
61
+ sourceName: z.string().min(1),
62
+ sourceKind: z.enum(["row", "sql"]),
63
+ queryMs: z.number().nonnegative()
64
+ });
65
+ const analyticsReportState = builderStateSchema.extend({ dimensions: z.array(z.enum(dimensions)).min(1) });
66
+ const analyticsListReportState = analyticsReportState.refine((state) => !state.dimensions.includes("date"), {
67
+ message: "List reports do not accept the date dimension.",
68
+ path: ["dimensions"]
69
+ });
70
+ const analyticsDetailReportState = analyticsReportState.refine((state) => state.dimensions.includes("date"), {
71
+ message: "Detail reports require the date dimension.",
72
+ path: ["dimensions"]
73
+ });
74
+ const analyticsReportRequest = z.strictObject({
75
+ state: analyticsListReportState,
76
+ comparison: analyticsListReportState.optional(),
77
+ filter: gscComparisonFilterSchema.optional()
78
+ });
79
+ const analyticsReportDetailRequest = z.strictObject({
80
+ state: analyticsDetailReportState,
81
+ comparison: analyticsDetailReportState.optional()
82
+ });
83
+ const analyticsReportData = defineResponseObject(gscdumpDataResponseSchema.shape);
84
+ const analyticsReportDetailData = defineResponseObject(gscdumpDataDetailResponseSchema.shape);
85
+ const analyticsReportResponse = defineSuccessResponse(analyticsReportData, analyticsMeta);
86
+ const analyticsReportDetailResponse = defineSuccessResponse(analyticsReportDetailData, analyticsMeta);
87
+ const integerQuery = (number, wirePattern) => z.union([number, z.string().regex(wirePattern)]);
88
+ const numericQuery = z.union([z.number(), z.string().regex(/^-?(?:\d+(?:\.\d+)?|\.\d+)$/)]);
89
+ const indexingSummaryQuery = z.strictObject({ days: integerQuery(z.number().int().min(1).max(90), /^(?:[1-9]|[1-8]\d|90)$/).optional() });
90
+ const indexingUrlsQuery = z.strictObject({
91
+ limit: integerQuery(z.number().int().min(1).max(500), /^(?:[1-9]|[1-9]\d|[1-4]\d{2}|500)$/).optional(),
92
+ offset: integerQuery(z.number().int().min(0), /^(?:0|[1-9]\d*)$/).optional(),
93
+ status: z.enum([
94
+ "indexed",
95
+ "not_indexed",
96
+ "pending"
97
+ ]).optional(),
98
+ issue: z.string().optional(),
99
+ search: z.string().optional(),
100
+ count: z.union([
101
+ z.literal(0),
102
+ z.literal(false),
103
+ z.literal("0"),
104
+ z.literal("false")
105
+ ]).optional()
106
+ });
107
+ const indexingDiagnosticsQuery = z.strictObject({
108
+ sampleIssues: z.union([z.string(), z.array(z.string())]).optional(),
109
+ sampleLimit: integerQuery(z.number().int().min(1).max(25), /^(?:[1-9]|1\d|2[0-5])$/).optional()
110
+ });
111
+ const sitemapChangesQuery = z.strictObject({ days: integerQuery(z.number().int().min(1).max(90), /^(?:[1-9]|[1-8]\d|90)$/).optional() });
112
+ const analysisBaseQueryShape = {
113
+ startDate: z.string().min(1),
114
+ endDate: z.string().min(1),
115
+ prevStartDate: z.string().min(1).optional(),
116
+ prevEndDate: z.string().min(1).optional(),
117
+ brandTerms: z.string().optional(),
118
+ limit: integerQuery(z.number().int().min(1).max(1e3), /^(?:[1-9]|[1-9]\d|[1-9]\d{2}|1000)$/).optional(),
119
+ offset: integerQuery(z.number().int().min(0), /^(?:0|[1-9]\d*)$/).optional(),
120
+ search: z.string().optional(),
121
+ minImpressions: numericQuery.optional(),
122
+ minPosition: numericQuery.optional(),
123
+ maxPosition: numericQuery.optional(),
124
+ maxCtr: numericQuery.optional(),
125
+ searchType: searchTypeSchema.optional()
126
+ };
127
+ const analysisQuery = z.strictObject({
128
+ ...analysisBaseQueryShape,
129
+ preset: gscdumpAnalysisPresetSchema
130
+ }).superRefine((value, ctx) => {
131
+ if ((value.preset === "brand-only" || value.preset === "non-brand") && !value.brandTerms?.trim()) ctx.addIssue({
132
+ code: "custom",
133
+ path: ["brandTerms"],
134
+ message: "brandTerms is required for brand/non-brand presets"
135
+ });
136
+ });
137
+ const analysisBundleQuery = z.strictObject({
138
+ ...analysisBaseQueryShape,
139
+ presets: z.union([z.array(gscdumpAnalysisPresetSchema).min(1).max(8), z.string().min(1)])
140
+ }).superRefine((value, ctx) => {
141
+ const presets = typeof value.presets === "string" ? value.presets.split(",").map((preset) => preset.trim()).filter(Boolean) : value.presets;
142
+ if (presets.length < 1 || presets.length > 8 || presets.some((preset) => !gscdumpAnalysisPresetSchema.safeParse(preset).success)) ctx.addIssue({
143
+ code: "custom",
144
+ path: ["presets"],
145
+ message: "presets must contain 1 to 8 supported presets"
146
+ });
147
+ if (presets.some((preset) => preset === "brand-only" || preset === "non-brand") && !value.brandTerms?.trim()) ctx.addIssue({
148
+ code: "custom",
149
+ path: ["brandTerms"],
150
+ message: "brandTerms is required for brand/non-brand presets"
151
+ });
152
+ if (presets.some((preset) => preset === "movers-rising" || preset === "movers-declining" || preset === "decay") && (!value.prevStartDate || !value.prevEndDate)) ctx.addIssue({
153
+ code: "custom",
154
+ path: ["prevStartDate"],
155
+ message: "Comparison presets require both previous-period dates"
156
+ });
157
+ });
158
+ const availableSitesQuery = z.strictObject({ refresh: z.union([
159
+ z.literal(true),
160
+ z.literal(1),
161
+ z.literal("true"),
162
+ z.literal("1")
163
+ ]).optional() });
164
+ const registerSiteRequest = registerPartnerSiteSchema.omit({
165
+ userId: true,
166
+ teamId: true
167
+ }).strict();
168
+ const indexingSummaryResponse = defineSuccessResponse(defineResponseObject(gscdumpIndexingResponseSchema.shape), partnerResponseMeta);
169
+ const indexingUrlsResponse = defineSuccessResponse(defineResponseObject(indexingUrlsResponseSchema.shape), partnerResponseMeta);
170
+ const indexingDiagnosticsResponse = defineSuccessResponse(defineResponseObject(gscdumpIndexingDiagnosticsResponseSchema.shape), partnerResponseMeta);
171
+ const sitemapsResponse = defineSuccessResponse(defineResponseObject(gscdumpSitemapsResponseSchema.shape), partnerResponseMeta);
172
+ const sitemapChangesResponse = defineSuccessResponse(defineResponseObject({
173
+ ...gscdumpSitemapChangesResponseSchema.shape,
174
+ summary: gscdumpSitemapChangesResponseSchema.shape.summary.unwrap()
175
+ }), partnerResponseMeta);
176
+ const analysisResponse = defineSuccessResponse(defineResponseObject(gscdumpAnalysisResponseSchema.shape), partnerResponseMeta);
177
+ const analysisBundleResponse = defineSuccessResponse(defineResponseObject(gscdumpAnalysisBundleResponseSchema.shape), partnerResponseMeta);
178
+ const availableSitesResponse = defineSuccessResponse(defineResponseObject({ sites: z.array(gscdumpAvailableSiteSchema) }), partnerResponseMeta);
179
+ const siteRegistrationResponse = defineSuccessResponse(defineResponseObject(gscdumpSiteRegistrationSchema.shape), partnerResponseMeta);
180
+ const siteDeletionResponse = defineSuccessResponse(defineResponseObject({
181
+ deleted: z.literal(true),
182
+ siteId: realtimeSchemas.publicSiteId,
183
+ siteUrl: z.string().min(1)
184
+ }), partnerResponseMeta);
185
+ const userRegistrationResponse = defineSuccessResponse(defineResponseObject(gscdumpUserRegistrationSchema.shape), partnerResponseMeta);
186
+ const userTokenUpdateResponse = defineSuccessResponse(defineResponseObject({
187
+ userId: realtimeSchemas.publicUserId,
188
+ updated: z.boolean(),
189
+ sites: z.array(gscdumpAvailableSiteSchema)
190
+ }), partnerResponseMeta);
191
+ const calendarDate = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD");
192
+ const trendQuery = z.strictObject({
193
+ startDate: calendarDate,
194
+ endDate: calendarDate,
195
+ searchType: searchTypeSchema.optional(),
196
+ prevStartDate: calendarDate.optional(),
197
+ prevEndDate: calendarDate.optional()
198
+ });
199
+ const keywordSparklinesRequest = z.strictObject({
200
+ keywords: z.array(z.string().trim().min(1)).min(1).max(20),
201
+ startDate: calendarDate,
202
+ endDate: calendarDate,
203
+ searchType: searchTypeSchema.optional()
204
+ });
205
+ const indexingInspectRequest = z.strictObject({ urls: z.array(z.string().url()).min(1).max(10) });
206
+ const canonicalMismatchesResponse = defineSuccessResponse(defineResponseObject(gscdumpCanonicalMismatchesResponseSchema.shape), partnerResponseMeta);
207
+ const keywordSparklinesResponse = defineSuccessResponse(defineResponseObject(gscdumpKeywordSparklinesResponseSchema.shape), partnerResponseMeta);
208
+ const queryTrendResponse = defineSuccessResponse(defineResponseObject(gscdumpQueryTrendResponseSchema.shape), partnerResponseMeta);
209
+ const pageTrendResponse = defineSuccessResponse(defineResponseObject(gscdumpPageTrendResponseSchema.shape), partnerResponseMeta);
210
+ const permissionRecoveryResponse = defineSuccessResponse(defineResponseObject({
211
+ success: z.boolean(),
212
+ permissionLevel: z.string().nullable(),
213
+ jobsQueued: z.number().int().nonnegative(),
214
+ message: z.string().min(1)
215
+ }), partnerResponseMeta);
216
+ const inspectionFact = z.string().nullable();
217
+ const inspectionResult = z.object({
218
+ url: z.string(),
219
+ verdict: inspectionFact,
220
+ coverageState: inspectionFact,
221
+ indexingState: inspectionFact,
222
+ robotsTxtState: inspectionFact,
223
+ pageFetchState: inspectionFact,
224
+ lastCrawlTime: inspectionFact,
225
+ crawlingUserAgent: inspectionFact,
226
+ userCanonical: inspectionFact,
227
+ googleCanonical: inspectionFact,
228
+ sitemaps: inspectionFact,
229
+ referringUrls: inspectionFact,
230
+ mobileVerdict: inspectionFact,
231
+ mobileIssues: inspectionFact,
232
+ richResultsVerdict: inspectionFact,
233
+ richResultsItems: inspectionFact,
234
+ ampVerdict: inspectionFact,
235
+ ampUrl: inspectionFact,
236
+ ampIndexingState: inspectionFact,
237
+ ampIndexStatusVerdict: inspectionFact,
238
+ ampRobotsTxtState: inspectionFact,
239
+ ampPageFetchState: inspectionFact,
240
+ ampLastCrawlTime: inspectionFact,
241
+ ampIssues: inspectionFact,
242
+ inspectionResultLink: inspectionFact
243
+ });
244
+ const indexingInspectionResponse = defineSuccessResponse(defineResponseObject({
245
+ siteId: realtimeSchemas.publicSiteId,
246
+ rateLimit: z.strictObject({
247
+ reserved: z.number().int().nonnegative(),
248
+ remaining: z.number().int().nonnegative(),
249
+ limit: z.number().int().positive()
250
+ }),
251
+ results: z.array(inspectionResult),
252
+ errors: z.array(z.strictObject({
253
+ url: z.string(),
254
+ error: z.string()
255
+ })),
256
+ skipped: z.array(z.strictObject({
257
+ url: z.string(),
258
+ reason: z.enum(["domain_mismatch", "rate_limited"])
259
+ }))
260
+ }), partnerResponseMeta);
261
+ const dateRangeQuery = z.strictObject({
262
+ startDate: calendarDate,
263
+ endDate: calendarDate
264
+ });
265
+ const siteDataMeta = z.object({
266
+ siteUrl: z.string().nullable(),
267
+ syncStatus: z.string().nullable()
268
+ });
269
+ const contentVelocityResponse = defineSuccessResponse(defineResponseObject({
270
+ weekly: z.array(z.strictObject({
271
+ week: z.string(),
272
+ newKeywords: z.number().int().nonnegative(),
273
+ totalKeywords: z.number().int().nonnegative()
274
+ })),
275
+ summary: z.strictObject({
276
+ totalNewKeywords: z.number().int().nonnegative(),
277
+ avgPerWeek: z.number().nonnegative(),
278
+ trend: z.enum([
279
+ "stable",
280
+ "accelerating",
281
+ "decelerating"
282
+ ])
283
+ }),
284
+ meta: siteDataMeta
285
+ }), partnerResponseMeta);
286
+ const ctrOutlier = z.strictObject({
287
+ query: z.string(),
288
+ clicks: z.number(),
289
+ impressions: z.number(),
290
+ ctr: z.number(),
291
+ position: z.number(),
292
+ expectedCtr: z.number(),
293
+ ctrDiff: z.number()
294
+ });
295
+ const ctrCurveResponse = defineSuccessResponse(defineResponseObject({
296
+ curve: z.array(z.strictObject({
297
+ bucket: z.string(),
298
+ avgCtr: z.number(),
299
+ medianPosition: z.number(),
300
+ keywordCount: z.number(),
301
+ totalClicks: z.number(),
302
+ totalImpressions: z.number()
303
+ })),
304
+ overperforming: z.array(ctrOutlier),
305
+ underperforming: z.array(ctrOutlier),
306
+ meta: siteDataMeta
307
+ }), partnerResponseMeta);
308
+ const darkTrafficResponse = defineSuccessResponse(defineResponseObject({
309
+ summary: z.strictObject({
310
+ totalClicks: z.number(),
311
+ attributedClicks: z.number(),
312
+ darkClicks: z.number(),
313
+ darkPercent: z.number(),
314
+ totalImpressions: z.number(),
315
+ attributedImpressions: z.number()
316
+ }),
317
+ pages: z.array(z.strictObject({
318
+ url: z.string(),
319
+ totalClicks: z.number(),
320
+ attributedClicks: z.number(),
321
+ darkClicks: z.number(),
322
+ darkPercent: z.number(),
323
+ keywordCount: z.number()
324
+ })),
325
+ meta: siteDataMeta
326
+ }), partnerResponseMeta);
327
+ const deviceGapMetrics = z.strictObject({
328
+ clicks: z.number(),
329
+ impressions: z.number(),
330
+ ctr: z.number(),
331
+ position: z.number()
332
+ });
333
+ const deviceGapResponse = defineSuccessResponse(defineResponseObject({
334
+ daily: z.array(z.strictObject({
335
+ date: z.string(),
336
+ desktop: deviceGapMetrics,
337
+ mobile: deviceGapMetrics,
338
+ gaps: z.strictObject({
339
+ ctrGap: z.number(),
340
+ positionGap: z.number()
341
+ })
342
+ })),
343
+ summary: z.strictObject({
344
+ avgCtrGap: z.number(),
345
+ avgPositionGap: z.number(),
346
+ ctrGapTrend: z.enum([
347
+ "stable",
348
+ "improving",
349
+ "worsening"
350
+ ]),
351
+ positionGapTrend: z.enum([
352
+ "stable",
353
+ "improving",
354
+ "worsening"
355
+ ])
356
+ }).nullable(),
357
+ meta: siteDataMeta
358
+ }), partnerResponseMeta);
359
+ const keywordBreadthPage = z.strictObject({
360
+ url: z.string(),
361
+ keywordCount: z.number(),
362
+ clicks: z.number(),
363
+ impressions: z.number()
364
+ });
365
+ const keywordBreadthResponse = defineSuccessResponse(defineResponseObject({
366
+ distribution: z.array(z.strictObject({
367
+ bucket: z.string(),
368
+ pageCount: z.number()
369
+ })),
370
+ fragilePages: z.array(keywordBreadthPage),
371
+ authorityPages: z.array(keywordBreadthPage),
372
+ summary: z.strictObject({
373
+ totalPages: z.number(),
374
+ avgKeywordsPerPage: z.number(),
375
+ fragileCount: z.number(),
376
+ authorityCount: z.number()
377
+ }),
378
+ meta: siteDataMeta
379
+ }), partnerResponseMeta);
380
+ const positionDistributionResponse = defineSuccessResponse(defineResponseObject({
381
+ distribution: z.array(z.strictObject({
382
+ date: z.string(),
383
+ pos_1_3: z.number(),
384
+ pos_4_10: z.number(),
385
+ pos_11_20: z.number(),
386
+ pos_20_plus: z.number(),
387
+ total: z.number()
388
+ })),
389
+ meta: siteDataMeta
390
+ }), partnerResponseMeta);
391
+ const topAssociationQuery = z.strictObject({
392
+ type: z.enum(["topPage", "topKeyword"]),
393
+ identifier: z.string().min(1),
394
+ startDate: calendarDate,
395
+ endDate: calendarDate
396
+ });
397
+ const topAssociationResponse = defineSuccessResponse(defineResponseObject(gscdumpTopAssociationResponseSchema.shape), partnerResponseMeta);
398
+ const indexPercentQuery = z.strictObject({
399
+ invisibleLimit: z.coerce.number().int().min(1).max(500).optional(),
400
+ invisibleOffset: z.coerce.number().int().min(0).max(1e6).optional(),
401
+ orphanLimit: z.coerce.number().int().min(1).max(500).optional()
402
+ });
403
+ const indexPercentResponse = defineSuccessResponse(defineResponseObject(gscdumpIndexPercentResponseSchema.shape), partnerResponseMeta);
404
+ const contentVelocityQuery = z.strictObject({ days: z.coerce.number().int().min(1).max(365).optional() });
405
+ const sitemapActionRequest = partnerSitemapActionSchema;
406
+ const sitemapActionResponse = defineSuccessResponse({
407
+ producer: partnerSitemapActionResponseSchema,
408
+ client: partnerSitemapActionResponseSchema
409
+ }, partnerResponseMeta);
410
+ const sitemapMembershipRequest = gscdumpSitemapMembershipParamsSchema.strict();
411
+ const sitemapMembershipResponse = defineSuccessResponse(defineResponseObject(gscdumpSitemapMembershipResponseSchema.shape), partnerResponseMeta);
412
+ const createTeamRequest = createPartnerTeamSchema.strict();
413
+ const teamCreatedResponse = defineSuccessResponse(defineResponseObject(partnerTeamCreatedResponseSchema.shape), partnerResponseMeta);
414
+ const renameTeamRequest = renamePartnerTeamSchema.strict();
415
+ const teamRenamedResponse = defineSuccessResponse(defineResponseObject(partnerTeamRenamedResponseSchema.shape), partnerResponseMeta);
416
+ const teamDeletedResponse = defineSuccessResponse(defineResponseObject(partnerTeamDeletedResponseSchema.shape), partnerResponseMeta);
417
+ const teamMembersResponse = defineSuccessResponse(defineResponseObject(partnerTeamMembersResponseSchema.shape), partnerResponseMeta);
418
+ const addTeamMemberRequest = addPartnerTeamMemberSchema.strict();
419
+ const teamMemberAddedResponse = defineSuccessResponse(defineResponseObject(partnerTeamMemberAddedResponseSchema.shape), partnerResponseMeta);
420
+ const updateTeamMemberRoleRequest = z.strictObject({ role: gscdumpTeamRoleSchema });
421
+ const teamMemberRoleResponse = defineSuccessResponse(defineResponseObject(partnerTeamMemberRoleResponseSchema.shape), partnerResponseMeta);
422
+ const teamMemberRemovedResponse = defineSuccessResponse(defineResponseObject(partnerTeamMemberRemovedResponseSchema.shape), partnerResponseMeta);
423
+ const bindSiteTeamRequest = bindPartnerSiteTeamSchema.strict();
424
+ const siteTeamBindingResponse = defineSuccessResponse(defineResponseObject(partnerSiteTeamBindingResponseSchema.shape), partnerResponseMeta);
425
+ const teamCatalogResponse = defineSuccessResponse(defineResponseObject(teamCatalogRefSchema.shape), partnerResponseMeta);
426
+ const bindTeamCatalogRequest = bindPartnerTeamCatalogSchema.strict();
427
+ const teamCatalogBindResponse = defineSuccessResponse(defineResponseObject(bindPartnerTeamCatalogResponseSchema.shape), partnerResponseMeta);
428
+ const siteIntIdCrosswalkResponse = defineSuccessResponse(defineResponseObject(siteIntIdCrosswalkResponseSchema.shape), partnerResponseMeta);
429
+ const deletePartnerUserResponse = defineSuccessResponse(defineResponseObject(gscdumpDeletePartnerUserResponseSchema.shape), partnerResponseMeta);
430
+ const verificationMethodSchema = z.enum([
431
+ "META",
432
+ "FILE",
433
+ "DNS_TXT",
434
+ "DNS_CNAME",
435
+ "ANALYTICS",
436
+ "TAG_MANAGER"
437
+ ]);
438
+ const verificationTokenRequest = z.strictObject({
439
+ siteUrl: z.string().min(1),
440
+ method: verificationMethodSchema.optional()
441
+ });
442
+ const verificationSiteShape = z.object({
443
+ type: z.string(),
444
+ identifier: z.string()
445
+ }).loose();
446
+ const verificationTokenResponse = defineSuccessResponse(defineResponseObject({
447
+ siteUrl: z.string(),
448
+ site: verificationSiteShape,
449
+ method: z.string(),
450
+ token: z.string(),
451
+ metaContent: z.string().nullable(),
452
+ dnsRecord: z.object({
453
+ type: z.enum(["TXT", "CNAME"]),
454
+ host: z.string(),
455
+ value: z.string()
456
+ }).nullable()
457
+ }), partnerResponseMeta);
458
+ const addAndVerifySiteRequest = verificationTokenRequest;
459
+ const addAndVerifySiteResponse = defineSuccessResponse(defineResponseObject({
460
+ siteUrl: z.string(),
461
+ site: verificationSiteShape,
462
+ method: z.string(),
463
+ verified: z.literal(true),
464
+ owners: z.array(z.string()).optional()
465
+ }), partnerResponseMeta);
466
+ const crossSourceRequest = z.strictObject({
467
+ queryKey: z.enum([
468
+ "crawl-error-losing-impressions",
469
+ "declining-clicks-poor-lcp",
470
+ "striking-distance-slow-pages",
471
+ "top-impressions-low-performance"
472
+ ]),
473
+ rangeDays: z.number().int().positive().max(180).optional(),
474
+ limit: z.number().int().positive().max(500).optional()
475
+ });
476
+ const crossSourceResponse = defineSuccessResponse(defineResponseObject({
477
+ reason: z.string().optional(),
478
+ sources: z.array(z.string()),
479
+ rows: z.array(z.record(z.string(), z.json()))
480
+ }), partnerResponseMeta);
481
+ const enrichKeywordsRequest = z.strictObject({ keywords: z.array(z.string().min(1)).min(1).max(500) });
482
+ const enrichKeywordsResponse = defineSuccessResponse(defineResponseObject({ metrics: z.record(z.string(), z.object({
483
+ difficulty: z.number().nullable(),
484
+ searchVolume: z.number().nullable(),
485
+ cpc: z.number().nullable()
486
+ }).loose()) }), partnerResponseMeta);
487
+ const responseStreamHead = defineResponseObject({
488
+ streamId: realtimeSchemas.streamId,
489
+ sequence: realtimeSchemas.sequence
490
+ });
491
+ const headResponse = defineSuccessResponse(defineResponseObject({ head: responseStreamHead.producer }, { head: responseStreamHead.client }), realtimeResponseMeta);
492
+ const ticketDataProducerShape = {
493
+ socketUrl: z.url().refine((value) => value.startsWith("wss://"), "socketUrl must use wss."),
494
+ protocol: z.literal(GSCDUMP_REALTIME_SUBPROTOCOL),
495
+ protocolVersion: z.literal(1),
496
+ ticket: z.string().max(GSCDUMP_REALTIME_TICKET_POLICY.maxBytes).regex(/^gscdump\.ticket\.v1\.[\w-]+\.[\w-]+$/),
497
+ expiresAt: z.iso.datetime(),
498
+ head: responseStreamHead.producer,
499
+ maxConnectionSeconds: z.literal(900)
500
+ };
501
+ const ticketResponse = {
502
+ producer: z.strictObject({
503
+ data: z.strictObject(ticketDataProducerShape),
504
+ meta: realtimeResponseMeta.producer
505
+ }),
506
+ client: realtimeSchemas.ticketResponseClient
507
+ };
508
+ const partnerUserLifecycleErrors = [
509
+ "invalid_request",
510
+ "unauthorized",
511
+ "forbidden",
512
+ "user_not_found",
513
+ "rate_limited",
514
+ "internal_error",
515
+ "contract_violation"
516
+ ];
517
+ const partnerSiteErrors = [
518
+ "invalid_request",
519
+ "unauthorized",
520
+ "forbidden",
521
+ "site_not_found",
522
+ "rate_limited",
523
+ "internal_error",
524
+ "contract_violation"
525
+ ];
526
+ const partnerUserErrors = [
527
+ "invalid_request",
528
+ "unauthorized",
529
+ "forbidden",
530
+ "user_not_found",
531
+ "rate_limited",
532
+ "internal_error",
533
+ "contract_violation"
534
+ ];
535
+ const analyticsRowsErrors = [
536
+ "invalid_request",
537
+ "unauthorized",
538
+ "forbidden",
539
+ "site_not_found",
540
+ "rate_limited",
541
+ "internal_error",
542
+ "contract_violation"
543
+ ];
544
+ const realtimeErrors = [
545
+ "invalid_request",
546
+ "unauthorized",
547
+ "forbidden",
548
+ "rate_limited",
549
+ "realtime_unavailable",
550
+ "internal_error",
551
+ "contract_violation"
552
+ ];
553
+ const partner = defineHttpSurface({
554
+ name: "partner",
555
+ prefix: "/api/partner/v1",
556
+ version: "1.0",
557
+ operations: {
558
+ getUserLifecycle: defineHttpOperation({
559
+ id: "partner.users.lifecycle.get",
560
+ method: "GET",
561
+ path: "/users/{userId}/lifecycle",
562
+ visibility: "public",
563
+ semantics: {
564
+ kind: "query",
565
+ sideEffects: "none",
566
+ idempotent: true,
567
+ retry: "idempotent",
568
+ readConsistency: "primary"
569
+ },
570
+ auth: {
571
+ credentials: ["user_key", "partner_key"],
572
+ scopes: ["users:read"],
573
+ ownership: [{
574
+ credential: "user_key",
575
+ rule: "self"
576
+ }, {
577
+ credential: "partner_key",
578
+ rule: "linked_user"
579
+ }]
580
+ },
581
+ request: {
582
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
583
+ query: null,
584
+ headers: requestHeaders,
585
+ body: null
586
+ },
587
+ responses: { 200: lifecycleResponse },
588
+ errors: partnerUserLifecycleErrors,
589
+ errorResponse: errorEnvelopeSchemas(partnerUserLifecycleErrors, realtimeSchemas.publicRequestId),
590
+ resources: {
591
+ reads: [{
592
+ type: "partner.user",
593
+ idFrom: "params.userId"
594
+ }, {
595
+ type: "user.sites",
596
+ idFrom: "params.userId"
597
+ }],
598
+ changes: []
599
+ },
600
+ lifecycle: { introduced: "1.0.0" },
601
+ docs: {
602
+ summary: "Get user lifecycle",
603
+ description: "Returns the authoritative lifecycle state for one visible user and their sites.",
604
+ tags: ["Users"],
605
+ examples: {
606
+ request: { params: { userId: "u_01" } },
607
+ response: {
608
+ data: {
609
+ userId: "u_01",
610
+ partnerId: "p_01",
611
+ currentTeamId: null,
612
+ account: {
613
+ status: "ready",
614
+ grantedScopes: ["https://www.googleapis.com/auth/webmasters.readonly"],
615
+ missingScopes: [],
616
+ nextAction: "none"
617
+ },
618
+ sites: []
619
+ },
620
+ meta: {
621
+ requestId: "req_01",
622
+ surface: "partner",
623
+ version: "1.0"
624
+ }
625
+ }
626
+ }
627
+ }
628
+ }),
629
+ listAvailableSites: defineHttpOperation({
630
+ id: "partner.users.sites.available.list",
631
+ method: "GET",
632
+ path: "/users/{userId}/available-sites",
633
+ visibility: "public",
634
+ semantics: {
635
+ kind: "query",
636
+ sideEffects: "none",
637
+ idempotent: true,
638
+ retry: "idempotent",
639
+ readConsistency: "primary"
640
+ },
641
+ auth: {
642
+ credentials: ["user_key", "partner_key"],
643
+ scopes: ["sites:read"],
644
+ ownership: [{
645
+ credential: "user_key",
646
+ rule: "self"
647
+ }, {
648
+ credential: "partner_key",
649
+ rule: "linked_user"
650
+ }]
651
+ },
652
+ request: {
653
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
654
+ query: availableSitesQuery,
655
+ headers: requestHeaders,
656
+ body: null
657
+ },
658
+ responses: { 200: availableSitesResponse },
659
+ errors: partnerUserErrors,
660
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
661
+ resources: {
662
+ reads: [{
663
+ type: "partner.user",
664
+ idFrom: "params.userId"
665
+ }, {
666
+ type: "user.sites",
667
+ idFrom: "params.userId"
668
+ }],
669
+ changes: []
670
+ },
671
+ lifecycle: { introduced: "1.0.0" },
672
+ docs: {
673
+ summary: "List available Search Console properties",
674
+ description: "Lists the visible Google Search Console properties and their registration state.",
675
+ tags: ["Sites"],
676
+ examples: {
677
+ request: {
678
+ params: { userId: "u_01" },
679
+ query: {}
680
+ },
681
+ response: {
682
+ data: { sites: [] },
683
+ meta: {
684
+ requestId: "req_01",
685
+ surface: "partner",
686
+ version: "1.0"
687
+ }
688
+ }
689
+ }
690
+ }
691
+ }),
692
+ createSite: defineHttpOperation({
693
+ id: "partner.users.sites.create",
694
+ method: "POST",
695
+ path: "/users/{userId}/sites",
696
+ visibility: "public",
697
+ semantics: {
698
+ kind: "mutation",
699
+ sideEffects: "state",
700
+ idempotent: true,
701
+ retry: "idempotent",
702
+ readConsistency: null
703
+ },
704
+ auth: {
705
+ credentials: ["user_key", "partner_key"],
706
+ scopes: ["sites:write"],
707
+ ownership: [{
708
+ credential: "user_key",
709
+ rule: "self"
710
+ }, {
711
+ credential: "partner_key",
712
+ rule: "linked_user"
713
+ }]
714
+ },
715
+ request: {
716
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
717
+ query: null,
718
+ headers: requestHeaders,
719
+ body: registerSiteRequest
720
+ },
721
+ responses: { 200: siteRegistrationResponse },
722
+ errors: partnerUserErrors,
723
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
724
+ resources: {
725
+ reads: [{
726
+ type: "partner.user",
727
+ idFrom: "params.userId"
728
+ }],
729
+ changes: [{
730
+ type: "site.registration",
731
+ idFrom: "params.userId"
732
+ }]
733
+ },
734
+ lifecycle: { introduced: "1.0.0" },
735
+ docs: {
736
+ summary: "Register a site",
737
+ description: "Registers one Search Console property for an authorized user.",
738
+ tags: ["Sites"],
739
+ examples: {
740
+ request: {
741
+ params: { userId: "u_01" },
742
+ body: { siteUrl: "sc-domain:example.com" }
743
+ },
744
+ response: {
745
+ data: {
746
+ siteId: "s_01",
747
+ status: "pending"
748
+ },
749
+ meta: {
750
+ requestId: "req_01",
751
+ surface: "partner",
752
+ version: "1.0"
753
+ }
754
+ }
755
+ }
756
+ }
757
+ }),
758
+ createUser: defineHttpOperation({
759
+ id: "partner.users.create",
760
+ method: "POST",
761
+ path: "/users",
762
+ visibility: "public",
763
+ semantics: {
764
+ kind: "mutation",
765
+ sideEffects: "state",
766
+ idempotent: true,
767
+ retry: "idempotent",
768
+ readConsistency: null
769
+ },
770
+ auth: {
771
+ credentials: ["partner_key"],
772
+ scopes: ["users:write"],
773
+ ownership: [{
774
+ credential: "partner_key",
775
+ rule: "partner_tenant"
776
+ }]
777
+ },
778
+ request: {
779
+ params: null,
780
+ query: null,
781
+ headers: requestHeaders,
782
+ body: registerPartnerUserSchema.strict()
783
+ },
784
+ responses: { 200: userRegistrationResponse },
785
+ errors: partnerUserErrors,
786
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
787
+ resources: {
788
+ reads: [],
789
+ changes: [{
790
+ type: "partner.user",
791
+ idFrom: "principal.id"
792
+ }]
793
+ },
794
+ lifecycle: { introduced: "1.0.0" },
795
+ docs: {
796
+ summary: "Register a partner user",
797
+ description: "Creates or updates a user owned by the authenticated partner tenant.",
798
+ tags: ["Users"],
799
+ examples: {
800
+ request: { body: {
801
+ userGoogleId: "google_01",
802
+ userEmail: "owner@example.com",
803
+ accessToken: "token",
804
+ refreshToken: "refresh"
805
+ } },
806
+ response: {
807
+ data: {
808
+ userId: "u_01",
809
+ status: "provisioning"
810
+ },
811
+ meta: {
812
+ requestId: "req_01",
813
+ surface: "partner",
814
+ version: "1.0"
815
+ }
816
+ }
817
+ }
818
+ }
819
+ }),
820
+ updateUserTokens: defineHttpOperation({
821
+ id: "partner.users.tokens.update",
822
+ method: "PATCH",
823
+ path: "/users/{userId}/tokens",
824
+ visibility: "public",
825
+ semantics: {
826
+ kind: "mutation",
827
+ sideEffects: "state",
828
+ idempotent: true,
829
+ retry: "idempotent",
830
+ readConsistency: null
831
+ },
832
+ auth: {
833
+ credentials: ["partner_key"],
834
+ scopes: ["users:write"],
835
+ ownership: [{
836
+ credential: "partner_key",
837
+ rule: "linked_user"
838
+ }]
839
+ },
840
+ request: {
841
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
842
+ query: null,
843
+ headers: requestHeaders,
844
+ body: updatePartnerUserTokensSchema.strict()
845
+ },
846
+ responses: { 200: userTokenUpdateResponse },
847
+ errors: partnerUserErrors,
848
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
849
+ resources: {
850
+ reads: [{
851
+ type: "partner.user",
852
+ idFrom: "params.userId"
853
+ }],
854
+ changes: [{
855
+ type: "partner.user",
856
+ idFrom: "params.userId"
857
+ }]
858
+ },
859
+ lifecycle: { introduced: "1.0.0" },
860
+ docs: {
861
+ summary: "Update user OAuth tokens",
862
+ description: "Replaces the Google OAuth grant for a partner-linked user.",
863
+ tags: ["Users"],
864
+ examples: {
865
+ request: {
866
+ params: { userId: "u_01" },
867
+ body: {
868
+ accessToken: "token",
869
+ refreshToken: "refresh"
870
+ }
871
+ },
872
+ response: {
873
+ data: {
874
+ userId: "u_01",
875
+ updated: true,
876
+ sites: []
877
+ },
878
+ meta: {
879
+ requestId: "req_01",
880
+ surface: "partner",
881
+ version: "1.0"
882
+ }
883
+ }
884
+ }
885
+ }
886
+ }),
887
+ getSiteIndexing: defineHttpOperation({
888
+ id: "partner.sites.indexing.get",
889
+ method: "GET",
890
+ path: "/sites/{siteId}/indexing",
891
+ visibility: "public",
892
+ semantics: {
893
+ kind: "query",
894
+ sideEffects: "none",
895
+ idempotent: true,
896
+ retry: "idempotent",
897
+ readConsistency: "primary"
898
+ },
899
+ auth: {
900
+ credentials: ["user_key", "partner_key"],
901
+ scopes: ["indexing:read"],
902
+ ownership: [{
903
+ credential: "user_key",
904
+ rule: "authorized_site"
905
+ }, {
906
+ credential: "partner_key",
907
+ rule: "authorized_site"
908
+ }]
909
+ },
910
+ request: {
911
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
912
+ query: indexingSummaryQuery,
913
+ headers: requestHeaders,
914
+ body: null
915
+ },
916
+ responses: { 200: indexingSummaryResponse },
917
+ errors: partnerSiteErrors,
918
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
919
+ resources: {
920
+ reads: [{
921
+ type: "site.indexing",
922
+ idFrom: "params.siteId"
923
+ }],
924
+ changes: []
925
+ },
926
+ lifecycle: { introduced: "1.0.0" },
927
+ docs: {
928
+ summary: "Get site indexing summary",
929
+ description: "Returns indexing coverage, trend, and inspection signal totals.",
930
+ tags: ["Indexing"],
931
+ examples: {
932
+ request: {
933
+ params: { siteId: "s_01" },
934
+ query: { days: 28 }
935
+ },
936
+ response: {
937
+ data: {
938
+ trend: [],
939
+ summary: {
940
+ totalUrls: 0,
941
+ indexed: 0,
942
+ notIndexed: 0,
943
+ pending: 0,
944
+ indexedPercent: 0,
945
+ oldestCheck: null,
946
+ newestCheck: null,
947
+ change7d: null,
948
+ change28d: null,
949
+ signals: {
950
+ mobilePass: 0,
951
+ mobileFail: 0,
952
+ mobileUnspecified: 0,
953
+ richResultsPass: 0,
954
+ richResultsFail: 0,
955
+ richResultTypes: [],
956
+ crawlingMobile: 0,
957
+ crawlingDesktop: 0
958
+ }
959
+ },
960
+ meta: {
961
+ siteUrl: "sc-domain:example.com",
962
+ syncStatus: "synced",
963
+ indexingStatus: "complete",
964
+ indexingProgress: 100,
965
+ sitemapTotal: 0,
966
+ inspectedCount: 0,
967
+ noSitemapsSubmitted: false,
968
+ sitemapsPending: false
969
+ }
970
+ },
971
+ meta: {
972
+ requestId: "req_01",
973
+ surface: "partner",
974
+ version: "1.0"
975
+ }
976
+ }
977
+ }
978
+ }
979
+ }),
980
+ listSiteIndexingUrls: defineHttpOperation({
981
+ id: "partner.sites.indexing.urls.list",
982
+ method: "GET",
983
+ path: "/sites/{siteId}/indexing/urls",
984
+ visibility: "public",
985
+ semantics: {
986
+ kind: "query",
987
+ sideEffects: "none",
988
+ idempotent: true,
989
+ retry: "idempotent",
990
+ readConsistency: "primary"
991
+ },
992
+ auth: {
993
+ credentials: ["user_key", "partner_key"],
994
+ scopes: ["indexing:read"],
995
+ ownership: [{
996
+ credential: "user_key",
997
+ rule: "authorized_site"
998
+ }, {
999
+ credential: "partner_key",
1000
+ rule: "authorized_site"
1001
+ }]
1002
+ },
1003
+ request: {
1004
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1005
+ query: indexingUrlsQuery,
1006
+ headers: requestHeaders,
1007
+ body: null
1008
+ },
1009
+ responses: { 200: indexingUrlsResponse },
1010
+ errors: partnerSiteErrors,
1011
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1012
+ resources: {
1013
+ reads: [{
1014
+ type: "site.indexing",
1015
+ idFrom: "params.siteId"
1016
+ }],
1017
+ changes: []
1018
+ },
1019
+ lifecycle: { introduced: "1.0.0" },
1020
+ docs: {
1021
+ summary: "List indexed URLs",
1022
+ description: "Returns the filtered URL-inspection index with pagination metadata.",
1023
+ tags: ["Indexing"],
1024
+ examples: {
1025
+ request: {
1026
+ params: { siteId: "s_01" },
1027
+ query: {
1028
+ limit: 100,
1029
+ offset: 0
1030
+ }
1031
+ },
1032
+ response: {
1033
+ data: {
1034
+ urls: [],
1035
+ pagination: {
1036
+ total: 0,
1037
+ limit: 100,
1038
+ offset: 0,
1039
+ hasMore: false
1040
+ },
1041
+ meta: {
1042
+ siteUrl: "sc-domain:example.com",
1043
+ status: "all",
1044
+ issue: null
1045
+ }
1046
+ },
1047
+ meta: {
1048
+ requestId: "req_01",
1049
+ surface: "partner",
1050
+ version: "1.0"
1051
+ }
1052
+ }
1053
+ }
1054
+ }
1055
+ }),
1056
+ getSiteIndexingDiagnostics: defineHttpOperation({
1057
+ id: "partner.sites.indexing.diagnostics.get",
1058
+ method: "GET",
1059
+ path: "/sites/{siteId}/indexing/diagnostics",
1060
+ visibility: "public",
1061
+ semantics: {
1062
+ kind: "query",
1063
+ sideEffects: "none",
1064
+ idempotent: true,
1065
+ retry: "idempotent",
1066
+ readConsistency: "primary"
1067
+ },
1068
+ auth: {
1069
+ credentials: ["user_key", "partner_key"],
1070
+ scopes: ["indexing:read"],
1071
+ ownership: [{
1072
+ credential: "user_key",
1073
+ rule: "authorized_site"
1074
+ }, {
1075
+ credential: "partner_key",
1076
+ rule: "authorized_site"
1077
+ }]
1078
+ },
1079
+ request: {
1080
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1081
+ query: indexingDiagnosticsQuery,
1082
+ headers: requestHeaders,
1083
+ body: null
1084
+ },
1085
+ responses: { 200: indexingDiagnosticsResponse },
1086
+ errors: partnerSiteErrors,
1087
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1088
+ resources: {
1089
+ reads: [{
1090
+ type: "site.indexing",
1091
+ idFrom: "params.siteId"
1092
+ }],
1093
+ changes: []
1094
+ },
1095
+ lifecycle: { introduced: "1.0.0" },
1096
+ docs: {
1097
+ summary: "Get indexing diagnostics",
1098
+ description: "Returns indexing issue groups and optional URL samples.",
1099
+ tags: ["Indexing"],
1100
+ examples: {
1101
+ request: {
1102
+ params: { siteId: "s_01" },
1103
+ query: {}
1104
+ },
1105
+ response: {
1106
+ data: {
1107
+ summary: {
1108
+ totalUrls: 0,
1109
+ indexed: 0,
1110
+ indexedPercent: 0
1111
+ },
1112
+ issues: [],
1113
+ meta: { siteUrl: "sc-domain:example.com" }
1114
+ },
1115
+ meta: {
1116
+ requestId: "req_01",
1117
+ surface: "partner",
1118
+ version: "1.0"
1119
+ }
1120
+ }
1121
+ }
1122
+ }
1123
+ }),
1124
+ getSiteSitemaps: defineHttpOperation({
1125
+ id: "partner.sites.sitemaps.get",
1126
+ method: "GET",
1127
+ path: "/sites/{siteId}/sitemaps",
1128
+ visibility: "public",
1129
+ semantics: {
1130
+ kind: "query",
1131
+ sideEffects: "none",
1132
+ idempotent: true,
1133
+ retry: "idempotent",
1134
+ readConsistency: "primary"
1135
+ },
1136
+ auth: {
1137
+ credentials: ["user_key", "partner_key"],
1138
+ scopes: ["sitemaps:read"],
1139
+ ownership: [{
1140
+ credential: "user_key",
1141
+ rule: "authorized_site"
1142
+ }, {
1143
+ credential: "partner_key",
1144
+ rule: "authorized_site"
1145
+ }]
1146
+ },
1147
+ request: {
1148
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1149
+ query: null,
1150
+ headers: requestHeaders,
1151
+ body: null
1152
+ },
1153
+ responses: { 200: sitemapsResponse },
1154
+ errors: partnerSiteErrors,
1155
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1156
+ resources: {
1157
+ reads: [{
1158
+ type: "site.sitemaps",
1159
+ idFrom: "params.siteId"
1160
+ }],
1161
+ changes: []
1162
+ },
1163
+ lifecycle: { introduced: "1.0.0" },
1164
+ docs: {
1165
+ summary: "Get sitemap snapshot",
1166
+ description: "Returns registered sitemaps and their aggregate and per-sitemap history.",
1167
+ tags: ["Sitemaps"],
1168
+ examples: {
1169
+ request: { params: { siteId: "s_01" } },
1170
+ response: {
1171
+ data: {
1172
+ sitemaps: [],
1173
+ history: [],
1174
+ perSitemapHistory: {},
1175
+ meta: {
1176
+ siteUrl: "sc-domain:example.com",
1177
+ gscPropertyUrl: "sc-domain:example.com",
1178
+ syncStatus: "synced"
1179
+ }
1180
+ },
1181
+ meta: {
1182
+ requestId: "req_01",
1183
+ surface: "partner",
1184
+ version: "1.0"
1185
+ }
1186
+ }
1187
+ }
1188
+ }
1189
+ }),
1190
+ getSiteSitemapChanges: defineHttpOperation({
1191
+ id: "partner.sites.sitemaps.changes.get",
1192
+ method: "GET",
1193
+ path: "/sites/{siteId}/sitemaps/changes",
1194
+ visibility: "public",
1195
+ semantics: {
1196
+ kind: "query",
1197
+ sideEffects: "none",
1198
+ idempotent: true,
1199
+ retry: "idempotent",
1200
+ readConsistency: "primary"
1201
+ },
1202
+ auth: {
1203
+ credentials: ["user_key", "partner_key"],
1204
+ scopes: ["sitemaps:read"],
1205
+ ownership: [{
1206
+ credential: "user_key",
1207
+ rule: "authorized_site"
1208
+ }, {
1209
+ credential: "partner_key",
1210
+ rule: "authorized_site"
1211
+ }]
1212
+ },
1213
+ request: {
1214
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1215
+ query: sitemapChangesQuery,
1216
+ headers: requestHeaders,
1217
+ body: null
1218
+ },
1219
+ responses: { 200: sitemapChangesResponse },
1220
+ errors: partnerSiteErrors,
1221
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1222
+ resources: {
1223
+ reads: [{
1224
+ type: "site.sitemaps",
1225
+ idFrom: "params.siteId"
1226
+ }],
1227
+ changes: []
1228
+ },
1229
+ lifecycle: { introduced: "1.0.0" },
1230
+ docs: {
1231
+ summary: "Get sitemap URL changes",
1232
+ description: "Returns recently added and removed sitemap URLs for the requested window.",
1233
+ tags: ["Sitemaps"],
1234
+ examples: {
1235
+ request: {
1236
+ params: { siteId: "s_01" },
1237
+ query: { days: 28 }
1238
+ },
1239
+ response: {
1240
+ data: {
1241
+ added: [],
1242
+ removed: [],
1243
+ summary: {
1244
+ totalAdded: 0,
1245
+ totalRemoved: 0,
1246
+ period: { days: 28 }
1247
+ }
1248
+ },
1249
+ meta: {
1250
+ requestId: "req_01",
1251
+ surface: "partner",
1252
+ version: "1.0"
1253
+ }
1254
+ }
1255
+ }
1256
+ }
1257
+ }),
1258
+ getSiteAnalysis: defineHttpOperation({
1259
+ id: "partner.sites.analysis.get",
1260
+ method: "GET",
1261
+ path: "/sites/{siteId}/analysis",
1262
+ visibility: "public",
1263
+ semantics: {
1264
+ kind: "query",
1265
+ sideEffects: "none",
1266
+ idempotent: true,
1267
+ retry: "idempotent",
1268
+ readConsistency: "primary"
1269
+ },
1270
+ auth: {
1271
+ credentials: ["user_key", "partner_key"],
1272
+ scopes: ["analytics:execute"],
1273
+ ownership: [{
1274
+ credential: "user_key",
1275
+ rule: "authorized_site"
1276
+ }, {
1277
+ credential: "partner_key",
1278
+ rule: "authorized_site"
1279
+ }]
1280
+ },
1281
+ request: {
1282
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1283
+ query: analysisQuery,
1284
+ headers: requestHeaders,
1285
+ body: null
1286
+ },
1287
+ responses: { 200: analysisResponse },
1288
+ errors: partnerSiteErrors,
1289
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1290
+ resources: {
1291
+ reads: [{
1292
+ type: "site.analytics",
1293
+ idFrom: "params.siteId"
1294
+ }],
1295
+ changes: []
1296
+ },
1297
+ lifecycle: { introduced: "1.0.0" },
1298
+ docs: {
1299
+ summary: "Run an analysis preset",
1300
+ description: "Runs one validated analysis preset for an analytics window.",
1301
+ tags: ["Analysis"],
1302
+ examples: {
1303
+ request: {
1304
+ params: { siteId: "s_01" },
1305
+ query: {
1306
+ preset: "opportunity",
1307
+ startDate: "2026-06-01",
1308
+ endDate: "2026-06-30"
1309
+ }
1310
+ },
1311
+ response: {
1312
+ data: {
1313
+ preset: "opportunity",
1314
+ keywords: [],
1315
+ totalCount: 0,
1316
+ meta: {
1317
+ siteUrl: "sc-domain:example.com",
1318
+ params: {
1319
+ startDate: "2026-06-01",
1320
+ endDate: "2026-06-30"
1321
+ }
1322
+ }
1323
+ },
1324
+ meta: {
1325
+ requestId: "req_01",
1326
+ surface: "partner",
1327
+ version: "1.0"
1328
+ }
1329
+ }
1330
+ }
1331
+ }
1332
+ }),
1333
+ getSiteAnalysisBundle: defineHttpOperation({
1334
+ id: "partner.sites.analysis.bundle.get",
1335
+ method: "GET",
1336
+ path: "/sites/{siteId}/analysis/bundle",
1337
+ visibility: "public",
1338
+ semantics: {
1339
+ kind: "query",
1340
+ sideEffects: "none",
1341
+ idempotent: true,
1342
+ retry: "idempotent",
1343
+ readConsistency: "primary"
1344
+ },
1345
+ auth: {
1346
+ credentials: ["user_key", "partner_key"],
1347
+ scopes: ["analytics:execute"],
1348
+ ownership: [{
1349
+ credential: "user_key",
1350
+ rule: "authorized_site"
1351
+ }, {
1352
+ credential: "partner_key",
1353
+ rule: "authorized_site"
1354
+ }]
1355
+ },
1356
+ request: {
1357
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1358
+ query: analysisBundleQuery,
1359
+ headers: requestHeaders,
1360
+ body: null
1361
+ },
1362
+ responses: { 200: analysisBundleResponse },
1363
+ errors: partnerSiteErrors,
1364
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1365
+ resources: {
1366
+ reads: [{
1367
+ type: "site.analytics",
1368
+ idFrom: "params.siteId"
1369
+ }],
1370
+ changes: []
1371
+ },
1372
+ lifecycle: { introduced: "1.0.0" },
1373
+ docs: {
1374
+ summary: "Run an analysis bundle",
1375
+ description: "Runs several validated presets against one shared analytics pool.",
1376
+ tags: ["Analysis"],
1377
+ examples: {
1378
+ request: {
1379
+ params: { siteId: "s_01" },
1380
+ query: {
1381
+ presets: ["opportunity"],
1382
+ startDate: "2026-06-01",
1383
+ endDate: "2026-06-30"
1384
+ }
1385
+ },
1386
+ response: {
1387
+ data: {
1388
+ bundle: {},
1389
+ meta: {
1390
+ siteUrl: "sc-domain:example.com",
1391
+ params: {
1392
+ startDate: "2026-06-01",
1393
+ endDate: "2026-06-30"
1394
+ }
1395
+ }
1396
+ },
1397
+ meta: {
1398
+ requestId: "req_01",
1399
+ surface: "partner",
1400
+ version: "1.0"
1401
+ }
1402
+ }
1403
+ }
1404
+ }
1405
+ }),
1406
+ deleteSite: defineHttpOperation({
1407
+ id: "partner.sites.delete",
1408
+ method: "DELETE",
1409
+ path: "/sites/{siteId}",
1410
+ visibility: "public",
1411
+ semantics: {
1412
+ kind: "mutation",
1413
+ sideEffects: "state",
1414
+ idempotent: true,
1415
+ retry: "idempotent",
1416
+ readConsistency: null
1417
+ },
1418
+ auth: {
1419
+ credentials: ["user_key", "partner_key"],
1420
+ scopes: ["sites:write"],
1421
+ ownership: [{
1422
+ credential: "user_key",
1423
+ rule: "authorized_site"
1424
+ }, {
1425
+ credential: "partner_key",
1426
+ rule: "authorized_site"
1427
+ }]
1428
+ },
1429
+ request: {
1430
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1431
+ query: null,
1432
+ headers: requestHeaders,
1433
+ body: null
1434
+ },
1435
+ responses: { 200: siteDeletionResponse },
1436
+ errors: partnerSiteErrors,
1437
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1438
+ resources: {
1439
+ reads: [{
1440
+ type: "site.registration",
1441
+ idFrom: "params.siteId"
1442
+ }],
1443
+ changes: [{
1444
+ type: "site.registration",
1445
+ idFrom: "params.siteId"
1446
+ }, {
1447
+ type: "site.lifecycle",
1448
+ idFrom: "params.siteId"
1449
+ }]
1450
+ },
1451
+ lifecycle: { introduced: "1.0.0" },
1452
+ docs: {
1453
+ summary: "Delete a site registration",
1454
+ description: "Removes the site registration and queued work while retaining the user data store.",
1455
+ tags: ["Sites"],
1456
+ examples: {
1457
+ request: { params: { siteId: "s_01" } },
1458
+ response: {
1459
+ data: {
1460
+ deleted: true,
1461
+ siteId: "s_01",
1462
+ siteUrl: "example.com"
1463
+ },
1464
+ meta: {
1465
+ requestId: "req_01",
1466
+ surface: "partner",
1467
+ version: "1.0"
1468
+ }
1469
+ }
1470
+ }
1471
+ }
1472
+ }),
1473
+ getCanonicalMismatches: defineHttpOperation({
1474
+ id: "partner.sites.canonical.mismatches.get",
1475
+ method: "GET",
1476
+ path: "/sites/{siteId}/canonical-mismatches",
1477
+ visibility: "public",
1478
+ semantics: {
1479
+ kind: "query",
1480
+ sideEffects: "none",
1481
+ idempotent: true,
1482
+ retry: "idempotent",
1483
+ readConsistency: "primary"
1484
+ },
1485
+ auth: {
1486
+ credentials: ["user_key", "partner_key"],
1487
+ scopes: ["indexing:read"],
1488
+ ownership: [{
1489
+ credential: "user_key",
1490
+ rule: "authorized_site"
1491
+ }, {
1492
+ credential: "partner_key",
1493
+ rule: "authorized_site"
1494
+ }]
1495
+ },
1496
+ request: {
1497
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1498
+ query: null,
1499
+ headers: requestHeaders,
1500
+ body: null
1501
+ },
1502
+ responses: { 200: canonicalMismatchesResponse },
1503
+ errors: partnerSiteErrors,
1504
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1505
+ resources: {
1506
+ reads: [{
1507
+ type: "site.indexing",
1508
+ idFrom: "params.siteId"
1509
+ }],
1510
+ changes: []
1511
+ },
1512
+ lifecycle: { introduced: "1.1.0" },
1513
+ docs: {
1514
+ summary: "List canonical mismatches",
1515
+ description: "Returns sitemap-scoped URLs whose Google-chosen canonical diverges from the declared canonical, with consolidation targets and trend.",
1516
+ tags: ["Indexing"],
1517
+ examples: {
1518
+ request: { params: { siteId: "s_01" } },
1519
+ response: {
1520
+ data: {
1521
+ mismatches: [],
1522
+ totalCount: 0,
1523
+ consolidationTargets: [],
1524
+ trend: [],
1525
+ meta: {
1526
+ siteUrl: "sc-domain:example.com",
1527
+ syncStatus: "synced"
1528
+ }
1529
+ },
1530
+ meta: {
1531
+ requestId: "req_01",
1532
+ surface: "partner",
1533
+ version: "1.0"
1534
+ }
1535
+ }
1536
+ }
1537
+ }
1538
+ }),
1539
+ inspectSiteUrls: defineHttpOperation({
1540
+ id: "partner.sites.indexing.inspect.create",
1541
+ method: "POST",
1542
+ path: "/sites/{siteId}/indexing/inspect",
1543
+ visibility: "public",
1544
+ semantics: {
1545
+ kind: "mutation",
1546
+ sideEffects: "state",
1547
+ idempotent: false,
1548
+ retry: "never",
1549
+ readConsistency: null
1550
+ },
1551
+ auth: {
1552
+ credentials: ["user_key", "partner_key"],
1553
+ scopes: ["indexing:write"],
1554
+ ownership: [{
1555
+ credential: "user_key",
1556
+ rule: "authorized_site"
1557
+ }, {
1558
+ credential: "partner_key",
1559
+ rule: "authorized_site"
1560
+ }]
1561
+ },
1562
+ request: {
1563
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1564
+ query: null,
1565
+ headers: requestHeaders,
1566
+ body: indexingInspectRequest
1567
+ },
1568
+ responses: { 200: indexingInspectionResponse },
1569
+ errors: partnerSiteErrors,
1570
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1571
+ resources: {
1572
+ reads: [{
1573
+ type: "site.indexing",
1574
+ idFrom: "params.siteId"
1575
+ }],
1576
+ changes: [{
1577
+ type: "site.indexing",
1578
+ idFrom: "params.siteId"
1579
+ }]
1580
+ },
1581
+ lifecycle: { introduced: "1.1.0" },
1582
+ docs: {
1583
+ summary: "Inspect URLs on demand",
1584
+ description: "Runs live URL inspections against the daily per-site quota; URLs outside the site domain and over-quota URLs are reported as skipped. Exhausted quota fails with rate_limited.",
1585
+ tags: ["Indexing"],
1586
+ examples: {
1587
+ request: {
1588
+ params: { siteId: "s_01" },
1589
+ body: { urls: ["https://example.com/"] }
1590
+ },
1591
+ response: {
1592
+ data: {
1593
+ siteId: "s_01",
1594
+ rateLimit: {
1595
+ reserved: 1,
1596
+ remaining: 199,
1597
+ limit: 200
1598
+ },
1599
+ results: [],
1600
+ errors: [],
1601
+ skipped: []
1602
+ },
1603
+ meta: {
1604
+ requestId: "req_01",
1605
+ surface: "partner",
1606
+ version: "1.0"
1607
+ }
1608
+ }
1609
+ }
1610
+ }
1611
+ }),
1612
+ recoverSitePermission: defineHttpOperation({
1613
+ id: "partner.sites.permission.recover",
1614
+ method: "POST",
1615
+ path: "/sites/{siteId}/permission/recover",
1616
+ visibility: "public",
1617
+ semantics: {
1618
+ kind: "mutation",
1619
+ sideEffects: "state",
1620
+ idempotent: true,
1621
+ retry: "idempotent",
1622
+ readConsistency: null
1623
+ },
1624
+ auth: {
1625
+ credentials: ["user_key", "partner_key"],
1626
+ scopes: ["sites:write"],
1627
+ ownership: [{
1628
+ credential: "user_key",
1629
+ rule: "authorized_site"
1630
+ }, {
1631
+ credential: "partner_key",
1632
+ rule: "authorized_site"
1633
+ }]
1634
+ },
1635
+ request: {
1636
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1637
+ query: null,
1638
+ headers: requestHeaders,
1639
+ body: null
1640
+ },
1641
+ responses: { 200: permissionRecoveryResponse },
1642
+ errors: partnerSiteErrors,
1643
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1644
+ resources: {
1645
+ reads: [{
1646
+ type: "site.auth",
1647
+ idFrom: "params.siteId"
1648
+ }],
1649
+ changes: [{
1650
+ type: "site.auth",
1651
+ idFrom: "params.siteId"
1652
+ }, {
1653
+ type: "site.lifecycle",
1654
+ idFrom: "params.siteId"
1655
+ }]
1656
+ },
1657
+ lifecycle: { introduced: "1.1.0" },
1658
+ docs: {
1659
+ summary: "Re-check and recover site permission",
1660
+ description: "Force-rechecks Google Search Console access for a permission-lost site; on recovery resets sync state and queues fresh sync jobs.",
1661
+ tags: ["Sites"],
1662
+ examples: {
1663
+ request: { params: { siteId: "s_01" } },
1664
+ response: {
1665
+ data: {
1666
+ success: true,
1667
+ permissionLevel: "siteFullUser",
1668
+ jobsQueued: 3,
1669
+ message: "Permission restored (siteFullUser). Queued 3 sync jobs."
1670
+ },
1671
+ meta: {
1672
+ requestId: "req_01",
1673
+ surface: "partner",
1674
+ version: "1.0"
1675
+ }
1676
+ }
1677
+ }
1678
+ }
1679
+ }),
1680
+ queryKeywordSparklines: defineHttpOperation({
1681
+ id: "partner.sites.keyword.sparklines.query",
1682
+ method: "POST",
1683
+ path: "/sites/{siteId}/keyword-sparklines",
1684
+ visibility: "public",
1685
+ semantics: {
1686
+ kind: "query",
1687
+ sideEffects: "none",
1688
+ idempotent: true,
1689
+ retry: "idempotent",
1690
+ readConsistency: "primary"
1691
+ },
1692
+ auth: {
1693
+ credentials: ["user_key", "partner_key"],
1694
+ scopes: ["analytics:read"],
1695
+ ownership: [{
1696
+ credential: "user_key",
1697
+ rule: "authorized_site"
1698
+ }, {
1699
+ credential: "partner_key",
1700
+ rule: "authorized_site"
1701
+ }]
1702
+ },
1703
+ request: {
1704
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1705
+ query: null,
1706
+ headers: requestHeaders,
1707
+ body: keywordSparklinesRequest
1708
+ },
1709
+ responses: { 200: keywordSparklinesResponse },
1710
+ errors: partnerSiteErrors,
1711
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1712
+ resources: {
1713
+ reads: [{
1714
+ type: "site.analytics",
1715
+ idFrom: "params.siteId"
1716
+ }],
1717
+ changes: []
1718
+ },
1719
+ lifecycle: { introduced: "1.1.0" },
1720
+ docs: {
1721
+ summary: "Query keyword sparklines",
1722
+ description: "Returns per-keyword daily click series for up to 20 keywords over the requested window.",
1723
+ tags: ["Analytics"],
1724
+ examples: {
1725
+ request: {
1726
+ params: { siteId: "s_01" },
1727
+ body: {
1728
+ keywords: ["nuxt seo"],
1729
+ startDate: "2026-06-01",
1730
+ endDate: "2026-06-28"
1731
+ }
1732
+ },
1733
+ response: {
1734
+ data: { sparklines: { "nuxt seo": [
1735
+ 0,
1736
+ 1,
1737
+ 2
1738
+ ] } },
1739
+ meta: {
1740
+ requestId: "req_01",
1741
+ surface: "partner",
1742
+ version: "1.0"
1743
+ }
1744
+ }
1745
+ }
1746
+ }
1747
+ }),
1748
+ getQueryTrend: defineHttpOperation({
1749
+ id: "partner.sites.query.trend.get",
1750
+ method: "GET",
1751
+ path: "/sites/{siteId}/query-trend",
1752
+ visibility: "public",
1753
+ semantics: {
1754
+ kind: "query",
1755
+ sideEffects: "none",
1756
+ idempotent: true,
1757
+ retry: "idempotent",
1758
+ readConsistency: "primary"
1759
+ },
1760
+ auth: {
1761
+ credentials: ["user_key", "partner_key"],
1762
+ scopes: ["analytics:read"],
1763
+ ownership: [{
1764
+ credential: "user_key",
1765
+ rule: "authorized_site"
1766
+ }, {
1767
+ credential: "partner_key",
1768
+ rule: "authorized_site"
1769
+ }]
1770
+ },
1771
+ request: {
1772
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1773
+ query: trendQuery,
1774
+ headers: requestHeaders,
1775
+ body: null
1776
+ },
1777
+ responses: { 200: queryTrendResponse },
1778
+ errors: partnerSiteErrors,
1779
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1780
+ resources: {
1781
+ reads: [{
1782
+ type: "site.analytics",
1783
+ idFrom: "params.siteId"
1784
+ }],
1785
+ changes: []
1786
+ },
1787
+ lifecycle: { introduced: "1.1.0" },
1788
+ docs: {
1789
+ summary: "Get unique-query trend",
1790
+ description: "Returns the daily unique-query count series for a window, with an optional previous-period total for comparison.",
1791
+ tags: ["Analytics"],
1792
+ examples: {
1793
+ request: {
1794
+ params: { siteId: "s_01" },
1795
+ query: {
1796
+ startDate: "2026-06-01",
1797
+ endDate: "2026-06-28"
1798
+ }
1799
+ },
1800
+ response: {
1801
+ data: {
1802
+ daily: [],
1803
+ total: 0,
1804
+ meta: {
1805
+ siteUrl: "sc-domain:example.com",
1806
+ syncStatus: "synced"
1807
+ }
1808
+ },
1809
+ meta: {
1810
+ requestId: "req_01",
1811
+ surface: "partner",
1812
+ version: "1.0"
1813
+ }
1814
+ }
1815
+ }
1816
+ }
1817
+ }),
1818
+ getPageTrend: defineHttpOperation({
1819
+ id: "partner.sites.page.trend.get",
1820
+ method: "GET",
1821
+ path: "/sites/{siteId}/page-trend",
1822
+ visibility: "public",
1823
+ semantics: {
1824
+ kind: "query",
1825
+ sideEffects: "none",
1826
+ idempotent: true,
1827
+ retry: "idempotent",
1828
+ readConsistency: "primary"
1829
+ },
1830
+ auth: {
1831
+ credentials: ["user_key", "partner_key"],
1832
+ scopes: ["analytics:read"],
1833
+ ownership: [{
1834
+ credential: "user_key",
1835
+ rule: "authorized_site"
1836
+ }, {
1837
+ credential: "partner_key",
1838
+ rule: "authorized_site"
1839
+ }]
1840
+ },
1841
+ request: {
1842
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1843
+ query: trendQuery,
1844
+ headers: requestHeaders,
1845
+ body: null
1846
+ },
1847
+ responses: { 200: pageTrendResponse },
1848
+ errors: partnerSiteErrors,
1849
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1850
+ resources: {
1851
+ reads: [{
1852
+ type: "site.analytics",
1853
+ idFrom: "params.siteId"
1854
+ }],
1855
+ changes: []
1856
+ },
1857
+ lifecycle: { introduced: "1.1.0" },
1858
+ docs: {
1859
+ summary: "Get unique-page trend",
1860
+ description: "Returns the daily unique-page count series for a window, with an optional previous-period total for comparison.",
1861
+ tags: ["Analytics"],
1862
+ examples: {
1863
+ request: {
1864
+ params: { siteId: "s_01" },
1865
+ query: {
1866
+ startDate: "2026-06-01",
1867
+ endDate: "2026-06-28"
1868
+ }
1869
+ },
1870
+ response: {
1871
+ data: {
1872
+ daily: [],
1873
+ total: 0,
1874
+ meta: {
1875
+ siteUrl: "sc-domain:example.com",
1876
+ syncStatus: "synced"
1877
+ }
1878
+ },
1879
+ meta: {
1880
+ requestId: "req_01",
1881
+ surface: "partner",
1882
+ version: "1.0"
1883
+ }
1884
+ }
1885
+ }
1886
+ }
1887
+ }),
1888
+ getContentVelocity: defineHttpOperation({
1889
+ id: "partner.sites.content.velocity.get",
1890
+ method: "GET",
1891
+ path: "/sites/{siteId}/content-velocity",
1892
+ visibility: "public",
1893
+ semantics: {
1894
+ kind: "query",
1895
+ sideEffects: "none",
1896
+ idempotent: true,
1897
+ retry: "idempotent",
1898
+ readConsistency: "primary"
1899
+ },
1900
+ auth: {
1901
+ credentials: ["user_key", "partner_key"],
1902
+ scopes: ["analytics:read"],
1903
+ ownership: [{
1904
+ credential: "user_key",
1905
+ rule: "authorized_site"
1906
+ }, {
1907
+ credential: "partner_key",
1908
+ rule: "authorized_site"
1909
+ }]
1910
+ },
1911
+ request: {
1912
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1913
+ query: contentVelocityQuery,
1914
+ headers: requestHeaders,
1915
+ body: null
1916
+ },
1917
+ responses: { 200: contentVelocityResponse },
1918
+ errors: partnerSiteErrors,
1919
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1920
+ resources: {
1921
+ reads: [{
1922
+ type: "site.analytics",
1923
+ idFrom: "params.siteId"
1924
+ }],
1925
+ changes: []
1926
+ },
1927
+ lifecycle: { introduced: "1.2.0" },
1928
+ docs: {
1929
+ summary: "Get content velocity",
1930
+ description: "Returns the weekly new-keyword series over the requested window with a summary trend.",
1931
+ tags: ["Analytics"],
1932
+ examples: {
1933
+ request: {
1934
+ params: { siteId: "s_01" },
1935
+ query: { days: 90 }
1936
+ },
1937
+ response: {
1938
+ data: {
1939
+ weekly: [],
1940
+ summary: {
1941
+ totalNewKeywords: 0,
1942
+ avgPerWeek: 0,
1943
+ trend: "stable"
1944
+ },
1945
+ meta: {
1946
+ siteUrl: "sc-domain:example.com",
1947
+ syncStatus: "synced"
1948
+ }
1949
+ },
1950
+ meta: {
1951
+ requestId: "req_01",
1952
+ surface: "partner",
1953
+ version: "1.0"
1954
+ }
1955
+ }
1956
+ }
1957
+ }
1958
+ }),
1959
+ getCtrCurve: defineHttpOperation({
1960
+ id: "partner.sites.ctr.curve.get",
1961
+ method: "GET",
1962
+ path: "/sites/{siteId}/ctr-curve",
1963
+ visibility: "public",
1964
+ semantics: {
1965
+ kind: "query",
1966
+ sideEffects: "none",
1967
+ idempotent: true,
1968
+ retry: "idempotent",
1969
+ readConsistency: "primary"
1970
+ },
1971
+ auth: {
1972
+ credentials: ["user_key", "partner_key"],
1973
+ scopes: ["analytics:read"],
1974
+ ownership: [{
1975
+ credential: "user_key",
1976
+ rule: "authorized_site"
1977
+ }, {
1978
+ credential: "partner_key",
1979
+ rule: "authorized_site"
1980
+ }]
1981
+ },
1982
+ request: {
1983
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
1984
+ query: dateRangeQuery,
1985
+ headers: requestHeaders,
1986
+ body: null
1987
+ },
1988
+ responses: { 200: ctrCurveResponse },
1989
+ errors: partnerSiteErrors,
1990
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
1991
+ resources: {
1992
+ reads: [{
1993
+ type: "site.analytics",
1994
+ idFrom: "params.siteId"
1995
+ }],
1996
+ changes: []
1997
+ },
1998
+ lifecycle: { introduced: "1.2.0" },
1999
+ docs: {
2000
+ summary: "Get CTR curve and outliers",
2001
+ description: "Returns the position-bucketed CTR curve plus over/under-performing query outliers for the window.",
2002
+ tags: ["Analytics"],
2003
+ examples: {
2004
+ request: {
2005
+ params: { siteId: "s_01" },
2006
+ query: {
2007
+ startDate: "2026-06-01",
2008
+ endDate: "2026-06-28"
2009
+ }
2010
+ },
2011
+ response: {
2012
+ data: {
2013
+ curve: [],
2014
+ overperforming: [],
2015
+ underperforming: [],
2016
+ meta: {
2017
+ siteUrl: "sc-domain:example.com",
2018
+ syncStatus: "synced"
2019
+ }
2020
+ },
2021
+ meta: {
2022
+ requestId: "req_01",
2023
+ surface: "partner",
2024
+ version: "1.0"
2025
+ }
2026
+ }
2027
+ }
2028
+ }
2029
+ }),
2030
+ getDarkTraffic: defineHttpOperation({
2031
+ id: "partner.sites.dark.traffic.get",
2032
+ method: "GET",
2033
+ path: "/sites/{siteId}/dark-traffic",
2034
+ visibility: "public",
2035
+ semantics: {
2036
+ kind: "query",
2037
+ sideEffects: "none",
2038
+ idempotent: true,
2039
+ retry: "idempotent",
2040
+ readConsistency: "primary"
2041
+ },
2042
+ auth: {
2043
+ credentials: ["user_key", "partner_key"],
2044
+ scopes: ["analytics:read"],
2045
+ ownership: [{
2046
+ credential: "user_key",
2047
+ rule: "authorized_site"
2048
+ }, {
2049
+ credential: "partner_key",
2050
+ rule: "authorized_site"
2051
+ }]
2052
+ },
2053
+ request: {
2054
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2055
+ query: dateRangeQuery,
2056
+ headers: requestHeaders,
2057
+ body: null
2058
+ },
2059
+ responses: { 200: darkTrafficResponse },
2060
+ errors: partnerSiteErrors,
2061
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2062
+ resources: {
2063
+ reads: [{
2064
+ type: "site.analytics",
2065
+ idFrom: "params.siteId"
2066
+ }],
2067
+ changes: []
2068
+ },
2069
+ lifecycle: { introduced: "1.2.0" },
2070
+ docs: {
2071
+ summary: "Get dark traffic breakdown",
2072
+ description: "Returns clicks not attributable to any tracked keyword, in total and per page, for the window.",
2073
+ tags: ["Analytics"],
2074
+ examples: {
2075
+ request: {
2076
+ params: { siteId: "s_01" },
2077
+ query: {
2078
+ startDate: "2026-06-01",
2079
+ endDate: "2026-06-28"
2080
+ }
2081
+ },
2082
+ response: {
2083
+ data: {
2084
+ summary: {
2085
+ totalClicks: 0,
2086
+ attributedClicks: 0,
2087
+ darkClicks: 0,
2088
+ darkPercent: 0,
2089
+ totalImpressions: 0,
2090
+ attributedImpressions: 0
2091
+ },
2092
+ pages: [],
2093
+ meta: {
2094
+ siteUrl: "sc-domain:example.com",
2095
+ syncStatus: "synced"
2096
+ }
2097
+ },
2098
+ meta: {
2099
+ requestId: "req_01",
2100
+ surface: "partner",
2101
+ version: "1.0"
2102
+ }
2103
+ }
2104
+ }
2105
+ }
2106
+ }),
2107
+ getDeviceGap: defineHttpOperation({
2108
+ id: "partner.sites.device.gap.get",
2109
+ method: "GET",
2110
+ path: "/sites/{siteId}/device-gap",
2111
+ visibility: "public",
2112
+ semantics: {
2113
+ kind: "query",
2114
+ sideEffects: "none",
2115
+ idempotent: true,
2116
+ retry: "idempotent",
2117
+ readConsistency: "primary"
2118
+ },
2119
+ auth: {
2120
+ credentials: ["user_key", "partner_key"],
2121
+ scopes: ["analytics:read"],
2122
+ ownership: [{
2123
+ credential: "user_key",
2124
+ rule: "authorized_site"
2125
+ }, {
2126
+ credential: "partner_key",
2127
+ rule: "authorized_site"
2128
+ }]
2129
+ },
2130
+ request: {
2131
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2132
+ query: dateRangeQuery,
2133
+ headers: requestHeaders,
2134
+ body: null
2135
+ },
2136
+ responses: { 200: deviceGapResponse },
2137
+ errors: partnerSiteErrors,
2138
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2139
+ resources: {
2140
+ reads: [{
2141
+ type: "site.analytics",
2142
+ idFrom: "params.siteId"
2143
+ }],
2144
+ changes: []
2145
+ },
2146
+ lifecycle: { introduced: "1.2.0" },
2147
+ docs: {
2148
+ summary: "Get desktop/mobile gap",
2149
+ description: "Returns per-day desktop vs mobile CTR/position metrics with gap trends for the window.",
2150
+ tags: ["Analytics"],
2151
+ examples: {
2152
+ request: {
2153
+ params: { siteId: "s_01" },
2154
+ query: {
2155
+ startDate: "2026-06-01",
2156
+ endDate: "2026-06-28"
2157
+ }
2158
+ },
2159
+ response: {
2160
+ data: {
2161
+ daily: [],
2162
+ summary: null,
2163
+ meta: {
2164
+ siteUrl: "sc-domain:example.com",
2165
+ syncStatus: "synced"
2166
+ }
2167
+ },
2168
+ meta: {
2169
+ requestId: "req_01",
2170
+ surface: "partner",
2171
+ version: "1.0"
2172
+ }
2173
+ }
2174
+ }
2175
+ }
2176
+ }),
2177
+ getKeywordBreadth: defineHttpOperation({
2178
+ id: "partner.sites.keyword.breadth.get",
2179
+ method: "GET",
2180
+ path: "/sites/{siteId}/keyword-breadth",
2181
+ visibility: "public",
2182
+ semantics: {
2183
+ kind: "query",
2184
+ sideEffects: "none",
2185
+ idempotent: true,
2186
+ retry: "idempotent",
2187
+ readConsistency: "primary"
2188
+ },
2189
+ auth: {
2190
+ credentials: ["user_key", "partner_key"],
2191
+ scopes: ["analytics:read"],
2192
+ ownership: [{
2193
+ credential: "user_key",
2194
+ rule: "authorized_site"
2195
+ }, {
2196
+ credential: "partner_key",
2197
+ rule: "authorized_site"
2198
+ }]
2199
+ },
2200
+ request: {
2201
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2202
+ query: dateRangeQuery,
2203
+ headers: requestHeaders,
2204
+ body: null
2205
+ },
2206
+ responses: { 200: keywordBreadthResponse },
2207
+ errors: partnerSiteErrors,
2208
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2209
+ resources: {
2210
+ reads: [{
2211
+ type: "site.analytics",
2212
+ idFrom: "params.siteId"
2213
+ }],
2214
+ changes: []
2215
+ },
2216
+ lifecycle: { introduced: "1.2.0" },
2217
+ docs: {
2218
+ summary: "Get keyword breadth",
2219
+ description: "Returns the pages-per-keyword-count distribution with fragile and authority page lists for the window.",
2220
+ tags: ["Analytics"],
2221
+ examples: {
2222
+ request: {
2223
+ params: { siteId: "s_01" },
2224
+ query: {
2225
+ startDate: "2026-06-01",
2226
+ endDate: "2026-06-28"
2227
+ }
2228
+ },
2229
+ response: {
2230
+ data: {
2231
+ distribution: [],
2232
+ fragilePages: [],
2233
+ authorityPages: [],
2234
+ summary: {
2235
+ totalPages: 0,
2236
+ avgKeywordsPerPage: 0,
2237
+ fragileCount: 0,
2238
+ authorityCount: 0
2239
+ },
2240
+ meta: {
2241
+ siteUrl: "sc-domain:example.com",
2242
+ syncStatus: "synced"
2243
+ }
2244
+ },
2245
+ meta: {
2246
+ requestId: "req_01",
2247
+ surface: "partner",
2248
+ version: "1.0"
2249
+ }
2250
+ }
2251
+ }
2252
+ }
2253
+ }),
2254
+ getPositionDistribution: defineHttpOperation({
2255
+ id: "partner.sites.position.distribution.get",
2256
+ method: "GET",
2257
+ path: "/sites/{siteId}/position-distribution",
2258
+ visibility: "public",
2259
+ semantics: {
2260
+ kind: "query",
2261
+ sideEffects: "none",
2262
+ idempotent: true,
2263
+ retry: "idempotent",
2264
+ readConsistency: "primary"
2265
+ },
2266
+ auth: {
2267
+ credentials: ["user_key", "partner_key"],
2268
+ scopes: ["analytics:read"],
2269
+ ownership: [{
2270
+ credential: "user_key",
2271
+ rule: "authorized_site"
2272
+ }, {
2273
+ credential: "partner_key",
2274
+ rule: "authorized_site"
2275
+ }]
2276
+ },
2277
+ request: {
2278
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2279
+ query: dateRangeQuery,
2280
+ headers: requestHeaders,
2281
+ body: null
2282
+ },
2283
+ responses: { 200: positionDistributionResponse },
2284
+ errors: partnerSiteErrors,
2285
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2286
+ resources: {
2287
+ reads: [{
2288
+ type: "site.analytics",
2289
+ idFrom: "params.siteId"
2290
+ }],
2291
+ changes: []
2292
+ },
2293
+ lifecycle: { introduced: "1.2.0" },
2294
+ docs: {
2295
+ summary: "Get position distribution",
2296
+ description: "Returns the per-day keyword counts bucketed by average position for the window.",
2297
+ tags: ["Analytics"],
2298
+ examples: {
2299
+ request: {
2300
+ params: { siteId: "s_01" },
2301
+ query: {
2302
+ startDate: "2026-06-01",
2303
+ endDate: "2026-06-28"
2304
+ }
2305
+ },
2306
+ response: {
2307
+ data: {
2308
+ distribution: [],
2309
+ meta: {
2310
+ siteUrl: "sc-domain:example.com",
2311
+ syncStatus: "synced"
2312
+ }
2313
+ },
2314
+ meta: {
2315
+ requestId: "req_01",
2316
+ surface: "partner",
2317
+ version: "1.0"
2318
+ }
2319
+ }
2320
+ }
2321
+ }
2322
+ }),
2323
+ getTopAssociation: defineHttpOperation({
2324
+ id: "partner.sites.top.association.get",
2325
+ method: "GET",
2326
+ path: "/sites/{siteId}/top-association",
2327
+ visibility: "public",
2328
+ semantics: {
2329
+ kind: "query",
2330
+ sideEffects: "none",
2331
+ idempotent: true,
2332
+ retry: "idempotent",
2333
+ readConsistency: "primary"
2334
+ },
2335
+ auth: {
2336
+ credentials: ["user_key", "partner_key"],
2337
+ scopes: ["analytics:read"],
2338
+ ownership: [{
2339
+ credential: "user_key",
2340
+ rule: "authorized_site"
2341
+ }, {
2342
+ credential: "partner_key",
2343
+ rule: "authorized_site"
2344
+ }]
2345
+ },
2346
+ request: {
2347
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2348
+ query: topAssociationQuery,
2349
+ headers: requestHeaders,
2350
+ body: null
2351
+ },
2352
+ responses: { 200: topAssociationResponse },
2353
+ errors: partnerSiteErrors,
2354
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2355
+ resources: {
2356
+ reads: [{
2357
+ type: "site.analytics",
2358
+ idFrom: "params.siteId"
2359
+ }],
2360
+ changes: []
2361
+ },
2362
+ lifecycle: { introduced: "1.2.0" },
2363
+ docs: {
2364
+ summary: "Get top association",
2365
+ description: "Returns the single best-performing page for a keyword, or keyword for a page, over the window.",
2366
+ tags: ["Analytics"],
2367
+ examples: {
2368
+ request: {
2369
+ params: { siteId: "s_01" },
2370
+ query: {
2371
+ type: "topKeyword",
2372
+ identifier: "/docs",
2373
+ startDate: "2026-06-01",
2374
+ endDate: "2026-06-28"
2375
+ }
2376
+ },
2377
+ response: {
2378
+ data: { value: null },
2379
+ meta: {
2380
+ requestId: "req_01",
2381
+ surface: "partner",
2382
+ version: "1.0"
2383
+ }
2384
+ }
2385
+ }
2386
+ }
2387
+ }),
2388
+ getIndexPercent: defineHttpOperation({
2389
+ id: "partner.sites.index.percent.get",
2390
+ method: "GET",
2391
+ path: "/sites/{siteId}/index-percent",
2392
+ visibility: "public",
2393
+ semantics: {
2394
+ kind: "query",
2395
+ sideEffects: "none",
2396
+ idempotent: true,
2397
+ retry: "idempotent",
2398
+ readConsistency: "primary"
2399
+ },
2400
+ auth: {
2401
+ credentials: ["user_key", "partner_key"],
2402
+ scopes: ["indexing:read"],
2403
+ ownership: [{
2404
+ credential: "user_key",
2405
+ rule: "authorized_site"
2406
+ }, {
2407
+ credential: "partner_key",
2408
+ rule: "authorized_site"
2409
+ }]
2410
+ },
2411
+ request: {
2412
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2413
+ query: indexPercentQuery,
2414
+ headers: requestHeaders,
2415
+ body: null
2416
+ },
2417
+ responses: { 200: indexPercentResponse },
2418
+ errors: partnerSiteErrors,
2419
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2420
+ resources: {
2421
+ reads: [{
2422
+ type: "site.indexing",
2423
+ idFrom: "params.siteId"
2424
+ }, {
2425
+ type: "site.sitemaps",
2426
+ idFrom: "params.siteId"
2427
+ }],
2428
+ changes: []
2429
+ },
2430
+ lifecycle: { introduced: "1.2.0" },
2431
+ docs: {
2432
+ summary: "Get sitemap index-percent",
2433
+ description: "Returns the sitemap visibility trend, invisible URLs, orphan pages, and per-sitemap counts.",
2434
+ tags: ["Indexing"],
2435
+ examples: {
2436
+ request: {
2437
+ params: { siteId: "s_01" },
2438
+ query: { invisibleLimit: 100 }
2439
+ },
2440
+ response: {
2441
+ data: {
2442
+ trend: [],
2443
+ invisibleUrls: [],
2444
+ invisibleCount: 0,
2445
+ orphanPages: [],
2446
+ orphanCount: 0,
2447
+ sitemaps: [],
2448
+ summary: {
2449
+ currentPercent: 0,
2450
+ totalSitemapUrls: 0,
2451
+ visibleUrls: 0,
2452
+ change7d: null,
2453
+ change28d: null,
2454
+ dataDate: "2026-06-28"
2455
+ },
2456
+ meta: {
2457
+ siteUrl: "sc-domain:example.com",
2458
+ syncStatus: "synced",
2459
+ newestDateSynced: null
2460
+ }
2461
+ },
2462
+ meta: {
2463
+ requestId: "req_01",
2464
+ surface: "partner",
2465
+ version: "1.0"
2466
+ }
2467
+ }
2468
+ }
2469
+ }
2470
+ }),
2471
+ createSitemapAction: defineHttpOperation({
2472
+ id: "partner.sites.sitemaps.action.create",
2473
+ method: "POST",
2474
+ path: "/sites/{siteId}/sitemaps/actions",
2475
+ visibility: "public",
2476
+ semantics: {
2477
+ kind: "mutation",
2478
+ sideEffects: "state",
2479
+ idempotent: false,
2480
+ retry: "never",
2481
+ readConsistency: null
2482
+ },
2483
+ auth: {
2484
+ credentials: ["user_key", "partner_key"],
2485
+ scopes: ["sitemaps:write"],
2486
+ ownership: [{
2487
+ credential: "user_key",
2488
+ rule: "authorized_site"
2489
+ }, {
2490
+ credential: "partner_key",
2491
+ rule: "authorized_site"
2492
+ }]
2493
+ },
2494
+ request: {
2495
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2496
+ query: null,
2497
+ headers: requestHeaders,
2498
+ body: sitemapActionRequest
2499
+ },
2500
+ responses: { 200: sitemapActionResponse },
2501
+ errors: partnerSiteErrors,
2502
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2503
+ resources: {
2504
+ reads: [{
2505
+ type: "site.sitemaps",
2506
+ idFrom: "params.siteId"
2507
+ }],
2508
+ changes: [{
2509
+ type: "site.sitemaps",
2510
+ idFrom: "params.siteId"
2511
+ }]
2512
+ },
2513
+ lifecycle: { introduced: "1.3.0" },
2514
+ docs: {
2515
+ summary: "Run a sitemap action",
2516
+ description: "Submits, deletes, refreshes, or auto-discovers a site's sitemap; the response shape depends on the requested action.",
2517
+ tags: ["Sitemaps"],
2518
+ examples: {
2519
+ request: {
2520
+ params: { siteId: "s_01" },
2521
+ body: { action: "refresh" }
2522
+ },
2523
+ response: {
2524
+ data: {
2525
+ success: true,
2526
+ action: "refreshed",
2527
+ sitemapCount: 0,
2528
+ changed: false
2529
+ },
2530
+ meta: {
2531
+ requestId: "req_01",
2532
+ surface: "partner",
2533
+ version: "1.0"
2534
+ }
2535
+ }
2536
+ }
2537
+ }
2538
+ }),
2539
+ querySitemapMembership: defineHttpOperation({
2540
+ id: "partner.sites.sitemaps.membership.query",
2541
+ method: "POST",
2542
+ path: "/sites/{siteId}/sitemaps/membership",
2543
+ visibility: "public",
2544
+ semantics: {
2545
+ kind: "query",
2546
+ sideEffects: "none",
2547
+ idempotent: true,
2548
+ retry: "idempotent",
2549
+ readConsistency: "primary"
2550
+ },
2551
+ auth: {
2552
+ credentials: ["user_key", "partner_key"],
2553
+ scopes: ["sitemaps:read"],
2554
+ ownership: [{
2555
+ credential: "user_key",
2556
+ rule: "authorized_site"
2557
+ }, {
2558
+ credential: "partner_key",
2559
+ rule: "authorized_site"
2560
+ }]
2561
+ },
2562
+ request: {
2563
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
2564
+ query: null,
2565
+ headers: requestHeaders,
2566
+ body: sitemapMembershipRequest
2567
+ },
2568
+ responses: { 200: sitemapMembershipResponse },
2569
+ errors: partnerSiteErrors,
2570
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
2571
+ resources: {
2572
+ reads: [{
2573
+ type: "site.sitemaps",
2574
+ idFrom: "params.siteId"
2575
+ }],
2576
+ changes: []
2577
+ },
2578
+ lifecycle: { introduced: "1.3.0" },
2579
+ docs: {
2580
+ summary: "Query sitemap membership",
2581
+ description: "Checks whether each requested URL is present in the site's known sitemaps, subject to a freshness cap.",
2582
+ tags: ["Sitemaps"],
2583
+ examples: {
2584
+ request: {
2585
+ params: { siteId: "s_01" },
2586
+ body: {
2587
+ urls: ["https://example.com/"],
2588
+ maxAgeDays: 30
2589
+ }
2590
+ },
2591
+ response: {
2592
+ data: {
2593
+ urls: [],
2594
+ meta: {
2595
+ available: true,
2596
+ reason: null,
2597
+ requested: 1,
2598
+ checked: 1,
2599
+ matched: 0,
2600
+ newestFetchedAt: null
2601
+ }
2602
+ },
2603
+ meta: {
2604
+ requestId: "req_01",
2605
+ surface: "partner",
2606
+ version: "1.0"
2607
+ }
2608
+ }
2609
+ }
2610
+ }
2611
+ }),
2612
+ createTeam: defineHttpOperation({
2613
+ id: "partner.teams.create",
2614
+ method: "POST",
2615
+ path: "/teams",
2616
+ visibility: "public",
2617
+ semantics: {
2618
+ kind: "mutation",
2619
+ sideEffects: "state",
2620
+ idempotent: false,
2621
+ retry: "never",
2622
+ readConsistency: null
2623
+ },
2624
+ auth: {
2625
+ credentials: ["partner_key"],
2626
+ scopes: ["teams:write"],
2627
+ ownership: [{
2628
+ credential: "partner_key",
2629
+ rule: "partner_tenant"
2630
+ }]
2631
+ },
2632
+ request: {
2633
+ params: null,
2634
+ query: null,
2635
+ headers: requestHeaders,
2636
+ body: createTeamRequest
2637
+ },
2638
+ responses: { 200: teamCreatedResponse },
2639
+ errors: partnerUserErrors,
2640
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
2641
+ resources: {
2642
+ reads: [],
2643
+ changes: [{
2644
+ type: "partner.team",
2645
+ idFrom: "principal.id"
2646
+ }]
2647
+ },
2648
+ lifecycle: { introduced: "1.3.0" },
2649
+ docs: {
2650
+ summary: "Create a team",
2651
+ description: "Creates a team owned by a user linked to the authenticated partner tenant.",
2652
+ tags: ["Teams"],
2653
+ examples: {
2654
+ request: { body: {
2655
+ ownerUserId: "u_01",
2656
+ name: "Acme Team"
2657
+ } },
2658
+ response: {
2659
+ data: { team: {
2660
+ id: "t_01",
2661
+ ownerId: 1,
2662
+ name: "Acme Team",
2663
+ personalTeam: false,
2664
+ createdAt: 0,
2665
+ updatedAt: 0
2666
+ } },
2667
+ meta: {
2668
+ requestId: "req_01",
2669
+ surface: "partner",
2670
+ version: "1.0"
2671
+ }
2672
+ }
2673
+ }
2674
+ }
2675
+ }),
2676
+ renameTeam: defineHttpOperation({
2677
+ id: "partner.teams.rename",
2678
+ method: "PATCH",
2679
+ path: "/teams/{teamId}",
2680
+ visibility: "public",
2681
+ semantics: {
2682
+ kind: "mutation",
2683
+ sideEffects: "state",
2684
+ idempotent: true,
2685
+ retry: "idempotent",
2686
+ readConsistency: null
2687
+ },
2688
+ auth: {
2689
+ credentials: ["partner_key"],
2690
+ scopes: ["teams:write"],
2691
+ ownership: [{
2692
+ credential: "partner_key",
2693
+ rule: "partner_tenant"
2694
+ }]
2695
+ },
2696
+ request: {
2697
+ params: z.strictObject({ teamId: realtimeSchemas.publicTeamId }),
2698
+ query: null,
2699
+ headers: requestHeaders,
2700
+ body: renameTeamRequest
2701
+ },
2702
+ responses: { 200: teamRenamedResponse },
2703
+ errors: partnerUserErrors,
2704
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
2705
+ resources: {
2706
+ reads: [{
2707
+ type: "partner.team",
2708
+ idFrom: "params.teamId"
2709
+ }],
2710
+ changes: [{
2711
+ type: "partner.team",
2712
+ idFrom: "params.teamId"
2713
+ }]
2714
+ },
2715
+ lifecycle: { introduced: "1.3.0" },
2716
+ docs: {
2717
+ summary: "Rename a team",
2718
+ description: "Renames a team owned by the authenticated partner tenant.",
2719
+ tags: ["Teams"],
2720
+ examples: {
2721
+ request: {
2722
+ params: { teamId: "t_01" },
2723
+ body: { name: "New name" }
2724
+ },
2725
+ response: {
2726
+ data: {
2727
+ ok: true,
2728
+ name: "New name"
2729
+ },
2730
+ meta: {
2731
+ requestId: "req_01",
2732
+ surface: "partner",
2733
+ version: "1.0"
2734
+ }
2735
+ }
2736
+ }
2737
+ }
2738
+ }),
2739
+ deleteTeam: defineHttpOperation({
2740
+ id: "partner.teams.delete",
2741
+ method: "DELETE",
2742
+ path: "/teams/{teamId}",
2743
+ visibility: "public",
2744
+ semantics: {
2745
+ kind: "mutation",
2746
+ sideEffects: "state",
2747
+ idempotent: true,
2748
+ retry: "idempotent",
2749
+ readConsistency: null
2750
+ },
2751
+ auth: {
2752
+ credentials: ["partner_key"],
2753
+ scopes: ["teams:write"],
2754
+ ownership: [{
2755
+ credential: "partner_key",
2756
+ rule: "partner_tenant"
2757
+ }]
2758
+ },
2759
+ request: {
2760
+ params: z.strictObject({ teamId: realtimeSchemas.publicTeamId }),
2761
+ query: null,
2762
+ headers: requestHeaders,
2763
+ body: null
2764
+ },
2765
+ responses: { 200: teamDeletedResponse },
2766
+ errors: partnerUserErrors,
2767
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
2768
+ resources: {
2769
+ reads: [{
2770
+ type: "partner.team",
2771
+ idFrom: "params.teamId"
2772
+ }],
2773
+ changes: [{
2774
+ type: "partner.team",
2775
+ idFrom: "params.teamId"
2776
+ }]
2777
+ },
2778
+ lifecycle: { introduced: "1.3.0" },
2779
+ docs: {
2780
+ summary: "Delete a team",
2781
+ description: "Deletes a team owned by the authenticated partner tenant.",
2782
+ tags: ["Teams"],
2783
+ examples: {
2784
+ request: { params: { teamId: "t_01" } },
2785
+ response: {
2786
+ data: { ok: true },
2787
+ meta: {
2788
+ requestId: "req_01",
2789
+ surface: "partner",
2790
+ version: "1.0"
2791
+ }
2792
+ }
2793
+ }
2794
+ }
2795
+ }),
2796
+ listTeamMembers: defineHttpOperation({
2797
+ id: "partner.teams.members.list",
2798
+ method: "GET",
2799
+ path: "/teams/{teamId}/members",
2800
+ visibility: "public",
2801
+ semantics: {
2802
+ kind: "query",
2803
+ sideEffects: "none",
2804
+ idempotent: true,
2805
+ retry: "idempotent",
2806
+ readConsistency: "primary"
2807
+ },
2808
+ auth: {
2809
+ credentials: ["partner_key"],
2810
+ scopes: ["teams:read"],
2811
+ ownership: [{
2812
+ credential: "partner_key",
2813
+ rule: "partner_tenant"
2814
+ }]
2815
+ },
2816
+ request: {
2817
+ params: z.strictObject({ teamId: realtimeSchemas.publicTeamId }),
2818
+ query: null,
2819
+ headers: requestHeaders,
2820
+ body: null
2821
+ },
2822
+ responses: { 200: teamMembersResponse },
2823
+ errors: partnerUserErrors,
2824
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
2825
+ resources: {
2826
+ reads: [{
2827
+ type: "partner.team",
2828
+ idFrom: "params.teamId"
2829
+ }],
2830
+ changes: []
2831
+ },
2832
+ lifecycle: { introduced: "1.3.0" },
2833
+ docs: {
2834
+ summary: "List team members",
2835
+ description: "Lists the members of a team owned by the authenticated partner tenant.",
2836
+ tags: ["Teams"],
2837
+ examples: {
2838
+ request: { params: { teamId: "t_01" } },
2839
+ response: {
2840
+ data: { members: [] },
2841
+ meta: {
2842
+ requestId: "req_01",
2843
+ surface: "partner",
2844
+ version: "1.0"
2845
+ }
2846
+ }
2847
+ }
2848
+ }
2849
+ }),
2850
+ addTeamMember: defineHttpOperation({
2851
+ id: "partner.teams.members.add",
2852
+ method: "POST",
2853
+ path: "/teams/{teamId}/members",
2854
+ visibility: "public",
2855
+ semantics: {
2856
+ kind: "mutation",
2857
+ sideEffects: "state",
2858
+ idempotent: true,
2859
+ retry: "idempotent",
2860
+ readConsistency: null
2861
+ },
2862
+ auth: {
2863
+ credentials: ["partner_key"],
2864
+ scopes: ["teams:write"],
2865
+ ownership: [{
2866
+ credential: "partner_key",
2867
+ rule: "partner_tenant"
2868
+ }]
2869
+ },
2870
+ request: {
2871
+ params: z.strictObject({ teamId: realtimeSchemas.publicTeamId }),
2872
+ query: null,
2873
+ headers: requestHeaders,
2874
+ body: addTeamMemberRequest
2875
+ },
2876
+ responses: { 200: teamMemberAddedResponse },
2877
+ errors: partnerUserErrors,
2878
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
2879
+ resources: {
2880
+ reads: [{
2881
+ type: "partner.team",
2882
+ idFrom: "params.teamId"
2883
+ }],
2884
+ changes: [{
2885
+ type: "partner.team",
2886
+ idFrom: "params.teamId"
2887
+ }]
2888
+ },
2889
+ lifecycle: { introduced: "1.3.0" },
2890
+ docs: {
2891
+ summary: "Add a team member",
2892
+ description: "Adds a user to a team owned by the authenticated partner tenant, or reports it was already a member.",
2893
+ tags: ["Teams"],
2894
+ examples: {
2895
+ request: {
2896
+ params: { teamId: "t_01" },
2897
+ body: {
2898
+ userId: "u_02",
2899
+ role: "editor"
2900
+ }
2901
+ },
2902
+ response: {
2903
+ data: {
2904
+ ok: true,
2905
+ role: "editor"
2906
+ },
2907
+ meta: {
2908
+ requestId: "req_01",
2909
+ surface: "partner",
2910
+ version: "1.0"
2911
+ }
2912
+ }
2913
+ }
2914
+ }
2915
+ }),
2916
+ updateTeamMemberRole: defineHttpOperation({
2917
+ id: "partner.teams.members.role.update",
2918
+ method: "PATCH",
2919
+ path: "/teams/{teamId}/members/{userId}",
2920
+ visibility: "public",
2921
+ semantics: {
2922
+ kind: "mutation",
2923
+ sideEffects: "state",
2924
+ idempotent: true,
2925
+ retry: "idempotent",
2926
+ readConsistency: null
2927
+ },
2928
+ auth: {
2929
+ credentials: ["partner_key"],
2930
+ scopes: ["teams:write"],
2931
+ ownership: [{
2932
+ credential: "partner_key",
2933
+ rule: "partner_tenant"
2934
+ }]
2935
+ },
2936
+ request: {
2937
+ params: z.strictObject({
2938
+ teamId: realtimeSchemas.publicTeamId,
2939
+ userId: realtimeSchemas.publicUserId
2940
+ }),
2941
+ query: null,
2942
+ headers: requestHeaders,
2943
+ body: updateTeamMemberRoleRequest
2944
+ },
2945
+ responses: { 200: teamMemberRoleResponse },
2946
+ errors: partnerUserErrors,
2947
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
2948
+ resources: {
2949
+ reads: [{
2950
+ type: "partner.team",
2951
+ idFrom: "params.teamId"
2952
+ }, {
2953
+ type: "partner.user",
2954
+ idFrom: "params.userId"
2955
+ }],
2956
+ changes: [{
2957
+ type: "partner.team",
2958
+ idFrom: "params.teamId"
2959
+ }, {
2960
+ type: "partner.user",
2961
+ idFrom: "params.userId"
2962
+ }]
2963
+ },
2964
+ lifecycle: { introduced: "1.3.0" },
2965
+ docs: {
2966
+ summary: "Update a team member role",
2967
+ description: "Updates the role of an existing member of a team owned by the authenticated partner tenant.",
2968
+ tags: ["Teams"],
2969
+ examples: {
2970
+ request: {
2971
+ params: {
2972
+ teamId: "t_01",
2973
+ userId: "u_02"
2974
+ },
2975
+ body: { role: "admin" }
2976
+ },
2977
+ response: {
2978
+ data: {
2979
+ ok: true,
2980
+ role: "admin"
2981
+ },
2982
+ meta: {
2983
+ requestId: "req_01",
2984
+ surface: "partner",
2985
+ version: "1.0"
2986
+ }
2987
+ }
2988
+ }
2989
+ }
2990
+ }),
2991
+ removeTeamMember: defineHttpOperation({
2992
+ id: "partner.teams.members.remove",
2993
+ method: "DELETE",
2994
+ path: "/teams/{teamId}/members/{userId}",
2995
+ visibility: "public",
2996
+ semantics: {
2997
+ kind: "mutation",
2998
+ sideEffects: "state",
2999
+ idempotent: true,
3000
+ retry: "idempotent",
3001
+ readConsistency: null
3002
+ },
3003
+ auth: {
3004
+ credentials: ["partner_key"],
3005
+ scopes: ["teams:write"],
3006
+ ownership: [{
3007
+ credential: "partner_key",
3008
+ rule: "partner_tenant"
3009
+ }]
3010
+ },
3011
+ request: {
3012
+ params: z.strictObject({
3013
+ teamId: realtimeSchemas.publicTeamId,
3014
+ userId: realtimeSchemas.publicUserId
3015
+ }),
3016
+ query: null,
3017
+ headers: requestHeaders,
3018
+ body: null
3019
+ },
3020
+ responses: { 200: teamMemberRemovedResponse },
3021
+ errors: partnerUserErrors,
3022
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3023
+ resources: {
3024
+ reads: [{
3025
+ type: "partner.team",
3026
+ idFrom: "params.teamId"
3027
+ }, {
3028
+ type: "partner.user",
3029
+ idFrom: "params.userId"
3030
+ }],
3031
+ changes: [{
3032
+ type: "partner.team",
3033
+ idFrom: "params.teamId"
3034
+ }, {
3035
+ type: "partner.user",
3036
+ idFrom: "params.userId"
3037
+ }]
3038
+ },
3039
+ lifecycle: { introduced: "1.3.0" },
3040
+ docs: {
3041
+ summary: "Remove a team member",
3042
+ description: "Removes a member from a team owned by the authenticated partner tenant.",
3043
+ tags: ["Teams"],
3044
+ examples: {
3045
+ request: { params: {
3046
+ teamId: "t_01",
3047
+ userId: "u_02"
3048
+ } },
3049
+ response: {
3050
+ data: { ok: true },
3051
+ meta: {
3052
+ requestId: "req_01",
3053
+ surface: "partner",
3054
+ version: "1.0"
3055
+ }
3056
+ }
3057
+ }
3058
+ }
3059
+ }),
3060
+ updateSiteTeam: defineHttpOperation({
3061
+ id: "partner.sites.team.update",
3062
+ method: "PATCH",
3063
+ path: "/sites/{siteId}/team",
3064
+ visibility: "public",
3065
+ semantics: {
3066
+ kind: "mutation",
3067
+ sideEffects: "state",
3068
+ idempotent: true,
3069
+ retry: "idempotent",
3070
+ readConsistency: null
3071
+ },
3072
+ auth: {
3073
+ credentials: ["partner_key"],
3074
+ scopes: ["sites:write"],
3075
+ ownership: [{
3076
+ credential: "partner_key",
3077
+ rule: "authorized_site"
3078
+ }]
3079
+ },
3080
+ request: {
3081
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
3082
+ query: null,
3083
+ headers: requestHeaders,
3084
+ body: bindSiteTeamRequest
3085
+ },
3086
+ responses: { 200: siteTeamBindingResponse },
3087
+ errors: partnerSiteErrors,
3088
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
3089
+ resources: {
3090
+ reads: [{
3091
+ type: "site.registration",
3092
+ idFrom: "params.siteId"
3093
+ }],
3094
+ changes: [{
3095
+ type: "site.registration",
3096
+ idFrom: "params.siteId"
3097
+ }]
3098
+ },
3099
+ lifecycle: { introduced: "1.3.0" },
3100
+ docs: {
3101
+ summary: "Bind a site to a team",
3102
+ description: "Binds or unbinds (teamId: null) a partner-owned site to a partner-owned team.",
3103
+ tags: ["Teams"],
3104
+ examples: {
3105
+ request: {
3106
+ params: { siteId: "s_01" },
3107
+ body: { teamId: "t_01" }
3108
+ },
3109
+ response: {
3110
+ data: {
3111
+ ok: true,
3112
+ teamId: "t_01"
3113
+ },
3114
+ meta: {
3115
+ requestId: "req_01",
3116
+ surface: "partner",
3117
+ version: "1.0"
3118
+ }
3119
+ }
3120
+ }
3121
+ }
3122
+ }),
3123
+ getTeamCatalog: defineHttpOperation({
3124
+ id: "partner.teams.catalog.get",
3125
+ method: "GET",
3126
+ path: "/teams/{teamId}/catalog",
3127
+ visibility: "public",
3128
+ semantics: {
3129
+ kind: "query",
3130
+ sideEffects: "none",
3131
+ idempotent: true,
3132
+ retry: "idempotent",
3133
+ readConsistency: "primary"
3134
+ },
3135
+ auth: {
3136
+ credentials: ["partner_key"],
3137
+ scopes: ["teams:read"],
3138
+ ownership: [{
3139
+ credential: "partner_key",
3140
+ rule: "partner_tenant"
3141
+ }]
3142
+ },
3143
+ request: {
3144
+ params: z.strictObject({ teamId: realtimeSchemas.publicTeamId }),
3145
+ query: null,
3146
+ headers: requestHeaders,
3147
+ body: null
3148
+ },
3149
+ responses: { 200: teamCatalogResponse },
3150
+ errors: partnerUserErrors,
3151
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3152
+ resources: {
3153
+ reads: [{
3154
+ type: "partner.team",
3155
+ idFrom: "params.teamId"
3156
+ }],
3157
+ changes: []
3158
+ },
3159
+ lifecycle: { introduced: "1.3.0" },
3160
+ docs: {
3161
+ summary: "Get a team catalog",
3162
+ description: "Returns the Iceberg catalog reference bound to a partner-owned team, if any.",
3163
+ tags: ["Teams"],
3164
+ examples: {
3165
+ request: { params: { teamId: "t_01" } },
3166
+ response: {
3167
+ data: {
3168
+ teamId: "t_01",
3169
+ catalogUri: null,
3170
+ warehouse: null,
3171
+ bucket: null,
3172
+ namespace: null,
3173
+ provisioningState: null,
3174
+ keyEncoding: null,
3175
+ catalogTablesReady: false,
3176
+ readsEnabled: false
3177
+ },
3178
+ meta: {
3179
+ requestId: "req_01",
3180
+ surface: "partner",
3181
+ version: "1.0"
3182
+ }
3183
+ }
3184
+ }
3185
+ }
3186
+ }),
3187
+ bindTeamCatalog: defineHttpOperation({
3188
+ id: "partner.teams.catalog.bind",
3189
+ method: "POST",
3190
+ path: "/teams/{teamId}/catalog",
3191
+ visibility: "public",
3192
+ semantics: {
3193
+ kind: "mutation",
3194
+ sideEffects: "state",
3195
+ idempotent: true,
3196
+ retry: "idempotent",
3197
+ readConsistency: null
3198
+ },
3199
+ auth: {
3200
+ credentials: ["partner_key"],
3201
+ scopes: ["teams:write"],
3202
+ ownership: [{
3203
+ credential: "partner_key",
3204
+ rule: "partner_tenant"
3205
+ }]
3206
+ },
3207
+ request: {
3208
+ params: z.strictObject({ teamId: realtimeSchemas.publicTeamId }),
3209
+ query: null,
3210
+ headers: requestHeaders,
3211
+ body: bindTeamCatalogRequest
3212
+ },
3213
+ responses: { 200: teamCatalogBindResponse },
3214
+ errors: partnerUserErrors,
3215
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3216
+ resources: {
3217
+ reads: [{
3218
+ type: "partner.team",
3219
+ idFrom: "params.teamId"
3220
+ }],
3221
+ changes: [{
3222
+ type: "partner.team",
3223
+ idFrom: "params.teamId"
3224
+ }]
3225
+ },
3226
+ lifecycle: { introduced: "1.3.0" },
3227
+ docs: {
3228
+ summary: "Bind a team catalog",
3229
+ description: "Binds an Iceberg catalog (URI, warehouse, and optional bucket/namespace) to a partner-owned team.",
3230
+ tags: ["Teams"],
3231
+ examples: {
3232
+ request: {
3233
+ params: { teamId: "t_01" },
3234
+ body: {
3235
+ catalogUri: "gs://bucket/catalog",
3236
+ warehouse: "primary",
3237
+ namespace: "ns1",
3238
+ bucket: "bucket1"
3239
+ }
3240
+ },
3241
+ response: {
3242
+ data: {
3243
+ teamId: "t_01",
3244
+ status: "ready",
3245
+ catalogUri: "gs://bucket/catalog",
3246
+ warehouse: "primary",
3247
+ bucket: "bucket1",
3248
+ namespace: "ns1"
3249
+ },
3250
+ meta: {
3251
+ requestId: "req_01",
3252
+ surface: "partner",
3253
+ version: "1.0"
3254
+ }
3255
+ }
3256
+ }
3257
+ }
3258
+ }),
3259
+ getSiteIntIdCrosswalk: defineHttpOperation({
3260
+ id: "partner.users.sites.crosswalk.get",
3261
+ method: "GET",
3262
+ path: "/users/{userId}/sites/crosswalk",
3263
+ visibility: "public",
3264
+ semantics: {
3265
+ kind: "query",
3266
+ sideEffects: "none",
3267
+ idempotent: true,
3268
+ retry: "idempotent",
3269
+ readConsistency: "primary"
3270
+ },
3271
+ auth: {
3272
+ credentials: ["user_key", "partner_key"],
3273
+ scopes: ["sites:read"],
3274
+ ownership: [{
3275
+ credential: "user_key",
3276
+ rule: "self"
3277
+ }, {
3278
+ credential: "partner_key",
3279
+ rule: "linked_user"
3280
+ }]
3281
+ },
3282
+ request: {
3283
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
3284
+ query: null,
3285
+ headers: requestHeaders,
3286
+ body: null
3287
+ },
3288
+ responses: { 200: siteIntIdCrosswalkResponse },
3289
+ errors: partnerUserErrors,
3290
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3291
+ resources: {
3292
+ reads: [{
3293
+ type: "partner.user",
3294
+ idFrom: "params.userId"
3295
+ }, {
3296
+ type: "user.sites",
3297
+ idFrom: "params.userId"
3298
+ }],
3299
+ changes: []
3300
+ },
3301
+ lifecycle: { introduced: "1.3.0" },
3302
+ docs: {
3303
+ summary: "Get the site int-id crosswalk",
3304
+ description: "Maps a user's public site IDs to their internal integer IDs, for partners that need the legacy numeric identifier.",
3305
+ tags: ["Sites"],
3306
+ examples: {
3307
+ request: { params: { userId: "u_01" } },
3308
+ response: {
3309
+ data: {
3310
+ crosswalk: {},
3311
+ sites: []
3312
+ },
3313
+ meta: {
3314
+ requestId: "req_01",
3315
+ surface: "partner",
3316
+ version: "1.0"
3317
+ }
3318
+ }
3319
+ }
3320
+ }
3321
+ }),
3322
+ deleteUser: defineHttpOperation({
3323
+ id: "partner.users.delete",
3324
+ method: "DELETE",
3325
+ path: "/users/{userId}",
3326
+ visibility: "public",
3327
+ semantics: {
3328
+ kind: "mutation",
3329
+ sideEffects: "state",
3330
+ idempotent: true,
3331
+ retry: "idempotent",
3332
+ readConsistency: null
3333
+ },
3334
+ auth: {
3335
+ credentials: ["partner_key"],
3336
+ scopes: ["users:write"],
3337
+ ownership: [{
3338
+ credential: "partner_key",
3339
+ rule: "linked_user"
3340
+ }]
3341
+ },
3342
+ request: {
3343
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
3344
+ query: null,
3345
+ headers: requestHeaders,
3346
+ body: null
3347
+ },
3348
+ responses: { 200: deletePartnerUserResponse },
3349
+ errors: partnerUserErrors,
3350
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3351
+ resources: {
3352
+ reads: [{
3353
+ type: "partner.user",
3354
+ idFrom: "params.userId"
3355
+ }],
3356
+ changes: [{
3357
+ type: "partner.user",
3358
+ idFrom: "params.userId"
3359
+ }, {
3360
+ type: "user.sites",
3361
+ idFrom: "params.userId"
3362
+ }]
3363
+ },
3364
+ lifecycle: { introduced: "1.3.0" },
3365
+ docs: {
3366
+ summary: "Delete a partner user",
3367
+ description: "Queues cascade deletion of a partner-linked user and their sites.",
3368
+ tags: ["Users"],
3369
+ examples: {
3370
+ request: { params: { userId: "u_01" } },
3371
+ response: {
3372
+ data: {
3373
+ ok: true,
3374
+ queued: true,
3375
+ userId: 1,
3376
+ publicId: "u_01"
3377
+ },
3378
+ meta: {
3379
+ requestId: "req_01",
3380
+ surface: "partner",
3381
+ version: "1.0"
3382
+ }
3383
+ }
3384
+ }
3385
+ }
3386
+ }),
3387
+ createVerificationToken: defineHttpOperation({
3388
+ id: "partner.users.verification.token.create",
3389
+ method: "POST",
3390
+ path: "/users/{userId}/verification-token",
3391
+ visibility: "public",
3392
+ semantics: {
3393
+ kind: "query",
3394
+ sideEffects: "none",
3395
+ idempotent: true,
3396
+ retry: "idempotent",
3397
+ readConsistency: "primary"
3398
+ },
3399
+ auth: {
3400
+ credentials: ["user_key", "partner_key"],
3401
+ scopes: ["sites:write"],
3402
+ ownership: [{
3403
+ credential: "user_key",
3404
+ rule: "self"
3405
+ }, {
3406
+ credential: "partner_key",
3407
+ rule: "linked_user"
3408
+ }]
3409
+ },
3410
+ request: {
3411
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
3412
+ query: null,
3413
+ headers: requestHeaders,
3414
+ body: verificationTokenRequest
3415
+ },
3416
+ responses: { 200: verificationTokenResponse },
3417
+ errors: partnerUserErrors,
3418
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3419
+ resources: {
3420
+ reads: [{
3421
+ type: "partner.user",
3422
+ idFrom: "params.userId"
3423
+ }, {
3424
+ type: "user.sites",
3425
+ idFrom: "params.userId"
3426
+ }],
3427
+ changes: []
3428
+ },
3429
+ lifecycle: { introduced: "1.3.0" },
3430
+ docs: {
3431
+ summary: "Create a site verification token",
3432
+ description: "Mints a Search Console site-ownership verification token (meta tag or DNS record) for a not-yet-registered site.",
3433
+ tags: ["Sites"],
3434
+ examples: {
3435
+ request: {
3436
+ params: { userId: "u_01" },
3437
+ body: {
3438
+ siteUrl: "https://example.com",
3439
+ method: "DNS_TXT"
3440
+ }
3441
+ },
3442
+ response: {
3443
+ data: {
3444
+ siteUrl: "https://example.com",
3445
+ site: {
3446
+ type: "INET_DOMAIN",
3447
+ identifier: "example.com"
3448
+ },
3449
+ method: "DNS_TXT",
3450
+ token: "abc123",
3451
+ metaContent: null,
3452
+ dnsRecord: {
3453
+ type: "TXT",
3454
+ host: "_gsc.example.com",
3455
+ value: "abc123"
3456
+ }
3457
+ },
3458
+ meta: {
3459
+ requestId: "req_01",
3460
+ surface: "partner",
3461
+ version: "1.0"
3462
+ }
3463
+ }
3464
+ }
3465
+ }
3466
+ }),
3467
+ addAndVerifySite: defineHttpOperation({
3468
+ id: "partner.users.sites.verify.create",
3469
+ method: "POST",
3470
+ path: "/users/{userId}/sites/verify",
3471
+ visibility: "public",
3472
+ semantics: {
3473
+ kind: "mutation",
3474
+ sideEffects: "state",
3475
+ idempotent: true,
3476
+ retry: "idempotent",
3477
+ readConsistency: null
3478
+ },
3479
+ auth: {
3480
+ credentials: ["user_key", "partner_key"],
3481
+ scopes: ["sites:write"],
3482
+ ownership: [{
3483
+ credential: "user_key",
3484
+ rule: "self"
3485
+ }, {
3486
+ credential: "partner_key",
3487
+ rule: "linked_user"
3488
+ }]
3489
+ },
3490
+ request: {
3491
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
3492
+ query: null,
3493
+ headers: requestHeaders,
3494
+ body: addAndVerifySiteRequest
3495
+ },
3496
+ responses: { 200: addAndVerifySiteResponse },
3497
+ errors: partnerUserErrors,
3498
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3499
+ resources: {
3500
+ reads: [{
3501
+ type: "partner.user",
3502
+ idFrom: "params.userId"
3503
+ }],
3504
+ changes: [{
3505
+ type: "user.sites",
3506
+ idFrom: "params.userId"
3507
+ }]
3508
+ },
3509
+ lifecycle: { introduced: "1.3.0" },
3510
+ docs: {
3511
+ summary: "Add and verify a site",
3512
+ description: "Verifies Search Console ownership of a site for a user via the given method and records the verified ownership.",
3513
+ tags: ["Sites"],
3514
+ examples: {
3515
+ request: {
3516
+ params: { userId: "u_01" },
3517
+ body: {
3518
+ siteUrl: "https://example.com",
3519
+ method: "DNS_TXT"
3520
+ }
3521
+ },
3522
+ response: {
3523
+ data: {
3524
+ siteUrl: "https://example.com",
3525
+ site: {
3526
+ type: "INET_DOMAIN",
3527
+ identifier: "example.com"
3528
+ },
3529
+ method: "DNS_TXT",
3530
+ verified: true,
3531
+ owners: ["owner@example.com"]
3532
+ },
3533
+ meta: {
3534
+ requestId: "req_01",
3535
+ surface: "partner",
3536
+ version: "1.0"
3537
+ }
3538
+ }
3539
+ }
3540
+ }
3541
+ }),
3542
+ queryCrossSource: defineHttpOperation({
3543
+ id: "partner.sites.cross.source.query",
3544
+ method: "POST",
3545
+ path: "/sites/{siteId}/cross-source",
3546
+ visibility: "public",
3547
+ semantics: {
3548
+ kind: "query",
3549
+ sideEffects: "none",
3550
+ idempotent: true,
3551
+ retry: "idempotent",
3552
+ readConsistency: "primary"
3553
+ },
3554
+ auth: {
3555
+ credentials: ["partner_key"],
3556
+ scopes: ["analytics:read"],
3557
+ ownership: [{
3558
+ credential: "partner_key",
3559
+ rule: "authorized_site"
3560
+ }]
3561
+ },
3562
+ request: {
3563
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
3564
+ query: null,
3565
+ headers: requestHeaders,
3566
+ body: crossSourceRequest
3567
+ },
3568
+ responses: { 200: crossSourceResponse },
3569
+ errors: partnerSiteErrors,
3570
+ errorResponse: errorEnvelopeSchemas(partnerSiteErrors, realtimeSchemas.publicRequestId),
3571
+ resources: {
3572
+ reads: [{
3573
+ type: "site.analytics",
3574
+ idFrom: "params.siteId"
3575
+ }],
3576
+ changes: []
3577
+ },
3578
+ lifecycle: { introduced: "1.3.0" },
3579
+ docs: {
3580
+ summary: "Query cross-source analysis",
3581
+ description: "Runs one predefined cross-source query joining crawl, CWV, and GSC signals for a site.",
3582
+ tags: ["Analytics"],
3583
+ examples: {
3584
+ request: {
3585
+ params: { siteId: "s_01" },
3586
+ body: {
3587
+ queryKey: "crawl-error-losing-impressions",
3588
+ rangeDays: 28,
3589
+ limit: 50
3590
+ }
3591
+ },
3592
+ response: {
3593
+ data: {
3594
+ sources: ["crawl", "gsc"],
3595
+ rows: []
3596
+ },
3597
+ meta: {
3598
+ requestId: "req_01",
3599
+ surface: "partner",
3600
+ version: "1.0"
3601
+ }
3602
+ }
3603
+ }
3604
+ }
3605
+ }),
3606
+ enrichKeywords: defineHttpOperation({
3607
+ id: "partner.keywords.enrich.query",
3608
+ method: "POST",
3609
+ path: "/keywords/enrich",
3610
+ visibility: "public",
3611
+ semantics: {
3612
+ kind: "query",
3613
+ sideEffects: "none",
3614
+ idempotent: true,
3615
+ retry: "idempotent",
3616
+ readConsistency: "primary"
3617
+ },
3618
+ auth: {
3619
+ credentials: ["user_key", "partner_key"],
3620
+ scopes: ["analytics:read"],
3621
+ ownership: [{
3622
+ credential: "user_key",
3623
+ rule: "self"
3624
+ }, {
3625
+ credential: "partner_key",
3626
+ rule: "partner_tenant"
3627
+ }]
3628
+ },
3629
+ request: {
3630
+ params: null,
3631
+ query: null,
3632
+ headers: requestHeaders,
3633
+ body: enrichKeywordsRequest
3634
+ },
3635
+ responses: { 200: enrichKeywordsResponse },
3636
+ errors: partnerUserErrors,
3637
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
3638
+ resources: {
3639
+ reads: [],
3640
+ changes: []
3641
+ },
3642
+ lifecycle: { introduced: "1.3.0" },
3643
+ docs: {
3644
+ summary: "Enrich keywords with metrics",
3645
+ description: "Returns difficulty, search volume, and CPC estimates for up to 500 keywords.",
3646
+ tags: ["Analytics"],
3647
+ examples: {
3648
+ request: { body: { keywords: ["nuxt seo"] } },
3649
+ response: {
3650
+ data: { metrics: { "nuxt seo": {
3651
+ difficulty: 40,
3652
+ searchVolume: 100,
3653
+ cpc: 1.2
3654
+ } } },
3655
+ meta: {
3656
+ requestId: "req_01",
3657
+ surface: "partner",
3658
+ version: "1.0"
3659
+ }
3660
+ }
3661
+ }
3662
+ }
3663
+ })
3664
+ }
3665
+ });
3666
+ const analytics = defineHttpSurface({
3667
+ name: "analytics",
3668
+ prefix: "/api/analytics/v1",
3669
+ version: "1.0",
3670
+ operations: {
3671
+ queryRows: defineHttpOperation({
3672
+ id: "analytics.rows.query",
3673
+ method: "POST",
3674
+ path: "/sites/{siteId}/rows",
3675
+ visibility: "public",
3676
+ semantics: {
3677
+ kind: "query",
3678
+ sideEffects: "none",
3679
+ idempotent: true,
3680
+ retry: "idempotent",
3681
+ readConsistency: "primary"
3682
+ },
3683
+ auth: {
3684
+ credentials: ["user_key", "partner_key"],
3685
+ scopes: ["analytics:execute"],
3686
+ ownership: [{
3687
+ credential: "user_key",
3688
+ rule: "authorized_site"
3689
+ }, {
3690
+ credential: "partner_key",
3691
+ rule: "authorized_site"
3692
+ }]
3693
+ },
3694
+ request: {
3695
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
3696
+ query: null,
3697
+ headers: requestHeaders,
3698
+ body: analyticsRowsRequest
3699
+ },
3700
+ responses: { 200: analyticsRowsResponse },
3701
+ errors: analyticsRowsErrors,
3702
+ errorResponse: errorEnvelopeSchemas(analyticsRowsErrors, realtimeSchemas.publicRequestId),
3703
+ resources: {
3704
+ reads: [{
3705
+ type: "site.analytics",
3706
+ idFrom: "params.siteId"
3707
+ }],
3708
+ changes: []
3709
+ },
3710
+ lifecycle: { introduced: "1.0.0" },
3711
+ docs: {
3712
+ summary: "Query analytics rows",
3713
+ description: "Executes an idempotent primary-consistent analytics row query.",
3714
+ tags: ["Analytics rows"],
3715
+ examples: {
3716
+ request: {
3717
+ params: { siteId: "s_01" },
3718
+ body: {
3719
+ dimensions: ["query"],
3720
+ metrics: ["clicks", "impressions"],
3721
+ rowLimit: 100
3722
+ }
3723
+ },
3724
+ response: {
3725
+ data: { rows: [] },
3726
+ meta: {
3727
+ requestId: "req_01",
3728
+ surface: "analytics",
3729
+ version: "1.0",
3730
+ sourceName: "primary",
3731
+ sourceKind: "sql",
3732
+ queryMs: 12
3733
+ }
3734
+ }
3735
+ }
3736
+ }
3737
+ }),
3738
+ queryReport: defineHttpOperation({
3739
+ id: "analytics.reports.query",
3740
+ method: "POST",
3741
+ path: "/sites/{siteId}/reports",
3742
+ visibility: "public",
3743
+ semantics: {
3744
+ kind: "query",
3745
+ sideEffects: "none",
3746
+ idempotent: true,
3747
+ retry: "idempotent",
3748
+ readConsistency: "primary"
3749
+ },
3750
+ auth: {
3751
+ credentials: ["user_key", "partner_key"],
3752
+ scopes: ["analytics:execute"],
3753
+ ownership: [{
3754
+ credential: "user_key",
3755
+ rule: "authorized_site"
3756
+ }, {
3757
+ credential: "partner_key",
3758
+ rule: "authorized_site"
3759
+ }]
3760
+ },
3761
+ request: {
3762
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
3763
+ query: null,
3764
+ headers: requestHeaders,
3765
+ body: analyticsReportRequest
3766
+ },
3767
+ responses: { 200: analyticsReportResponse },
3768
+ errors: analyticsRowsErrors,
3769
+ errorResponse: errorEnvelopeSchemas(analyticsRowsErrors, realtimeSchemas.publicRequestId),
3770
+ resources: {
3771
+ reads: [{
3772
+ type: "site.analytics",
3773
+ idFrom: "params.siteId"
3774
+ }],
3775
+ changes: []
3776
+ },
3777
+ lifecycle: { introduced: "1.0.0" },
3778
+ docs: {
3779
+ summary: "Query an analytics report",
3780
+ description: "Returns the hosted analytics list report with totals, comparison fields, and sync metadata.",
3781
+ tags: ["Analytics reports"],
3782
+ examples: {
3783
+ request: {
3784
+ params: { siteId: "s_01" },
3785
+ body: { state: {
3786
+ dimensions: ["query"],
3787
+ searchType: "web"
3788
+ } }
3789
+ },
3790
+ response: {
3791
+ data: {
3792
+ rows: [],
3793
+ totalCount: 0,
3794
+ totals: {
3795
+ clicks: 0,
3796
+ impressions: 0,
3797
+ ctr: 0,
3798
+ position: 0
3799
+ },
3800
+ meta: {
3801
+ siteUrl: "sc-domain:example.com",
3802
+ syncStatus: "synced",
3803
+ newestDateSynced: null,
3804
+ oldestDateSynced: null,
3805
+ dataDelay: "0 days"
3806
+ }
3807
+ },
3808
+ meta: {
3809
+ requestId: "req_01",
3810
+ surface: "analytics",
3811
+ version: "1.0",
3812
+ sourceName: "hosted-report",
3813
+ sourceKind: "sql",
3814
+ queryMs: 12
3815
+ }
3816
+ }
3817
+ }
3818
+ }
3819
+ }),
3820
+ queryReportDetail: defineHttpOperation({
3821
+ id: "analytics.reports.detail.query",
3822
+ method: "POST",
3823
+ path: "/sites/{siteId}/reports/detail",
3824
+ visibility: "public",
3825
+ semantics: {
3826
+ kind: "query",
3827
+ sideEffects: "none",
3828
+ idempotent: true,
3829
+ retry: "idempotent",
3830
+ readConsistency: "primary"
3831
+ },
3832
+ auth: {
3833
+ credentials: ["user_key", "partner_key"],
3834
+ scopes: ["analytics:execute"],
3835
+ ownership: [{
3836
+ credential: "user_key",
3837
+ rule: "authorized_site"
3838
+ }, {
3839
+ credential: "partner_key",
3840
+ rule: "authorized_site"
3841
+ }]
3842
+ },
3843
+ request: {
3844
+ params: z.strictObject({ siteId: realtimeSchemas.publicSiteId }),
3845
+ query: null,
3846
+ headers: requestHeaders,
3847
+ body: analyticsReportDetailRequest
3848
+ },
3849
+ responses: { 200: analyticsReportDetailResponse },
3850
+ errors: analyticsRowsErrors,
3851
+ errorResponse: errorEnvelopeSchemas(analyticsRowsErrors, realtimeSchemas.publicRequestId),
3852
+ resources: {
3853
+ reads: [{
3854
+ type: "site.analytics",
3855
+ idFrom: "params.siteId"
3856
+ }],
3857
+ changes: []
3858
+ },
3859
+ lifecycle: { introduced: "1.0.0" },
3860
+ docs: {
3861
+ summary: "Query analytics report detail",
3862
+ description: "Returns the hosted analytics timeseries report with current and comparison totals.",
3863
+ tags: ["Analytics reports"],
3864
+ examples: {
3865
+ request: {
3866
+ params: { siteId: "s_01" },
3867
+ body: { state: {
3868
+ dimensions: ["date"],
3869
+ searchType: "web"
3870
+ } }
3871
+ },
3872
+ response: {
3873
+ data: {
3874
+ daily: [],
3875
+ totals: {
3876
+ clicks: 0,
3877
+ impressions: 0,
3878
+ ctr: 0,
3879
+ position: 0
3880
+ },
3881
+ meta: {
3882
+ siteUrl: "sc-domain:example.com",
3883
+ syncStatus: "synced",
3884
+ newestDateSynced: null,
3885
+ oldestDateSynced: null,
3886
+ dataDelay: "0 days"
3887
+ }
3888
+ },
3889
+ meta: {
3890
+ requestId: "req_01",
3891
+ surface: "analytics",
3892
+ version: "1.0",
3893
+ sourceName: "hosted-report",
3894
+ sourceKind: "sql",
3895
+ queryMs: 12
3896
+ }
3897
+ }
3898
+ }
3899
+ }
3900
+ })
3901
+ }
3902
+ });
3903
+ const realtime = defineHttpSurface({
3904
+ name: "realtime",
3905
+ prefix: "/api/realtime/v1",
3906
+ version: "1.0",
3907
+ operations: {
3908
+ getStreamHead: defineHttpOperation({
3909
+ id: "realtime.stream.head.get",
3910
+ method: "GET",
3911
+ path: "/stream/head",
3912
+ visibility: "public",
3913
+ semantics: {
3914
+ kind: "query",
3915
+ sideEffects: "none",
3916
+ idempotent: true,
3917
+ retry: "idempotent",
3918
+ readConsistency: "primary"
3919
+ },
3920
+ auth: {
3921
+ credentials: ["user_key", "partner_key"],
3922
+ scopes: ["realtime:connect"],
3923
+ ownership: [{
3924
+ credential: "user_key",
3925
+ rule: "principal_stream"
3926
+ }, {
3927
+ credential: "partner_key",
3928
+ rule: "principal_stream"
3929
+ }]
3930
+ },
3931
+ request: {
3932
+ params: null,
3933
+ query: null,
3934
+ headers: requestHeaders,
3935
+ body: null
3936
+ },
3937
+ responses: { 200: headResponse },
3938
+ errors: realtimeErrors,
3939
+ errorResponse: errorEnvelopeSchemas(realtimeErrors, realtimeSchemas.publicRequestId),
3940
+ resources: {
3941
+ reads: [],
3942
+ changes: []
3943
+ },
3944
+ lifecycle: { introduced: "1.0.0" },
3945
+ docs: {
3946
+ summary: "Get the inferred stream head",
3947
+ description: "Returns the current durable head for the credential's one exact stream.",
3948
+ tags: ["Realtime"],
3949
+ examples: {
3950
+ request: {},
3951
+ response: {
3952
+ data: { head: {
3953
+ streamId: "user:u_01",
3954
+ sequence: "142"
3955
+ } },
3956
+ meta: {
3957
+ requestId: "req_01",
3958
+ surface: "realtime",
3959
+ version: "1.0"
3960
+ }
3961
+ }
3962
+ }
3963
+ }
3964
+ }),
3965
+ createTicket: defineHttpOperation({
3966
+ id: "realtime.tickets.create",
3967
+ method: "POST",
3968
+ path: "/tickets",
3969
+ visibility: "public",
3970
+ semantics: {
3971
+ kind: "mutation",
3972
+ sideEffects: "state",
3973
+ idempotent: false,
3974
+ retry: "never",
3975
+ readConsistency: null
3976
+ },
3977
+ auth: {
3978
+ credentials: ["user_key", "partner_key"],
3979
+ scopes: ["realtime:connect"],
3980
+ ownership: [{
3981
+ credential: "user_key",
3982
+ rule: "principal_stream"
3983
+ }, {
3984
+ credential: "partner_key",
3985
+ rule: "principal_stream"
3986
+ }]
3987
+ },
3988
+ request: {
3989
+ params: null,
3990
+ query: null,
3991
+ headers: requestHeaders,
3992
+ body: realtimeSchemas.ticketRequest
3993
+ },
3994
+ responses: { 201: ticketResponse },
3995
+ errors: realtimeErrors,
3996
+ errorResponse: errorEnvelopeSchemas(realtimeErrors, realtimeSchemas.publicRequestId),
3997
+ resources: {
3998
+ reads: [],
3999
+ changes: []
4000
+ },
4001
+ lifecycle: { introduced: "1.0.0" },
4002
+ docs: {
4003
+ summary: "Create a realtime ticket",
4004
+ description: "Creates a short-lived single-use ticket for the credential's inferred stream.",
4005
+ tags: ["Realtime"],
4006
+ examples: {
4007
+ request: { body: { origin: "https://nuxtseo.com" } },
4008
+ response: {
4009
+ data: {
4010
+ socketUrl: "wss://gscdump.com/ws/v1",
4011
+ protocol: GSCDUMP_REALTIME_SUBPROTOCOL,
4012
+ protocolVersion: 1,
4013
+ ticket: "gscdump.ticket.v1.cGF5bG9hZA.c2lnbmF0dXJl",
4014
+ expiresAt: "2026-07-14T08:01:00.000Z",
4015
+ head: {
4016
+ streamId: "user:u_01",
4017
+ sequence: "142"
4018
+ },
4019
+ maxConnectionSeconds: 900
4020
+ },
4021
+ meta: {
4022
+ requestId: "req_01",
4023
+ surface: "realtime",
4024
+ version: "1.0"
4025
+ }
4026
+ }
4027
+ }
4028
+ }
4029
+ })
4030
+ }
4031
+ });
4032
+ return {
4033
+ constants: {
4034
+ httpVersion: "1.0",
4035
+ realtimeProtocolVersion: 1,
4036
+ realtimeSubprotocol: GSCDUMP_REALTIME_SUBPROTOCOL,
4037
+ realtimeTicketPrefix: GSCDUMP_REALTIME_TICKET_PREFIX,
4038
+ realtimeTicketIssuer: GSCDUMP_REALTIME_TICKET_ISSUER,
4039
+ realtimeTicketAudience: GSCDUMP_REALTIME_TICKET_AUDIENCE,
4040
+ ping: GSCDUMP_REALTIME_PING,
4041
+ pong: GSCDUMP_REALTIME_PONG,
4042
+ ticketTtlSeconds: 60,
4043
+ maxConnectionSeconds: 900,
4044
+ ticketPolicy: GSCDUMP_REALTIME_TICKET_POLICY,
4045
+ connectionPolicy: GSCDUMP_REALTIME_CONNECTION_POLICY,
4046
+ replayPolicy: GSCDUMP_REALTIME_REPLAY_POLICY,
4047
+ limits: GSCDUMP_REALTIME_LIMITS,
4048
+ ackPolicy: GSCDUMP_REALTIME_ACK_POLICY,
4049
+ closeCodes: GSCDUMP_REALTIME_CLOSE_CODES,
4050
+ eventSemantics: REALTIME_V1_EVENT_SEMANTICS
4051
+ },
4052
+ schemas: {
4053
+ requestMetadata,
4054
+ requestHeaders,
4055
+ responseMeta,
4056
+ errorEnvelope,
4057
+ analyticsReportDetailRequest,
4058
+ analyticsReportDetailResponse,
4059
+ analyticsReportRequest,
4060
+ analyticsReportResponse,
4061
+ analyticsRowsRequest,
4062
+ analyticsRowsResponse,
4063
+ analysisBundleQuery,
4064
+ analysisBundleResponse,
4065
+ analysisQuery,
4066
+ analysisResponse,
4067
+ availableSitesQuery,
4068
+ availableSitesResponse,
4069
+ indexingDiagnosticsQuery,
4070
+ indexingDiagnosticsResponse,
4071
+ indexingSummaryQuery,
4072
+ indexingSummaryResponse,
4073
+ indexingUrlsQuery,
4074
+ indexingUrlsResponse,
4075
+ lifecycleResponse,
4076
+ registerSiteRequest,
4077
+ sitemapChangesQuery,
4078
+ sitemapChangesResponse,
4079
+ sitemapsResponse,
4080
+ siteDeletionResponse,
4081
+ siteRegistrationResponse,
4082
+ streamHeadResponse: headResponse,
4083
+ ticketResponse,
4084
+ userRegistrationResponse,
4085
+ userTokenUpdateResponse,
4086
+ ...realtimeSchemas
4087
+ },
4088
+ surfaces: {
4089
+ partner,
4090
+ analytics,
4091
+ realtime
4092
+ }
4093
+ };
4094
+ }
4095
+ export { createGscdumpV1Protocol };