samsar-js 0.48.23 → 0.48.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -131,6 +131,23 @@ await samsar.updateVideoOutroImage(
131
131
  { webhookUrl: 'https://example.com/webhook' },
132
132
  );
133
133
 
134
+ // Update the footer CTA on an existing video session
135
+ await samsar.updateVideoFooterImage(
136
+ {
137
+ videoSessionId: videoFromImages.data.session_id ?? videoFromImages.data.request_id!,
138
+ cta_text: 'Scan to book',
139
+ cta_logo: 'https://cdn.example.com/logo-white.png',
140
+ cta_url: 'https://example.com/book',
141
+ },
142
+ { webhookUrl: 'https://example.com/webhook' },
143
+ );
144
+
145
+ // Remove the footer from a cloned rerender
146
+ await samsar.updateVideoFooterImage({
147
+ videoSessionId: videoFromImages.data.session_id ?? videoFromImages.data.request_id!,
148
+ remove_footer: true,
149
+ });
150
+
134
151
  // Translate an existing video session into another language
135
152
  const translated = await samsar.translateVideo(
136
153
  {
@@ -445,6 +462,15 @@ const externalOutroUpdate = await platform.updateExternalVideoOutroImage(externa
445
462
  });
446
463
  console.log(externalOutroUpdate.data.request_id);
447
464
 
465
+ // Update or remove an external user's existing footer CTA.
466
+ const externalFooterUpdate = await platform.updateExternalVideoFooterImage(externalUser, {
467
+ request_id: externalRender.data.request_id,
468
+ cta_text: 'Scan to shop',
469
+ cta_logo: 'https://cdn.example.com/logo-white.png',
470
+ cta_url: 'https://example.com/shop',
471
+ });
472
+ console.log(externalFooterUpdate.data.request_id);
473
+
448
474
  // Repeated video routes accept the returned extreq_ id or the normalized external id.
449
475
  // The API resolves ownership through external request mappings and GlobalSession records.
450
476
 
@@ -516,14 +542,15 @@ Video model support notes:
516
542
  - `createVideoFromImageList` accepts either a provided outro (`outro_image_url`) or server-generated QR outro (`generate_outro_image: true` with `cta_url`). Do not combine the two modes in a single request.
517
543
  - `createVideoFromImageList` can render per-scene footer QR cards by setting `add_footer_animation: true` and providing one `footer_metadata` item per image scene.
518
544
  - `updateVideoOutroImage` accepts either a replacement outro image URL (`outro_image_url`, `outroImageUrl`, `new_outro_image_url`) or a generated QR CTA outro (`generate_outro_image: true` with `cta_url`, or just `cta_url` when no outro image URL is supplied). Generated outro updates reuse the existing session image layers for tiling and only queue frame/video regeneration.
519
- - Main video methods and external-user methods accept the same generated outro and footer parameters. The API can resolve either internal session ids or external `extreq_...` ids on repeated video routes, so client code can keep using `translateVideo`, `joinVideos`, `addSubtitles`, `removeSubtitles`, `addVideoOutroImage`, and `updateVideoOutroImage`; the explicit external variants are available when you want to call `/external_users/*` directly. Do not strip the `extreq_` prefix.
545
+ - `updateVideoFooterImage` updates the footer CTA on a cloned session with `cta_text`, `cta_logo`, and/or `cta_url`, or removes all scene footers with `remove_footer: true`. Footer updates queue only frame/video regeneration.
546
+ - Main video methods and external-user methods accept the same generated outro and footer parameters. The API can resolve either internal session ids or external `extreq_...` ids on repeated video routes, so client code can keep using `translateVideo`, `joinVideos`, `addSubtitles`, `removeSubtitles`, `addVideoOutroImage`, `updateVideoOutroImage`, and `updateVideoFooterImage`; the explicit external variants are available when you want to call `/external_users/*` directly. Do not strip the `extreq_` prefix.
520
547
  - Completed video status, latest-version, and completed-session list responses expose `has_subtitles` and `result_language` when the session metadata is available.
521
548
  - `publishPublication`, `editPublication`, and `revokePublication` manage public feed publications for completed sessions through free `/publications/*` endpoints. They work with account API keys, customer sub-account API keys, and client auth tokens when the session belongs to the authenticated actor.
522
549
  - Image-list video pricing is per rendered second: `VEO3.1I2V` and `SEEDANCEI2V` are 75 credits/sec, `KLING3.0` is 50 credits/sec, and `RUNWAYML` is 25 credits/sec.
523
550
 
524
551
  Upcoming `/v2` omni route adapters:
525
552
  - `/v2` is additive; `/v1` is not deprecated.
526
- - `createV2VideoFromText`, `createV2VideoFromImageList`, `updateV2VideoOutroImage`, `addV2VideoOutroImage`, `getV2Status`, `getV2Credits`, `listV2Requests`, and `createV2Session` call the new omni route surface.
553
+ - `createV2VideoFromText`, `createV2VideoFromImageList`, `updateV2VideoOutroImage`, `updateV2VideoFooterImage`, `addV2VideoOutroImage`, `getV2Status`, `getV2Credits`, `listV2Requests`, and `createV2Session` call the new omni route surface.
527
554
  - Programmatic user billing helpers include `createV2UserRechargeCredits`, `refreshV2UserToken`, `createV2UserAppKey`, `refreshV2UserAppKey`, `getV2UserCredits`, `getV2UserUsageLogs`, and `getV2UserPaymentStatus`.
528
555
  - Omit `externalUser` for internal account billing, pass `externalUser` to scope an external user with the account API key, or authenticate the client directly with an external-user auth token/API key.
529
556
 
package/dist/index.d.ts CHANGED
@@ -95,8 +95,18 @@ export interface OutroFocusArea {
95
95
  height: number;
96
96
  }
97
97
  export interface FooterMetadataItem {
98
- url: string;
98
+ url?: string;
99
+ cta_url?: string;
100
+ ctaUrl?: string;
99
101
  title?: string;
102
+ text?: string;
103
+ cta_text?: string;
104
+ ctaText?: string;
105
+ cta_logo?: string;
106
+ ctaLogo?: string;
107
+ logoUrl?: string;
108
+ logoImagePath?: string;
109
+ footerLogoImagePath?: string;
100
110
  }
101
111
  export type ImageListToVideoAspectRatio = '16:9' | '9:16';
102
112
  export type ImageListToVideoModel = 'VEO3.1I2V' | 'SEEDANCEI2V' | 'KLING3.0' | 'KLINGIMGTOVID3PRO' | 'RUNWAYML';
@@ -270,6 +280,39 @@ export interface UpdateVideoOutroImageResponse {
270
280
  remainingCredits?: number | null;
271
281
  [key: string]: unknown;
272
282
  }
283
+ export interface UpdateVideoFooterImageInput {
284
+ videoSessionId?: string;
285
+ video_session_id?: string;
286
+ videoSessionID?: string;
287
+ session_id?: string;
288
+ sessionId?: string;
289
+ sessionID?: string;
290
+ request_id?: string;
291
+ requestId?: string;
292
+ source_request_id?: string;
293
+ sourceRequestId?: string;
294
+ external_request_id?: string;
295
+ externalRequestId?: string;
296
+ external_session_id?: string;
297
+ externalSessionId?: string;
298
+ remove_footer?: boolean;
299
+ removeFooter?: boolean;
300
+ cta_text?: string;
301
+ ctaText?: string;
302
+ cta_logo?: string;
303
+ ctaLogo?: string;
304
+ cta_url?: string;
305
+ ctaUrl?: string;
306
+ [key: string]: unknown;
307
+ }
308
+ export interface UpdateVideoFooterImageResponse {
309
+ request_id?: string;
310
+ session_id?: string;
311
+ sessionID?: string;
312
+ creditsCharged?: number;
313
+ remainingCredits?: number | null;
314
+ [key: string]: unknown;
315
+ }
273
316
  export interface AddVideoOutroImageInput {
274
317
  videoSessionId?: string;
275
318
  video_session_id?: string;
@@ -1678,6 +1721,7 @@ export declare class SamsarClient {
1678
1721
  image_urls: string[];
1679
1722
  }>>;
1680
1723
  updateV2VideoOutroImage(input: UpdateVideoOutroImageInput, options?: V2RequestOptions): Promise<SamsarResult<UpdateVideoOutroImageResponse | ExternalRequestResponse>>;
1724
+ updateV2VideoFooterImage(input: UpdateVideoFooterImageInput, options?: V2RequestOptions): Promise<SamsarResult<UpdateVideoFooterImageResponse | ExternalRequestResponse>>;
1681
1725
  addV2VideoOutroImage(input: AddVideoOutroImageInput, options?: V2RequestOptions): Promise<SamsarResult<AddVideoOutroImageResponse | ExternalRequestResponse>>;
1682
1726
  getV2Status(requestId: string, options?: V2RequestOptions & {
1683
1727
  queryParams?: QueryParams;
@@ -1797,6 +1841,20 @@ export declare class SamsarClient {
1797
1841
  updateExternalVideoOutroImage(externalUser: ExternalUserIdentity, input: UpdateVideoOutroImageInput, options?: {
1798
1842
  webhookUrl?: string;
1799
1843
  } & SamsarRequestOptions): Promise<SamsarResult<ExternalRequestResponse>>;
1844
+ /**
1845
+ * Update or remove the footer for an existing video session by cloning it into a new session and
1846
+ * re-running frame/video generation.
1847
+ */
1848
+ updateVideoFooterImage(input: UpdateVideoFooterImageInput, options?: {
1849
+ webhookUrl?: string;
1850
+ } & SamsarRequestOptions): Promise<SamsarResult<UpdateVideoFooterImageResponse>>;
1851
+ /**
1852
+ * Update or remove the footer for an external-user video request through
1853
+ * /external_users/update_footer_image.
1854
+ */
1855
+ updateExternalVideoFooterImage(externalUser: ExternalUserIdentity, input: UpdateVideoFooterImageInput, options?: {
1856
+ webhookUrl?: string;
1857
+ } & SamsarRequestOptions): Promise<SamsarResult<ExternalRequestResponse>>;
1800
1858
  /**
1801
1859
  * Add or replace the outro image for an existing video session by cloning it into a new session and
1802
1860
  * re-running frame/video generation.
package/dist/index.js CHANGED
@@ -216,6 +216,61 @@ function normalizeUpdateVideoOutroImageInput(input, context = 'updateVideoOutroI
216
216
  ...(rawOutroFocusArea !== undefined ? { outro_focust_area: rawOutroFocusArea } : {}),
217
217
  };
218
218
  }
219
+ function normalizeUpdateVideoFooterImageInput(input, context = 'updateVideoFooterImage') {
220
+ const raw = input;
221
+ const videoSessionId = raw.videoSessionId ??
222
+ raw.video_session_id ??
223
+ raw.videoSessionID ??
224
+ raw.session_id ??
225
+ raw.sessionId ??
226
+ raw.sessionID ??
227
+ raw.request_id ??
228
+ raw.requestId ??
229
+ raw.source_request_id ??
230
+ raw.sourceRequestId ??
231
+ raw.external_request_id ??
232
+ raw.externalRequestId ??
233
+ raw.external_session_id ??
234
+ raw.externalSessionId;
235
+ const rawRemoveFooter = raw.remove_footer ??
236
+ raw.removeFooter;
237
+ const ctaText = raw.cta_text ??
238
+ raw.ctaText;
239
+ const ctaLogo = raw.cta_logo ??
240
+ raw.ctaLogo;
241
+ const ctaUrl = raw.cta_url ??
242
+ raw.ctaUrl;
243
+ const removeFooter = rawRemoveFooter === true;
244
+ if (!videoSessionId) {
245
+ throw new Error(`videoSessionId is required for ${context}`);
246
+ }
247
+ if (rawRemoveFooter !== undefined && typeof rawRemoveFooter !== 'boolean') {
248
+ throw new Error(`remove_footer must be a boolean for ${context}`);
249
+ }
250
+ if (ctaText !== undefined && typeof ctaText !== 'string') {
251
+ throw new Error(`cta_text must be a string for ${context}`);
252
+ }
253
+ if (ctaLogo !== undefined && typeof ctaLogo !== 'string') {
254
+ throw new Error(`cta_logo must be a string for ${context}`);
255
+ }
256
+ if (ctaUrl !== undefined && typeof ctaUrl !== 'string') {
257
+ throw new Error(`cta_url must be a string for ${context}`);
258
+ }
259
+ const normalizedCtaText = typeof ctaText === 'string' ? ctaText.trim() : '';
260
+ const normalizedCtaLogo = typeof ctaLogo === 'string' ? ctaLogo.trim() : '';
261
+ const normalizedCtaUrl = typeof ctaUrl === 'string' ? ctaUrl.trim() : '';
262
+ if (!removeFooter && !normalizedCtaText && !normalizedCtaLogo && !normalizedCtaUrl) {
263
+ throw new Error(`At least one of cta_text, cta_logo, or cta_url is required for ${context} unless remove_footer is true`);
264
+ }
265
+ return {
266
+ ...input,
267
+ videoSessionId: String(videoSessionId),
268
+ remove_footer: removeFooter,
269
+ ...(normalizedCtaText ? { cta_text: normalizedCtaText } : {}),
270
+ ...(normalizedCtaLogo ? { cta_logo: normalizedCtaLogo } : {}),
271
+ ...(normalizedCtaUrl ? { cta_url: normalizedCtaUrl } : {}),
272
+ };
273
+ }
219
274
  function normalizeSessionPublicationInput(input, context) {
220
275
  if (typeof input !== 'string' && (!input || typeof input !== 'object' || Array.isArray(input))) {
221
276
  throw new Error(`input must be a session id or object for ${context}`);
@@ -452,6 +507,13 @@ export class SamsarClient {
452
507
  webhookUrl: options?.webhookUrl,
453
508
  }, options);
454
509
  }
510
+ async updateV2VideoFooterImage(input, options) {
511
+ const normalizedInput = normalizeUpdateVideoFooterImageInput(input, 'updateV2VideoFooterImage');
512
+ return this.postV2('update_footer_image', {
513
+ input: normalizedInput,
514
+ webhookUrl: options?.webhookUrl,
515
+ }, options);
516
+ }
455
517
  async addV2VideoOutroImage(input, options) {
456
518
  return this.postV2('add_outro_image', {
457
519
  input,
@@ -923,6 +985,50 @@ export class SamsarClient {
923
985
  };
924
986
  return this.post('external_users/update_outro_image', body, options);
925
987
  }
988
+ /**
989
+ * Update or remove the footer for an existing video session by cloning it into a new session and
990
+ * re-running frame/video generation.
991
+ */
992
+ async updateVideoFooterImage(input, options) {
993
+ const normalizedInput = normalizeUpdateVideoFooterImageInput(input, 'updateVideoFooterImage');
994
+ const body = {
995
+ input: normalizedInput,
996
+ webhookUrl: options?.webhookUrl,
997
+ };
998
+ const response = await this.post('video/update_footer_image', body, options);
999
+ const data = response.data;
1000
+ if (data && typeof data === 'object') {
1001
+ const sessionId = typeof data.sessionID === 'string'
1002
+ ? data.sessionID
1003
+ : typeof data.session_id === 'string'
1004
+ ? data.session_id
1005
+ : typeof data.request_id === 'string'
1006
+ ? data.request_id
1007
+ : undefined;
1008
+ const normalizedSessionId = sessionId ? String(sessionId) : undefined;
1009
+ const normalizedData = {
1010
+ ...data,
1011
+ sessionID: data.sessionID ?? normalizedSessionId ?? '',
1012
+ session_id: data.session_id ?? normalizedSessionId,
1013
+ request_id: data.request_id ?? normalizedSessionId,
1014
+ };
1015
+ return { ...response, data: normalizedData };
1016
+ }
1017
+ return response;
1018
+ }
1019
+ /**
1020
+ * Update or remove the footer for an external-user video request through
1021
+ * /external_users/update_footer_image.
1022
+ */
1023
+ async updateExternalVideoFooterImage(externalUser, input, options) {
1024
+ const normalizedInput = normalizeUpdateVideoFooterImageInput(input, 'updateExternalVideoFooterImage');
1025
+ const body = {
1026
+ external_user: normalizeExternalUserIdentity(externalUser),
1027
+ input: normalizedInput,
1028
+ webhookUrl: options?.webhookUrl,
1029
+ };
1030
+ return this.post('external_users/update_footer_image', body, options);
1031
+ }
926
1032
  /**
927
1033
  * Add or replace the outro image for an existing video session by cloning it into a new session and
928
1034
  * re-running frame/video generation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samsar-js",
3
- "version": "0.48.23",
3
+ "version": "0.48.24",
4
4
  "description": "TypeScript client for the Samsar Processor API routes.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",