samsar-js 0.48.2 → 0.48.3

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
@@ -112,6 +112,17 @@ const embedding = await samsar.createEmbedding({
112
112
  // field_options controls which fields are embedded, used for structured filters, and returned in raw results.
113
113
  // Use dot-notated paths (e.g. owner.email) or inline wrappers like { value, searchable, filterable, retrievable }.
114
114
 
115
+ // Create embeddings from one URL or a URL list
116
+ const websiteEmbedding = await samsar.createEmbeddingFromUrl({
117
+ name: 'product-docs',
118
+ urls: [
119
+ 'https://example.com/docs/getting-started',
120
+ 'https://example.com/docs/pricing',
121
+ ],
122
+ });
123
+
124
+ // The generic createEmbedding wrapper also accepts `urls` on the same route if you prefer one entrypoint.
125
+
115
126
  // Search against an embedding template
116
127
  const search = await samsar.searchAgainstEmbedding({
117
128
  template_id: embedding.data.template_id,
@@ -224,6 +235,66 @@ const paymentStatus = await samsar.getPaymentStatus({
224
235
  console.log(paymentStatus.data.status);
225
236
  ```
226
237
 
238
+ ## External users
239
+
240
+ Use the external-user surface when many platform users share one central Samsar account and API key.
241
+
242
+ ```ts
243
+ import SamsarClient from 'samsar-js';
244
+
245
+ const platform = new SamsarClient({
246
+ apiKey: process.env.SAMSAR_PLATFORM_API_KEY!,
247
+ });
248
+
249
+ const externalUser = {
250
+ provider: 'whop',
251
+ external_user_id: 'usr_123',
252
+ external_app_id: 'app_abc',
253
+ username: 'roy24x7',
254
+ };
255
+
256
+ // Bootstrap or refresh the external user
257
+ const externalSession = await platform.createExternalUserSession(externalUser);
258
+ console.log(externalSession.data.remainingCredits, externalSession.data.external_api_key);
259
+
260
+ // Create a render attributed to that external user
261
+ const externalRender = await platform.createExternalVideoFromText(externalUser, {
262
+ prompt: 'A sleek teaser for a futuristic running shoe',
263
+ image_model: 'GPTIMAGE1',
264
+ video_model: 'RUNWAYML',
265
+ duration: 10,
266
+ enable_subtitles: true,
267
+ });
268
+
269
+ // Fetch their external library
270
+ const library = await platform.listExternalUserRequests(externalUser, { limit: 12 });
271
+ console.log(library.data.requests.length);
272
+
273
+ // Publish or archive a render
274
+ await platform.publishExternalUserRequest(externalRender.data.request_id, {
275
+ title: 'Running shoe teaser',
276
+ }, externalUser);
277
+ await platform.archiveExternalUserRequest(externalRender.data.request_id, externalUser);
278
+
279
+ // Create a short-lived login URL for the external Studio dashboard
280
+ const login = await platform.createExternalUserLoginToken(externalUser, {
281
+ redirect: '/external/studio',
282
+ });
283
+ console.log(login.data.loginUrl);
284
+
285
+ // Exchange the login token for a client auth token
286
+ const verified = await platform.verifyClientSession({
287
+ loginToken: login.data.loginToken,
288
+ });
289
+
290
+ // The returned authToken can be used as the SDK apiKey for external-user routes
291
+ const externalClient = new SamsarClient({
292
+ apiKey: verified.data.authToken!,
293
+ });
294
+ const externalLibrary = await externalClient.listExternalUserRequests();
295
+ console.log(externalLibrary.data.requests.map((request) => request.request_id));
296
+ ```
297
+
227
298
  Video model support notes:
228
299
  - `createVideoFromText` image model keys include: `GPTIMAGE1`, `IMAGEN4`, `SEEDREAM`, `HUNYUAN`, `NANOBANANA2`.
229
300
  - `createVideoFromText` supports all express video models: `RUNWAYML`, `KLINGIMGTOVID3PRO`, `HAILUO`, `HAILUOPRO`, `SEEDANCEI2V`, `VEO3.1I2V`, `VEO3.1I2VFAST`, `SORA2`, `SORA2PRO`.
@@ -234,6 +305,7 @@ Each method returns `{ data, status, headers, creditsCharged, creditsRemaining,
234
305
  ## Billing notes
235
306
 
236
307
  - Embedding endpoints (`createEmbedding`, `updateEmbedding`, `searchAgainstEmbedding`, `similarToEmbedding`) are billed by input tokens at $1 per million tokens. `deleteEmbeddings` does not consume tokens.
308
+ - URL-based embedding creation (`createEmbedding` with `urls`, or `createEmbeddingFromUrl`) adds Firecrawl crawl cost to the embedding token cost, then applies Samsar's 100 credits per USD mapping with a `2.5x` multiplier.
237
309
  - Token counts follow OpenAI tokenization for `text-embedding-3-large`. Credit deductions follow the existing 100 credits per USD rule.
238
310
  - Receipt template creation (`createReceiptTemplate`) and template JSON lookup (`getReceiptTemplateJson`) are free; receipt template query (`queryReceiptTemplate`) costs 50 credits per request.
239
311
 
@@ -244,6 +316,7 @@ Each method returns `{ data, status, headers, creditsCharged, creditsRemaining,
244
316
  - `timeoutMs` (optional): defaults to 30s.
245
317
  - `fetch` (optional): supply a fetch implementation when not available globally (e.g., Node <18).
246
318
  - `defaultHeaders` (optional): merged into every request.
319
+ - `externalUserApiKey` (optional): default `x-external-user-api-key` header for external-user scoped requests.
247
320
 
248
321
  ## Build
249
322
 
package/dist/index.d.ts CHANGED
@@ -7,10 +7,12 @@ export interface SamsarClientOptions {
7
7
  timeoutMs?: number;
8
8
  fetch?: FetchLike;
9
9
  defaultHeaders?: Record<string, string>;
10
+ externalUserApiKey?: string;
10
11
  }
11
12
  export interface SamsarRequestOptions {
12
13
  idempotencyKey?: string;
13
14
  headers?: Record<string, string>;
15
+ externalUserApiKey?: string;
14
16
  signal?: AbortSignal;
15
17
  query?: QueryParams;
16
18
  }
@@ -306,6 +308,7 @@ export interface EmbeddingFieldOptions {
306
308
  filterable?: boolean;
307
309
  retrievable?: boolean;
308
310
  }
311
+ export type EmbeddingUrlInput = string | string[];
309
312
  export type EmbeddingFieldOptionsInput = Record<string, EmbeddingFieldOptions> | Array<EmbeddingFieldOptions & {
310
313
  key?: string;
311
314
  field?: string;
@@ -314,8 +317,25 @@ export type EmbeddingFieldOptionsInput = Record<string, EmbeddingFieldOptions> |
314
317
  column_name?: string;
315
318
  columnName?: string;
316
319
  }>;
320
+ export interface EmbeddingUrlIssue {
321
+ url?: string | null;
322
+ message?: string;
323
+ code?: string | null;
324
+ }
317
325
  export interface CreateEmbeddingRequest {
318
- records: Array<Record<string, unknown>>;
326
+ records?: Array<Record<string, unknown>>;
327
+ urls?: EmbeddingUrlInput;
328
+ url?: string;
329
+ name?: string;
330
+ embedding_name?: string;
331
+ template_name?: string;
332
+ field_options?: EmbeddingFieldOptionsInput;
333
+ fieldOptions?: EmbeddingFieldOptionsInput;
334
+ [key: string]: unknown;
335
+ }
336
+ export interface CreateEmbeddingFromUrlRequest {
337
+ urls?: EmbeddingUrlInput;
338
+ url?: string;
319
339
  name?: string;
320
340
  embedding_name?: string;
321
341
  template_name?: string;
@@ -328,6 +348,11 @@ export interface CreateEmbeddingResponse {
328
348
  template_hash?: string;
329
349
  hash_link?: string;
330
350
  record_count?: number;
351
+ input_url_count?: number;
352
+ processed_url_count?: number;
353
+ firecrawl_credits_used?: number;
354
+ skipped_urls?: EmbeddingUrlIssue[];
355
+ crawl_errors?: EmbeddingUrlIssue[];
331
356
  structured_fields?: EmbeddingStructuredField[];
332
357
  unstructured_fields?: string[];
333
358
  [key: string]: unknown;
@@ -754,6 +779,157 @@ export interface GlobalStatusResponse {
754
779
  message?: string | null;
755
780
  [key: string]: unknown;
756
781
  }
782
+ export interface ExternalUserIdentity {
783
+ provider: string;
784
+ external_user_id?: string;
785
+ externalUserId?: string;
786
+ external_app_id?: string;
787
+ externalAppId?: string;
788
+ external_company_id?: string;
789
+ externalCompanyId?: string;
790
+ external_account_id?: string;
791
+ externalAccountId?: string;
792
+ email?: string;
793
+ username?: string;
794
+ display_name?: string;
795
+ displayName?: string;
796
+ avatar_url?: string;
797
+ avatarUrl?: string;
798
+ metadata?: Record<string, unknown>;
799
+ [key: string]: unknown;
800
+ }
801
+ export interface ExternalUserSummary {
802
+ id?: string | null;
803
+ provider?: string;
804
+ external_user_id?: string;
805
+ external_app_id?: string | null;
806
+ external_company_id?: string | null;
807
+ email?: string | null;
808
+ username?: string | null;
809
+ display_name?: string | null;
810
+ avatar_url?: string | null;
811
+ generation_credits?: number;
812
+ has_external_api_key?: boolean;
813
+ external_api_key_created_at?: string | null;
814
+ external_api_key_last_used_at?: string | null;
815
+ total_requests?: number;
816
+ total_credits_used?: number;
817
+ total_credits_refunded?: number;
818
+ total_credits_purchased?: number;
819
+ last_request_at?: string | null;
820
+ last_purchase_at?: string | null;
821
+ last_activity_at?: string | null;
822
+ created_at?: string | null;
823
+ updated_at?: string | null;
824
+ [key: string]: unknown;
825
+ }
826
+ export interface ExternalRequestResponse {
827
+ request_id: string;
828
+ session_id?: string;
829
+ external_request_id?: string;
830
+ external_session_id?: string;
831
+ upstream_request_id?: string | null;
832
+ upstream_session_id?: string | null;
833
+ status_endpoint?: string;
834
+ external_user?: ExternalUserSummary | null;
835
+ creditsCharged?: number;
836
+ creditsRefunded?: number;
837
+ remainingCredits?: number | null;
838
+ [key: string]: unknown;
839
+ }
840
+ export interface ExternalCreditsBalanceResponse extends CreditsBalanceResponse {
841
+ externalUser?: ExternalUserSummary | null;
842
+ external_user?: ExternalUserSummary | null;
843
+ }
844
+ export interface ExternalUserSessionResponse extends ExternalCreditsBalanceResponse {
845
+ external_api_key?: string | null;
846
+ external_user?: ExternalUserSummary | null;
847
+ externalUser?: ExternalUserSummary | null;
848
+ }
849
+ export interface ExternalCreditsGrantResponse {
850
+ creditsGranted: number;
851
+ remainingCredits: number;
852
+ internalRemainingCredits?: number | null;
853
+ externalUser?: ExternalUserSummary | null;
854
+ external_user?: ExternalUserSummary | null;
855
+ [key: string]: unknown;
856
+ }
857
+ export interface ExternalCreditsRechargeResponse extends CreditsRechargeResponse {
858
+ external_payment_id?: string;
859
+ external_user?: ExternalUserSummary | null;
860
+ externalUser?: ExternalUserSummary | null;
861
+ }
862
+ export interface ExternalPaymentStatusRequest extends PaymentStatusRequest {
863
+ external_payment_id?: string;
864
+ externalPaymentId?: string;
865
+ }
866
+ export interface ExternalPaymentStatusResponse extends PaymentStatusResponse {
867
+ external_payment_id?: string;
868
+ external_user?: ExternalUserSummary | null;
869
+ externalUser?: ExternalUserSummary | null;
870
+ remainingCredits?: number | null;
871
+ lastTopUp?: CreditTopUpSummary | null;
872
+ }
873
+ export interface ExternalStatusResponse extends GlobalStatusResponse {
874
+ external_request_id?: string;
875
+ external_session_id?: string;
876
+ upstream_request_id?: string | null;
877
+ upstream_session_id?: string | null;
878
+ external_user?: ExternalUserSummary | null;
879
+ creditsRefunded?: number;
880
+ remainingCredits?: number | null;
881
+ }
882
+ export interface ExternalRequestSummary {
883
+ request_id?: string;
884
+ external_request_id?: string;
885
+ upstream_request_id?: string | null;
886
+ upstream_session_id?: string | null;
887
+ route_key?: string | null;
888
+ status?: string | null;
889
+ prompt?: string | null;
890
+ video_url?: string | null;
891
+ image_count?: number;
892
+ credits_charged?: number;
893
+ credits_refunded?: number;
894
+ remaining_credits?: number | null;
895
+ target_language?: string | null;
896
+ source_request_ids?: string[];
897
+ source_session_ids?: string[];
898
+ created_at?: string | null;
899
+ updated_at?: string | null;
900
+ is_published?: boolean;
901
+ published_title?: string | null;
902
+ published_description?: string | null;
903
+ published_tags?: string[];
904
+ published_at?: string | null;
905
+ published_video_url?: string | null;
906
+ published_publication_id?: string | null;
907
+ [key: string]: unknown;
908
+ }
909
+ export interface ExternalRequestsListResponse {
910
+ requests: ExternalRequestSummary[];
911
+ external_user?: ExternalUserSummary | null;
912
+ externalUser?: ExternalUserSummary | null;
913
+ [key: string]: unknown;
914
+ }
915
+ export interface ExternalArchiveResponse {
916
+ request?: ExternalRequestSummary | null;
917
+ external_user?: ExternalUserSummary | null;
918
+ externalUser?: ExternalUserSummary | null;
919
+ [key: string]: unknown;
920
+ }
921
+ export interface ExternalPublishInput {
922
+ title?: string;
923
+ description?: string;
924
+ tags?: string[] | string;
925
+ aspectRatio?: string;
926
+ sessionLanguage?: string;
927
+ languageString?: string;
928
+ [key: string]: unknown;
929
+ }
930
+ export interface ExternalPublishResponse extends ExternalArchiveResponse {
931
+ publication?: Record<string, unknown> | null;
932
+ }
757
933
  export interface CreditTopUpSummary {
758
934
  id?: string;
759
935
  amountPaidCents?: number;
@@ -783,6 +959,39 @@ export interface CreateLoginTokenResponse {
783
959
  expiresAt?: string;
784
960
  [key: string]: unknown;
785
961
  }
962
+ export interface ExternalCreateLoginTokenResponse extends CreateLoginTokenResponse {
963
+ loginUrl?: string;
964
+ external_user?: ExternalUserSummary | null;
965
+ externalUser?: ExternalUserSummary | null;
966
+ }
967
+ export interface VerifyClientSessionInput {
968
+ loginToken?: string;
969
+ authToken?: string;
970
+ }
971
+ export interface VerifiedClientSessionResponse {
972
+ authToken?: string;
973
+ isExternalUser?: boolean;
974
+ _id?: string | null;
975
+ email?: string | null;
976
+ username?: string | null;
977
+ displayName?: string | null;
978
+ avatarUrl?: string | null;
979
+ provider?: string | null;
980
+ externalUserId?: string | null;
981
+ externalAppId?: string | null;
982
+ externalCompanyId?: string | null;
983
+ generationCredits?: number;
984
+ totalRequests?: number;
985
+ totalCreditsUsed?: number;
986
+ totalCreditsRefunded?: number;
987
+ totalCreditsPurchased?: number;
988
+ lastRequestAt?: string | null;
989
+ lastPurchaseAt?: string | null;
990
+ lastActivityAt?: string | null;
991
+ createdAt?: string | null;
992
+ updatedAt?: string | null;
993
+ [key: string]: unknown;
994
+ }
786
995
  export interface CreditsRechargeResponse {
787
996
  url: string;
788
997
  checkoutSessionId?: string | null;
@@ -882,6 +1091,7 @@ export declare class SamsarClient {
882
1091
  private readonly timeoutMs;
883
1092
  private readonly fetchFn;
884
1093
  private readonly defaultHeaders;
1094
+ private readonly externalUserApiKey?;
885
1095
  constructor(options: SamsarClientOptions);
886
1096
  /**
887
1097
  * Create a new video generation job from text.
@@ -895,6 +1105,34 @@ export declare class SamsarClient {
895
1105
  createVideoFromImageList(input: CreateVideoFromImageListInput, options?: {
896
1106
  webhookUrl?: string;
897
1107
  } & SamsarRequestOptions): Promise<SamsarResult<CreateVideoFromImageListResponse>>;
1108
+ /**
1109
+ * Create a text-to-video request attributed to an external user while billing against the shared API key.
1110
+ */
1111
+ createExternalVideoFromText(externalUser: ExternalUserIdentity, input: CreateVideoFromTextInput, options?: {
1112
+ webhookUrl?: string;
1113
+ } & SamsarRequestOptions): Promise<SamsarResult<ExternalRequestResponse>>;
1114
+ /**
1115
+ * Upload image data URLs for an external user before calling createExternalVideoFromImageList.
1116
+ */
1117
+ uploadExternalImageData(externalUser: ExternalUserIdentity, imageData: string[], options?: SamsarRequestOptions): Promise<SamsarResult<{
1118
+ image_urls: string[];
1119
+ }>>;
1120
+ /**
1121
+ * Create an image-list-to-video request attributed to an external user while billing against the shared API key.
1122
+ */
1123
+ createExternalVideoFromImageList(externalUser: ExternalUserIdentity, input: CreateVideoFromImageListInput, options?: {
1124
+ webhookUrl?: string;
1125
+ } & SamsarRequestOptions): Promise<SamsarResult<ExternalRequestResponse>>;
1126
+ /**
1127
+ * Create or refresh an external-user session and receive that user’s dedicated external API key.
1128
+ */
1129
+ createExternalUserSession(externalUser: ExternalUserIdentity, options?: SamsarRequestOptions): Promise<SamsarResult<ExternalUserSessionResponse>>;
1130
+ /**
1131
+ * Create a short-lived external-user login token plus a ready-to-open client login URL.
1132
+ */
1133
+ createExternalUserLoginToken(externalUser?: ExternalUserIdentity | null, options?: ({
1134
+ redirect?: string;
1135
+ } & SamsarRequestOptions)): Promise<SamsarResult<ExternalCreateLoginTokenResponse>>;
898
1136
  /**
899
1137
  * Translate an existing video session into a new language.
900
1138
  * Creates a new session_id and queues generation steps for lip sync + transcription + video render.
@@ -957,9 +1195,13 @@ export declare class SamsarClient {
957
1195
  */
958
1196
  enhanceMessage(payload: EnhanceMessageRequest, options?: SamsarRequestOptions): Promise<SamsarResult<EnhanceMessageResponse>>;
959
1197
  /**
960
- * Create a new embedding template and store embeddings for a JSON array.
1198
+ * Create a new embedding template from either a JSON array (`records`) or a URL input (`urls`).
961
1199
  */
962
1200
  createEmbedding(payload: CreateEmbeddingRequest, options?: SamsarRequestOptions): Promise<SamsarResult<CreateEmbeddingResponse>>;
1201
+ /**
1202
+ * Create a new embedding template from one URL or a list of URLs.
1203
+ */
1204
+ createEmbeddingFromUrl(payload: CreateEmbeddingFromUrlRequest, options?: SamsarRequestOptions): Promise<SamsarResult<CreateEmbeddingResponse>>;
963
1205
  /**
964
1206
  * Update an existing embedding template with additional records.
965
1207
  */
@@ -1037,6 +1279,28 @@ export declare class SamsarClient {
1037
1279
  * Fetch the remaining credits and last credit top-up for the API key.
1038
1280
  */
1039
1281
  getCreditsBalance(options?: SamsarRequestOptions): Promise<SamsarResult<CreditsBalanceResponse>>;
1282
+ /**
1283
+ * Fetch the shared credit balance plus attribution summary for a specific external user.
1284
+ */
1285
+ getExternalCreditsBalance(externalUser: ExternalUserIdentity, options?: SamsarRequestOptions): Promise<SamsarResult<ExternalCreditsBalanceResponse>>;
1286
+ /**
1287
+ * Manually grant credits to a specific external user while also crediting the shared platform account.
1288
+ */
1289
+ grantExternalUserCredits(externalUser: ExternalUserIdentity, credits: number, options?: SamsarRequestOptions): Promise<SamsarResult<ExternalCreditsGrantResponse>>;
1290
+ /**
1291
+ * Fetch recent external-user-attributed requests for library or dashboard views.
1292
+ */
1293
+ listExternalUserRequests(externalUser?: ExternalUserIdentity | null, options?: ({
1294
+ limit?: number;
1295
+ } & SamsarRequestOptions)): Promise<SamsarResult<ExternalRequestsListResponse>>;
1296
+ /**
1297
+ * Archive an external-user request so it no longer appears in the external library/feed.
1298
+ */
1299
+ archiveExternalUserRequest(requestId: string, externalUser?: ExternalUserIdentity | null, options?: SamsarRequestOptions): Promise<SamsarResult<ExternalArchiveResponse>>;
1300
+ /**
1301
+ * Publish a completed external-user request to the public library/feed.
1302
+ */
1303
+ publishExternalUserRequest(requestId: string, payload?: ExternalPublishInput, externalUser?: ExternalUserIdentity | null, options?: SamsarRequestOptions): Promise<SamsarResult<ExternalPublishResponse>>;
1040
1304
  /**
1041
1305
  * Create a short-lived login token that can be exchanged for an auth token in the client app.
1042
1306
  */
@@ -1046,6 +1310,10 @@ export declare class SamsarClient {
1046
1310
  * Business rule: 1 USD = 100 credits.
1047
1311
  */
1048
1312
  createCreditsRecharge(credits: number, options?: SamsarRequestOptions): Promise<SamsarResult<CreditsRechargeResponse>>;
1313
+ /**
1314
+ * Create a shared-balance Stripe recharge attributed to an external user.
1315
+ */
1316
+ createExternalCreditsRecharge(externalUser: ExternalUserIdentity, credits: number, options?: SamsarRequestOptions): Promise<SamsarResult<ExternalCreditsRechargeResponse>>;
1049
1317
  /**
1050
1318
  * Enable or update auto-recharge settings for the API key.
1051
1319
  * Returns a Stripe setup URL when a payment method is required.
@@ -1059,6 +1327,14 @@ export declare class SamsarClient {
1059
1327
  * Poll for checkout/payment/setup status using IDs returned by credit recharge or auto-recharge setup.
1060
1328
  */
1061
1329
  getPaymentStatus(payload: PaymentStatusRequest, options?: SamsarRequestOptions): Promise<SamsarResult<PaymentStatusResponse>>;
1330
+ /**
1331
+ * Poll shared-balance payment status for an external user credit purchase.
1332
+ */
1333
+ getExternalPaymentStatus(payload: ExternalPaymentStatusRequest, options?: SamsarRequestOptions): Promise<SamsarResult<ExternalPaymentStatusResponse>>;
1334
+ /**
1335
+ * Exchange a login token or verify an auth token against /users/verify_token.
1336
+ */
1337
+ verifyClientSession(payload: VerifyClientSessionInput, options?: SamsarRequestOptions): Promise<SamsarResult<VerifiedClientSessionResponse>>;
1062
1338
  /**
1063
1339
  * Retrieve the status of an asynchronous request by request_id.
1064
1340
  * Defaults to GET /status?request_id={requestId}, but the path can be overridden.
@@ -1068,6 +1344,12 @@ export declare class SamsarClient {
1068
1344
  path?: string;
1069
1345
  queryParams?: QueryParams;
1070
1346
  }): Promise<SamsarResult<GlobalStatusResponse>>;
1347
+ /**
1348
+ * Retrieve the status of an external-user-attributed asynchronous request by external request_id.
1349
+ */
1350
+ getExternalStatus(requestId: string, options?: SamsarRequestOptions & {
1351
+ queryParams?: QueryParams;
1352
+ }): Promise<SamsarResult<ExternalStatusResponse>>;
1071
1353
  /**
1072
1354
  * Retrieve the status of an image request (maps to GET /image/status).
1073
1355
  */
@@ -1079,5 +1361,6 @@ export declare class SamsarClient {
1079
1361
  private request;
1080
1362
  private buildHeaders;
1081
1363
  private buildUrl;
1364
+ private buildRootUrl;
1082
1365
  }
1083
1366
  export default SamsarClient;
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ export class SamsarClient {
25
25
  this.timeoutMs = options.timeoutMs ?? 30000;
26
26
  this.fetchFn = options.fetch ?? globalThis.fetch;
27
27
  this.defaultHeaders = options.defaultHeaders ?? {};
28
+ this.externalUserApiKey = options.externalUserApiKey?.trim() || undefined;
28
29
  if (typeof this.fetchFn !== 'function') {
29
30
  throw new Error('A fetch implementation is required. Provide one via the "fetch" option when running outside environments with global fetch.');
30
31
  }
@@ -68,6 +69,65 @@ export class SamsarClient {
68
69
  }
69
70
  return response;
70
71
  }
72
+ /**
73
+ * Create a text-to-video request attributed to an external user while billing against the shared API key.
74
+ */
75
+ async createExternalVideoFromText(externalUser, input, options) {
76
+ const body = {
77
+ external_user: normalizeExternalUserIdentity(externalUser),
78
+ input,
79
+ webhookUrl: options?.webhookUrl,
80
+ };
81
+ return this.post('external_users/text_to_video', body, options);
82
+ }
83
+ /**
84
+ * Upload image data URLs for an external user before calling createExternalVideoFromImageList.
85
+ */
86
+ async uploadExternalImageData(externalUser, imageData, options) {
87
+ if (!Array.isArray(imageData) || imageData.length === 0) {
88
+ throw new Error('imageData must be a non-empty array of data URLs');
89
+ }
90
+ const body = {
91
+ external_user: normalizeExternalUserIdentity(externalUser),
92
+ input: {
93
+ image_data: imageData,
94
+ },
95
+ };
96
+ return this.post('external_users/upload_image_data', body, options);
97
+ }
98
+ /**
99
+ * Create an image-list-to-video request attributed to an external user while billing against the shared API key.
100
+ */
101
+ async createExternalVideoFromImageList(externalUser, input, options) {
102
+ const body = {
103
+ external_user: normalizeExternalUserIdentity(externalUser),
104
+ input,
105
+ webhookUrl: options?.webhookUrl,
106
+ };
107
+ return this.post('external_users/image_list_to_video', body, options);
108
+ }
109
+ /**
110
+ * Create or refresh an external-user session and receive that user’s dedicated external API key.
111
+ */
112
+ async createExternalUserSession(externalUser, options) {
113
+ const body = {
114
+ external_user: normalizeExternalUserIdentity(externalUser),
115
+ };
116
+ return this.post('external_users/session', body, options);
117
+ }
118
+ /**
119
+ * Create a short-lived external-user login token plus a ready-to-open client login URL.
120
+ */
121
+ async createExternalUserLoginToken(externalUser, options) {
122
+ const body = {};
123
+ if (externalUser) {
124
+ body.external_user = normalizeExternalUserIdentity(externalUser);
125
+ }
126
+ if (options?.redirect) {
127
+ body.redirect = options.redirect;
128
+ }
129
+ return this.post('external_users/create_login_token', body, options);
130
+ }
71
131
  /**
72
132
  * Translate an existing video session into a new language.
73
133
  * Creates a new session_id and queues generation steps for lip sync + transcription + video render.
@@ -491,11 +551,17 @@ export class SamsarClient {
491
551
  return this.post('chat/enhance', payload, options);
492
552
  }
493
553
  /**
494
- * Create a new embedding template and store embeddings for a JSON array.
554
+ * Create a new embedding template from either a JSON array (`records`) or a URL input (`urls`).
495
555
  */
496
556
  async createEmbedding(payload, options) {
497
557
  return this.post('chat/create_embedding', payload, options);
498
558
  }
559
+ /**
560
+ * Create a new embedding template from one URL or a list of URLs.
561
+ */
562
+ async createEmbeddingFromUrl(payload, options) {
563
+ return this.post('chat/create_embedding_from_url', payload, options);
564
+ }
499
565
  /**
500
566
  * Update an existing embedding template with additional records.
501
567
  */
@@ -684,6 +750,82 @@ export class SamsarClient {
684
750
  async getCreditsBalance(options) {
685
751
  return this.get('credits', options);
686
752
  }
753
+ /**
754
+ * Fetch the shared credit balance plus attribution summary for a specific external user.
755
+ */
756
+ async getExternalCreditsBalance(externalUser, options) {
757
+ return this.get('external_users/credits', {
758
+ ...(options ?? {}),
759
+ query: {
760
+ ...buildExternalUserQuery(externalUser),
761
+ ...(options?.query ?? {}),
762
+ },
763
+ });
764
+ }
765
+ /**
766
+ * Manually grant credits to a specific external user while also crediting the shared platform account.
767
+ */
768
+ async grantExternalUserCredits(externalUser, credits, options) {
769
+ if (!Number.isFinite(credits) || credits <= 0) {
770
+ throw new Error('credits must be a positive number');
771
+ }
772
+ const payload = {
773
+ external_user: normalizeExternalUserIdentity(externalUser),
774
+ input: {
775
+ credits: Math.round(credits),
776
+ },
777
+ };
778
+ return this.post('external_users/credits/grant', payload, options);
779
+ }
780
+ /**
781
+ * Fetch recent external-user-attributed requests for library or dashboard views.
782
+ */
783
+ async listExternalUserRequests(externalUser, options) {
784
+ const query = {
785
+ ...(options?.query ?? {}),
786
+ };
787
+ if (externalUser) {
788
+ Object.assign(query, buildExternalUserQuery(externalUser));
789
+ }
790
+ if (options?.limit !== undefined) {
791
+ query.limit = options.limit;
792
+ }
793
+ return this.get('external_users/requests', {
794
+ ...(options ?? {}),
795
+ query,
796
+ });
797
+ }
798
+ /**
799
+ * Archive an external-user request so it no longer appears in the external library/feed.
800
+ */
801
+ async archiveExternalUserRequest(requestId, externalUser, options) {
802
+ if (!requestId || typeof requestId !== 'string') {
803
+ throw new Error('requestId is required');
804
+ }
805
+ const payload = {
806
+ request_id: requestId,
807
+ };
808
+ if (externalUser) {
809
+ payload.external_user = normalizeExternalUserIdentity(externalUser);
810
+ }
811
+ return this.post('external_users/archive', payload, options);
812
+ }
813
+ /**
814
+ * Publish a completed external-user request to the public library/feed.
815
+ */
816
+ async publishExternalUserRequest(requestId, payload = {}, externalUser, options) {
817
+ if (!requestId || typeof requestId !== 'string') {
818
+ throw new Error('requestId is required');
819
+ }
820
+ const body = {
821
+ request_id: requestId,
822
+ ...payload,
823
+ };
824
+ if (externalUser) {
825
+ body.external_user = normalizeExternalUserIdentity(externalUser);
826
+ }
827
+ return this.post('external_users/publish', body, options);
828
+ }
687
829
  /**
688
830
  * Create a short-lived login token that can be exchanged for an auth token in the client app.
689
831
  */
@@ -703,6 +845,21 @@ export class SamsarClient {
703
845
  };
704
846
  return this.post('credits/recharge', payload, options);
705
847
  }
848
+ /**
849
+ * Create a shared-balance Stripe recharge attributed to an external user.
850
+ */
851
+ async createExternalCreditsRecharge(externalUser, credits, options) {
852
+ if (!Number.isFinite(credits) || credits <= 0) {
853
+ throw new Error('credits must be a positive number');
854
+ }
855
+ const payload = {
856
+ external_user: normalizeExternalUserIdentity(externalUser),
857
+ input: {
858
+ credits: Math.round(credits),
859
+ },
860
+ };
861
+ return this.post('external_users/credits/recharge', payload, options);
862
+ }
706
863
  /**
707
864
  * Enable or update auto-recharge settings for the API key.
708
865
  * Returns a Stripe setup URL when a payment method is required.
@@ -737,6 +894,54 @@ export class SamsarClient {
737
894
  query,
738
895
  });
739
896
  }
897
+ /**
898
+ * Poll shared-balance payment status for an external user credit purchase.
899
+ */
900
+ async getExternalPaymentStatus(payload, options) {
901
+ const query = {
902
+ ...(options?.query ?? {}),
903
+ };
904
+ if (payload?.external_payment_id) {
905
+ query.external_payment_id = payload.external_payment_id;
906
+ }
907
+ if (payload?.externalPaymentId) {
908
+ query.external_payment_id = payload.externalPaymentId;
909
+ }
910
+ if (payload?.checkoutSessionId) {
911
+ query.checkoutSessionId = payload.checkoutSessionId;
912
+ }
913
+ if (payload?.paymentIntentId) {
914
+ query.paymentIntentId = payload.paymentIntentId;
915
+ }
916
+ if (payload?.setupIntentId) {
917
+ query.setupIntentId = payload.setupIntentId;
918
+ }
919
+ return this.get('external_users/payment_status', {
920
+ ...(options ?? {}),
921
+ query,
922
+ });
923
+ }
924
+ /**
925
+ * Exchange a login token or verify an auth token against /users/verify_token.
926
+ */
927
+ async verifyClientSession(payload, options) {
928
+ const query = {
929
+ ...(options?.query ?? {}),
930
+ };
931
+ if (payload?.loginToken) {
932
+ query.loginToken = payload.loginToken;
933
+ }
934
+ if (payload?.authToken) {
935
+ query.authToken = payload.authToken;
936
+ }
937
+ if (!query.loginToken && !query.authToken) {
938
+ throw new Error('loginToken or authToken is required');
939
+ }
940
+ return this.get(this.buildRootUrl('users/verify_token'), {
941
+ ...(options ?? {}),
942
+ query,
943
+ });
944
+ }
740
945
  /**
741
946
  * Retrieve the status of an asynchronous request by request_id.
742
947
  * Defaults to GET /status?request_id={requestId}, but the path can be overridden.
@@ -782,6 +987,16 @@ export class SamsarClient {
782
987
  };
783
988
  return { ...response, data: normalizedData };
784
989
  }
990
+ /**
991
+ * Retrieve the status of an external-user-attributed asynchronous request by external request_id.
992
+ */
993
+ async getExternalStatus(requestId, options) {
994
+ const response = await this.getStatus(requestId, {
995
+ ...options,
996
+ path: 'external_users/status',
997
+ });
998
+ return response;
999
+ }
785
1000
  /**
786
1001
  * Retrieve the status of an image request (maps to GET /image/status).
787
1002
  */
@@ -879,6 +1094,7 @@ export class SamsarClient {
879
1094
  const headers = {
880
1095
  Authorization: `Bearer ${this.apiKey}`,
881
1096
  'Content-Type': options.body ? 'application/json' : undefined,
1097
+ 'x-external-user-api-key': options.externalUserApiKey ?? this.externalUserApiKey,
882
1098
  ...this.defaultHeaders,
883
1099
  ...(options.headers ?? {}),
884
1100
  };
@@ -900,6 +1116,12 @@ export class SamsarClient {
900
1116
  }
901
1117
  return url.toString();
902
1118
  }
1119
+ buildRootUrl(path) {
1120
+ const cleanedPath = path.replace(/^\/+/, '');
1121
+ const baseUrl = trimTrailingSlash(this.baseUrl);
1122
+ const rootUrl = baseUrl.endsWith('/v1') ? baseUrl.slice(0, -3) : baseUrl;
1123
+ return `${rootUrl}/${cleanedPath}`;
1124
+ }
903
1125
  }
904
1126
  function trimTrailingSlash(url) {
905
1127
  return url.replace(/\/+$/, '');
@@ -932,4 +1154,47 @@ function removeEmptyHeaders(headers) {
932
1154
  }
933
1155
  return normalized;
934
1156
  }
1157
+ function normalizeExternalUserIdentity(externalUser) {
1158
+ const externalUserId = externalUser.external_user_id ??
1159
+ externalUser.externalUserId;
1160
+ if (!externalUser?.provider || !externalUserId) {
1161
+ throw new Error('externalUser.provider and externalUser.external_user_id are required');
1162
+ }
1163
+ return {
1164
+ provider: externalUser.provider,
1165
+ external_user_id: externalUserId,
1166
+ ...(externalUser.external_app_id || externalUser.externalAppId
1167
+ ? { external_app_id: externalUser.external_app_id ?? externalUser.externalAppId }
1168
+ : {}),
1169
+ ...(externalUser.external_company_id || externalUser.externalCompanyId
1170
+ ? { external_company_id: externalUser.external_company_id ?? externalUser.externalCompanyId }
1171
+ : {}),
1172
+ ...(externalUser.external_account_id || externalUser.externalAccountId
1173
+ ? { external_account_id: externalUser.external_account_id ?? externalUser.externalAccountId }
1174
+ : {}),
1175
+ ...(externalUser.email ? { email: externalUser.email } : {}),
1176
+ ...(externalUser.username ? { username: externalUser.username } : {}),
1177
+ ...(externalUser.display_name || externalUser.displayName
1178
+ ? { display_name: externalUser.display_name ?? externalUser.displayName }
1179
+ : {}),
1180
+ ...(externalUser.avatar_url || externalUser.avatarUrl
1181
+ ? { avatar_url: externalUser.avatar_url ?? externalUser.avatarUrl }
1182
+ : {}),
1183
+ ...(externalUser.metadata ? { metadata: externalUser.metadata } : {}),
1184
+ };
1185
+ }
1186
+ function buildExternalUserQuery(externalUser) {
1187
+ const normalized = normalizeExternalUserIdentity(externalUser);
1188
+ return {
1189
+ provider: normalized.provider,
1190
+ external_user_id: normalized.external_user_id,
1191
+ external_app_id: normalized.external_app_id ?? undefined,
1192
+ external_company_id: normalized.external_company_id ?? undefined,
1193
+ external_account_id: normalized.external_account_id ?? undefined,
1194
+ email: normalized.email ?? undefined,
1195
+ username: normalized.username ?? undefined,
1196
+ display_name: normalized.display_name ?? undefined,
1197
+ avatar_url: normalized.avatar_url ?? undefined,
1198
+ };
1199
+ }
935
1200
  export default SamsarClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samsar-js",
3
- "version": "0.48.2",
3
+ "version": "0.48.3",
4
4
  "description": "TypeScript client for the Samsar Processor API routes.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",