### System Prompt for Jay's Coding Assistant Source: https://docs.jay-metadata.com/developer_environment_setup A system prompt designed for AI coding assistants to provide expert help specifically for Jay's streaming integration stack. It emphasizes using provided documentation, constraining responses to Playout and Basket APIs, and formatting code examples with specific headers. ```plaintext You are an expert assistant for Jay’s streaming integration stack. Always prefer the company docs provided via llms.txt and sitemaps. Constrain answers to the Playout API (content/structure) and Basket API v2 (cart/checkout). When showing code, use TypeScript fetch examples and include required headers: - X-API-Key, X-API-Version (pinned), and __Secure-jay_tracking (cookie or header) for Playout - X-API-Key, X-API-Version, and Authorization: Bearer for Basket Before write access, verify availability via POST /baskets/products/details. If endpoint shape is uncertain, link to the exact reference page. Keep answers concise, deterministic, and copy‑pasteable. ``` -------------------------------- ### Environment Variables for Jay API Integration Source: https://docs.jay-metadata.com/developer_environment_setup Example local environment file (`.env`) containing necessary API keys and version information for interacting with Jay's Playout and Basket services. These variables are typically loaded and used by client applications or scripts. ```env JAY_API_KEY=xxx JAY_PLAYOUT_ID=xxx JAY_PLAYOUT_VER=2025-09-02 JAY_BASKET_VER=2025-09-15 JAY_TRACKING=local-dev ``` -------------------------------- ### Troubleshooting Assistant for Basket Checkout Failures Source: https://docs.jay-metadata.com/developer_environment_setup A guide to diagnosing and resolving issues encountered during the basket checkout process. It covers common problems such as missing or expired JWTs, locked baskets due to active sessions, product variant and stock discrepancies, and API version mismatches. The guide also provides instructions for generating cURL commands for reproduction and links to relevant documentation. ```bash # Troubleshooting Basket Checkout Failures # 1. Inspect Authorization Header / JWT Validity # Check if 'Authorization: Bearer ' header is present and if the JWT is not expired. # Use browser developer tools (Network tab) or logs to verify. # Example cURL (replace and endpoint): # curl -X POST https://basket.api.jay-metadata.com/checkout/session \ # -H "Authorization: Bearer " \ # -H "X-API-Version: basket" \ # -H "Content-Type: application/json" \ # -d '{"basketId": ""}' # If JWT is expired, obtain a new one (e.g., via createGuestBasket or login flow). # 2. Check for Locked Basket # A basket might be locked if an active checkout session is already in progress. # Verify the basket status or session status via API endpoints if available. # Example cURL (to check basket status, assumes an endpoint exists): # curl -X GET https://basket.api.jay-metadata.com/baskets/ \ # -H "Authorization: Bearer " \ # -H "X-API-Version: basket" # If locked, wait for the session to complete or be cancelled. Provide user feedback. # 3. Verify Product Variants and Stock # Ensure products in the basket exist and have sufficient stock. # Use the /baskets/products/details endpoint. # Example cURL (replace and product IDs): # curl -X POST https://basket.api.jay-metadata.com/baskets//products/details \ # -H "Authorization: Bearer " \ # -H "X-API-Version: basket" \ # -H "Content-Type: application/json" \ # -d '{"productIds": ["", ""]}' # If stock issues arise, inform the user and offer alternatives or removal. # 4. Reconcile X-API-Version Mismatches # Ensure the 'X-API-Version' header matches the expected version for the domain (e.g., 'basket' for basket.api.jay-metadata.com). # Check client-side interceptors and server-side routing. # Example cURL (ensure correct header): # curl -X POST https://basket.api.jay-metadata.com/some/endpoint \ # -H "X-API-Version: basket" \ # ... # 5. Generate Specific cURL Commands # Based on the specific error encountered, construct a cURL command that replicates the failing request. # Include all relevant headers (Authorization, X-API-Version, Content-Type, etc.) and the request body. # 6. Link to Reference Sections # Refer to relevant documentation sections for detailed explanations of API endpoints, error codes, and security practices. # e.g., [API Documentation: Basket Endpoints](link/to/basket/api/docs) # e.g., [Security: Authentication & Authorization](link/to/auth/docs) ``` -------------------------------- ### Request Playout API with X-API-Key Source: https://docs.jay-metadata.com/apis/authentication Demonstrates how to make a GET request to the Playout API by including the 'X-API-Key' in the request header. This is a fundamental authentication step for all Jay API endpoints. ```bash curl -X GET "https://api.jayplatform.com/playout" \ -H "X-API-Key: your_api_key_here" ``` -------------------------------- ### Get all Products for an Episode Source: https://docs.jay-metadata.com/platform/how-to/show-products Retrieves a list of all products available in a specific episode, including their basic information. ```APIDOC ## GET /playouts/{playoutId}/episodes/{episodeId}/products ### Description Retrieves a list of all products available in a specific episode, with their basic information. ### Method GET ### Endpoint /playouts/{playoutId}/episodes/{episodeId}/products ### Parameters #### Path Parameters - **playoutId** (string) - Required - The ID of the playout. - **episodeId** (string) - Required - The ID of the episode. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **products** (array) - A list of product objects. - **productId** (string) - The unique identifier for the product. - **name** (string) - The name of the product. - **brand** (string) - The brand of the product. - **price** (number) - The price of the product. - **imageUrl** (string) - The URL of the product image. #### Response Example ```json { "products": [ { "productId": "prod_123", "name": "T-Shirt", "brand": "ExampleBrand", "price": 29.99, "imageUrl": "https://example.com/image.jpg" } ] } ``` ``` -------------------------------- ### Get Props Source: https://docs.jay-metadata.com/platform/how-to/show-products Retrieves props associated with characters or locations in an episode, which can include purchasable products. ```APIDOC ## GET /playouts/{playoutId}/episodes/{episodeId}/props ### Description Fetches props associated with characters or locations in a specific episode. Props can sometimes contain references to purchasable products. ### Method GET ### Endpoint /playouts/{playoutId}/episodes/{episodeId}/props ### Parameters #### Path Parameters - **playoutId** (string) - Required - The ID of the playout. - **episodeId** (string) - Required - The ID of the episode. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **props** (array) - A list of prop objects. - **propId** (string) - The unique identifier for the prop. - **name** (string) - The name of the prop. - **productId** (string) - The ID of the product associated with this prop (if any). #### Response Example ```json { "props": [ { "propId": "prop_x", "name": "Vintage Lamp", "productId": "prod_789" } ] } ``` ``` -------------------------------- ### Minimal llms.txt Configuration for LLMs Source: https://docs.jay-metadata.com/developer_environment_setup This is a minimal configuration file for large language models (LLMs), specifying high-priority documentation links and machine-readable specifications. It helps AI assistants focus on relevant resources for Jay's platform. ```text # High-priority docs and machine-readable specs for LLMs ALLOW: https://docs.jay-metadata.com/ PRIORITY: https://docs.jay-metadata.com/platform/quickstarts/streaming-integration PRIORITY: https://docs.jay-metadata.com/platform/how-to/fetch-data PRIORITY: https://docs.jay-metadata.com/platform/how-to/use-the-basket PRIORITY: https://docs.jay-metadata.com/platform/how-to/checkout-stripe PRIORITY: https://docs.jay-metadata.com/apis/playout/latest/openapi PRIORITY: https://docs.jay-metadata.com/apis/basket/latest/openapi SITEMAP: https://docs.jay-metadata.com/sitemap.xml ``` -------------------------------- ### Get detailed Product Information Source: https://docs.jay-metadata.com/platform/how-to/show-products Fetches comprehensive details about a specific product, including its name, description, pricing, variants, images, and related products. ```APIDOC ## GET /playouts/{playoutId}/episodes/{episodeId}/products/{productId} ### Description Provides complete product information including product name, description, brand, pricing information, available sizes/variants, images, and related products. ### Method GET ### Endpoint /playouts/{playoutId}/episodes/{episodeId}/products/{productId} ### Parameters #### Path Parameters - **playoutId** (string) - Required - The ID of the playout. - **episodeId** (string) - Required - The ID of the episode. - **productId** (string) - Required - The ID of the product. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **product** (object) - Detailed information about the product. - **productId** (string) - The unique identifier for the product. - **name** (string) - The name of the product. - **description** (string) - The description of the product. - **brand** (string) - The brand of the product. - **price** (number) - The price of the product. - **currency** (string) - The currency of the price. - **variants** (array) - Available variants of the product (e.g., sizes). - **size** (string) - The size of the variant. - **sku** (string) - The SKU for the variant. - **images** (array) - URLs of product images. - **url** (string) - The URL of an image. - **linkedToProducts** (array) - References to related products. - **productId** (string) - The ID of the related product. #### Response Example ```json { "product": { "productId": "prod_456", "name": "Jeans", "description": "Comfortable blue jeans.", "brand": "DenimCo", "price": 59.99, "currency": "USD", "variants": [ { "size": "30x32", "sku": "SKU001" }, { "size": "32x32", "sku": "SKU002" } ], "images": [ { "url": "https://example.com/jeans1.jpg" }, { "url": "https://example.com/jeans2.jpg" } ], "linkedToProducts": [ { "productId": "prod_789" } ] } } ``` ``` -------------------------------- ### Bash Script for Fetching Playout Episodes with API Key Source: https://docs.jay-metadata.com/developer_environment_setup A bash script that uses `curl` to fetch episodes for a given Playout ID. It includes essential headers like X-API-Key, X-API-Version, and __Secure-jay_tracking. The output is piped to `jq` for JSON parsing. ```bash # scripts/api/episodes.sh curl -sS \ -H "X-API-Key: $JAY_API_KEY" \ -H "X-API-Version: ${JAY_PLAYOUT_VER:-2025-09-02}" \ -H "__Secure-jay_tracking: ${JAY_TRACKING:-local-dev}" \ "https://live.playout.api.jay-metadata.com/v1/playouts/$1/episodes" | jq . ``` -------------------------------- ### Default Request Headers for Jay APIs Source: https://docs.jay-metadata.com/developer_environment_setup Defines the default headers required for making requests to Jay's APIs, including Playout and Basket services. It shows placeholders for API keys, versions, tracking information, and authorization tokens. ```http X-API-Key: ${JAY_API_KEY} X-API-Version: ${JAY_PLAYOUT_VER} # Playout __Secure-jay_tracking: ${JAY_TRACKING} Authorization: Bearer # Basket only ``` -------------------------------- ### Get Costumes Source: https://docs.jay-metadata.com/platform/how-to/show-products Retrieves costumes associated with characters or locations in an episode, which include product information. ```APIDOC ## GET /playouts/{playoutId}/episodes/{episodeId}/costumes ### Description Fetches costumes associated with characters or locations in a specific episode. Costumes typically contain references to purchasable products. ### Method GET ### Endpoint /playouts/{playoutId}/episodes/{episodeId}/costumes ### Parameters #### Path Parameters - **playoutId** (string) - Required - The ID of the playout. - **episodeId** (string) - Required - The ID of the episode. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **costumes** (array) - A list of costume objects. - **costumeId** (string) - The unique identifier for the costume. - **name** (string) - The name of the costume. - **productId** (string) - The ID of the product associated with this costume. #### Response Example ```json { "costumes": [ { "costumeId": "costume_a", "name": "Hero Outfit", "productId": "prod_123" } ] } ``` ``` -------------------------------- ### Product Management Source: https://docs.jay-metadata.com/retailer/product-management/api Endpoints for managing products, including creating and updating product information. ```APIDOC ## Create Products ### Description Adds new products to the Jay marketplace with detailed attributes. ### Method POST ### Endpoint /api/products ### Parameters #### Request Body - **name** (string) - Required - The name of the product. - **description** (string) - Optional - A detailed description of the product. - **price** (object) - Required - The pricing information for the product. - **amount** (number) - Required - The price amount. - **currency** (string) - Required - The currency code (e.g., "USD"). ### Request Example ```json { "name": "Example T-Shirt", "description": "A comfortable cotton t-shirt.", "price": { "amount": 19.99, "currency": "USD" } } ``` ### Response #### Success Response (200) - **productId** (string) - The unique identifier for the newly created product. #### Response Example ```json { "productId": "prod_12345abc" } ``` ``` ```APIDOC ## Update Products ### Description Modifies existing product information, such as price, inventory, and descriptions. ### Method PUT ### Endpoint /api/products/{productId} ### Parameters #### Path Parameters - **productId** (string) - Required - The unique identifier of the product to update. #### Request Body - **description** (string) - Optional - An updated description of the product. - **price** (object) - Optional - Updated pricing information. - **amount** (number) - Required - The new price amount. - **currency** (string) - Required - The currency code (e.g., "USD"). ### Request Example ```json { "description": "An updated, more detailed description.", "price": { "amount": 21.50, "currency": "USD" } } ``` ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating the product was updated. #### Response Example ```json { "message": "Product prod_12345abc updated successfully." } ``` ``` -------------------------------- ### Product API Authentication Source: https://docs.jay-metadata.com/retailer/product-management/api Explains how to authenticate requests to the Jay Product API using an API key. ```APIDOC ## Authentication The API uses API key authentication. Include your API key in the header of each request: ```http Authorization: Bearer YOUR_API_KEY ``` ``` -------------------------------- ### Retrieval Prompt for Fetching API Facts Source: https://docs.jay-metadata.com/developer_environment_setup A prompt for an AI assistant to retrieve specific information about the Basket API v2, focusing on checkout session initiation and completion. It requests details on endpoints, headers, request bodies, responses, errors, and documentation links. ```plaintext Using the sources in llms.txt and sitemap.xml, find the latest Basket API v2 reference for starting and finishing a checkout session. Return: 1) Exact endpoints and required headers 2) Minimal request bodies 3) Expected success responses and common errors 4) Links to the specific sections in the docs ``` -------------------------------- ### Get Characters Source: https://docs.jay-metadata.com/platform/how-to/show-products Retrieves a list of characters within a specific episode, often used as a basis for looks. ```APIDOC ## GET /playouts/{playoutId}/episodes/{episodeId}/characters ### Description Fetches a list of characters present in a specific episode. ### Method GET ### Endpoint /playouts/{playoutId}/episodes/{episodeId}/characters ### Parameters #### Path Parameters - **playoutId** (string) - Required - The ID of the playout. - **episodeId** (string) - Required - The ID of the episode. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **characters** (array) - A list of character objects. - **characterId** (string) - The unique identifier for the character. - **name** (string) - The name of the character. #### Response Example ```json { "characters": [ { "characterId": "char_001", "name": "Hero" } ] } ``` ``` -------------------------------- ### Inventory Management Source: https://docs.jay-metadata.com/retailer/product-management/api Endpoints and methods for managing product inventory levels and availability. ```APIDOC ## Stock Level Updates ### Description Keeps inventory levels current for products. ### Method PUT ### Endpoint /api/products/{productId}/inventory ### Parameters #### Path Parameters - **productId** (string) - Required - The unique identifier of the product. #### Request Body - **stockLevel** (integer) - Required - The new stock level for the product. ### Request Example ```json { "stockLevel": 50 } ``` ### Response #### Success Response (200) - **message** (string) - A confirmation message. #### Response Example ```json { "message": "Stock level for product prod_12345abc updated to 50." } ``` ``` ```APIDOC ## Availability Control ### Description Marks products as in-stock or out-of-stock by setting the stock count to zero or a positive value. ### Method PUT ### Endpoint /api/products/{productId}/availability ### Parameters #### Path Parameters - **productId** (string) - Required - The unique identifier of the product. #### Request Body - **available** (boolean) - Required - Set to `true` to mark as in-stock, `false` for out-of-stock. ### Request Example ```json { "available": false } ``` ### Response #### Success Response (200) - **message** (string) - A confirmation message. #### Response Example ```json { "message": "Product prod_12345abc is now out of stock." } ``` ``` -------------------------------- ### Angular Service Generator Prompt for Playout API Source: https://docs.jay-metadata.com/developer_environment_setup A prompt instructing an AI to generate an Angular `Injectable` service named `PlayoutService`. This service should include methods for interacting with the Playout API, using `HttpClient`, setting default headers from environment variables, handling errors, and providing strict typings. ```plaintext Generate an Angular Injectable service `PlayoutService` with methods: - createTrackingSession() - listEpisodes(playoutId) - getEpisode(playoutId, episodeId) - listGroups(playoutId, episodeId) - listScenes(playoutId, episodeId) - listTimelineEvents(playoutId, episodeId) Use HttpClient. Set default headers (X-API-Key from env token provider, X-API-Version pinned, send __Secure-jay_tracking cookie when available, else header). Provide strict typings (interfaces) and handle non-200 with typed errors. ``` -------------------------------- ### Get Locations Source: https://docs.jay-metadata.com/platform/how-to/show-products Retrieves a list of locations within a specific episode, which can be associated with looks. ```APIDOC ## GET /playouts/{playoutId}/episodes/{episodeId}/locations ### Description Fetches a list of locations present in a specific episode. ### Method GET ### Endpoint /playouts/{playoutId}/episodes/{episodeId}/locations ### Parameters #### Path Parameters - **playoutId** (string) - Required - The ID of the playout. - **episodeId** (string) - Required - The ID of the episode. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **locations** (array) - A list of location objects. - **locationId** (string) - The unique identifier for the location. - **name** (string) - The name of the location. #### Response Example ```json { "locations": [ { "locationId": "loc_001", "name": "City Square" } ] } ``` ``` -------------------------------- ### Angular Interceptor for API Headers and Cookies Source: https://docs.jay-metadata.com/developer_environment_setup An Angular HttpInterceptor to dynamically inject headers based on URL patterns and domain specifics. It handles API keys, versioning, tracking information for Playout, and JWT-based authorization for Basket. Configuration options for SSR and browser environments are included. ```typescript import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, } from '@angular/common/http'; import { Injectable, Optional, PLATFORM_ID, inject, } from '@angular/core'; import { isPlatformBrowser, isPlatformServer, } from '@angular/common'; import { BehaviorSubject, Observable, catchError, finalize, throwError, } from 'rxjs'; import { ConfigService, TrackingService, BasketService, PlayoutService, } from './services'; // Assume these services exist @Injectable() export class ApiInterceptor implements HttpInterceptor { private readonly platformId = inject(PLATFORM_ID); private readonly configService = inject(ConfigService); private readonly trackingService = inject(TrackingService); private readonly basketService = inject(BasketService); private readonly playoutService = inject(PlayoutService); intercept( request: HttpRequest, next: HttpHandler ): Observable> { const apiKey = this.configService.getApiKey(); const isPlayout = request.url.includes('playout.api.jay-metadata.com'); const isBasket = request.url.includes('basket.api.jay-metadata.com'); let modifiedRequest = request; // Inject X-API-Key if (apiKey) { modifiedRequest = request.clone({ headers: request.headers.set('X-API-Key', apiKey), }); } // Inject X-API-Version if (isPlayout) { modifiedRequest = modifiedRequest.clone({ headers: modifiedRequest.headers.set('X-API-Version', 'playout'), }); } else if (isBasket) { modifiedRequest = modifiedRequest.clone({ headers: modifiedRequest.headers.set('X-API-Version', 'basket'), }); } // Playout specific logic if (isPlayout && isPlatformBrowser(this.platformId)) { const trackingCookie = document.cookie.split('; ').find(row => row.startsWith('__Secure-jay_tracking=')); if (!trackingCookie && !request.headers.has('X-Tracking-Id')) { const trackingId = this.trackingService.getTrackingId(); if (trackingId) { modifiedRequest = modifiedRequest.clone({ headers: modifiedRequest.headers.set('X-Tracking-Id', trackingId), }); } } } // Basket specific logic if (isBasket && isPlatformServer(this.platformId)) { // Example: Attempt to get JWT from a server-side context, adjust as needed const jwt = this.basketService.getServerSideJwt(); if (jwt) { modifiedRequest = modifiedRequest.clone({ headers: modifiedRequest.headers.set('Authorization', `Bearer ${jwt}`), }); } } else if (isBasket && isPlatformBrowser(this.platformId)) { const jwt = this.basketService.getClientSideJwt(); if (jwt) { modifiedRequest = modifiedRequest.clone({ headers: modifiedRequest.headers.set('Authorization', `Bearer ${jwt}`), }); } } return next.handle(modifiedRequest).pipe( catchError(error => { // Handle specific errors if needed return throwError(() => error); }), finalize(() => { // Cleanup or logging if necessary }) ); } } // Example usage in app.module.ts or a dedicated http-interceptor.module.ts // { // provide: HTTP_INTERCEPTORS, // useClass: ApiInterceptor, // multi: true, // } ``` -------------------------------- ### Setup Tracking Session in Kotlin with OkHttp Source: https://docs.jay-metadata.com/platform/how-to/do-tracking This snippet demonstrates how to set up a tracking session by making a POST request to the jay API using Kotlin and OkHttp. It handles user ID inclusion and returns the session ID upon a successful response. Ensure OkHttp library is added to your project dependencies. ```kotlin import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import org.json.JSONObject // Setup a tracking session fun setupTracking(userId: String? = null): String? { val client = OkHttpClient() val requestBuilder = Request.Builder() .url("https://your-api-domain/v1/playouts/tracking/session") .header("x-jay-api-version", "2025-05-19") .header("X-API-Key", "your_api_key_here") if (userId != null) { val json = "{\"userId\":\"$userId\"}" val requestBody = json.toRequestBody("application/json".toMediaType()) requestBuilder.post(requestBody) } else { requestBuilder.post("".toRequestBody(null)) } val request = requestBuilder.build() client.newCall(request).execute().use { response -> if (response.isSuccessful) { val jsonData = JSONObject(response.body!!.string()) val sessionId = jsonData.getString("session_id") // Store session ID in shared preferences or secure storage saveSessionIdToPreferences(sessionId) return sessionId } } return null } // Placeholder for saving session ID fun saveSessionIdToPreferences(sessionId: String) { // Implementation to save sessionId to SharedPreferences or other secure storage println("Session ID saved: $sessionId") } ``` -------------------------------- ### Playout API Authentication Source: https://docs.jay-metadata.com/apis/authentication All endpoints of the APIs require an `X-API-Key` in the header. This API key will be provided to you by Jay. Please contact our support team to obtain your API key. ```APIDOC ## Playout API Authentication ### Description All endpoints of the APIs require an `X-API-Key` in the header. This API key will be provided to you by Jay. Please contact our support team to obtain your API key. ### Method GET ### Endpoint `/playout` ### Parameters #### Header Parameters - **X-API-Key** (string) - Required - Your unique API key provided by Jay. ### Request Example ```bash curl -X GET "https://api.jayplatform.com/playout" \ -H "X-API-Key: your_api_key_here" ``` ### Response #### Success Response (200) (Response structure not detailed in the provided text) #### Response Example (Response example not detailed in the provided text) ``` -------------------------------- ### TypeScript Basket Flow Functions Source: https://docs.jay-metadata.com/developer_environment_setup A set of TypeScript functions to manage a user's shopping basket. This includes creating a guest basket, retrieving product details, adding products, initiating checkout with Stripe, and finalizing the session. It incorporates error handling for common issues like stock changes and locked baskets. ```typescript import { z } from 'zod'; // Assume these are defined elsewhere based on API responses const GuestBasketResponseSchema = z.object({ userId: z.string(), jwt: z.string(), }); const ProductDetailsSchema = z.object({ productId: z.string(), variantId: z.string(), stock: z.number().positive(), price: z.number().positive(), }); const AddProductResponseSchema = z.object({ basketId: z.string(), // other basket details }); const CheckoutSessionResponseSchema = z.object({ clientSecret: z.string(), }); const FinalizeCheckoutResponseSchema = z.object({ status: z.enum(['success', 'failed']), orderId: z.string().optional(), }); const StockErrorSchema = z.object({ code: z.literal('STOCK_UNAVAILABLE'), productId: z.string(), variantId: z.string(), }); const LockedBasketErrorSchema = z.object({ code: z.literal('BASKET_LOCKED'), message: z.string(), }); // Union of potential errors for product details and add product const BasketOperationErrorSchema = z.discriminatedUnion('code', [ StockErrorSchema, LockedBasketErrorSchema, z.object({ code: z.string(), // Catch-all for other errors message: z.string(), }), ]); export type BasketOperationError = z.infer; interface HttpClient { post(url: string, body: any, options?: any): Promise; get(url: string, options?: any): Promise; } // Mock HttpClient const httpClient: HttpClient = { post: async (url, body) => { console.log(`POST ${url}`, body); // Simulate API responses if (url === '/baskets') return { userId: 'guest-123', jwt: 'guest-jwt-token' } as any; if (url === '/baskets/products/details') return [{ productId: 'p1', variantId: 'v1', stock: 10, price: 25.00 }] as any; if (url.startsWith('/baskets/')) return { basketId: 'basket-abc' } as any; if (url === '/checkout/session') return { clientSecret: 'stripe-client-secret-123' } as any; if (url.startsWith('/checkout/')) return { status: 'success', orderId: 'order-456' } as any; throw new Error('Not Found'); }, get: async (url) => { console.log(`GET ${url}`); // Simulate API responses if (url.startsWith('/baskets/')) return { basketId: 'basket-abc', userId: 'guest-123', items: [] } as any; throw new Error('Not Found'); } }; // 1) Create a guest basket export async function createGuestBasket(): Promise<{ userId: string; jwt: string } | BasketOperationError> { try { const response = await httpClient.post('/baskets', {}); return GuestBasketResponseSchema.parse(response); } catch (error: any) { console.error('Failed to create guest basket:', error); const parsedError = BasketOperationErrorSchema.safeParse(error.error?.body || error); if (parsedError.success) return parsedError.data; return { code: 'UNKNOWN', message: error.message } as BasketOperationError; } } // 2) Check product details export async function checkProductDetails(basketId: string, productIds: string[]): Promise[] | BasketOperationError> { try { const response = await httpClient.post(`/baskets/${basketId}/products/details`, { productIds }); // Assuming the API returns an array of product details, validate each const validatedDetails = response.map((detail: any) => ProductDetailsSchema.parse(detail)); return validatedDetails; } catch (error: any) { console.error('Failed to check product details:', error); const parsedError = BasketOperationErrorSchema.safeParse(error.error?.body || error); if (parsedError.success) return parsedError.data; return { code: 'UNKNOWN', message: error.message } as BasketOperationError; } } // 3) Add first available product to the basket export async function addFirstAvailableProductToBasket(basketId: string, products: { productId: string; variantId?: string }[]): Promise | BasketOperationError> { // In a real scenario, you'd iterate through products, check details, and add the first one with stock. // For simplicity, let's assume we add the first product from the input list. if (products.length === 0) { return { code: 'NO_PRODUCTS', message: 'No products provided to add.' } as BasketOperationError; } const productToAdd = products[0]; try { const response = await httpClient.post(`/baskets/${basketId}`, { productId: productToAdd.productId, variantId: productToAdd.variantId, quantity: 1, }); return AddProductResponseSchema.parse(response); } catch (error: any) { console.error('Failed to add product to basket:', error); const parsedError = BasketOperationErrorSchema.safeParse(error.error?.body || error); if (parsedError.success) return parsedError.data; return { code: 'UNKNOWN', message: error.message } as BasketOperationError; } } // 4) Start a checkout session export async function startCheckoutSession(basketId: string): Promise | BasketOperationError> { try { const response = await httpClient.post(`/checkout/session`, { basketId }); return CheckoutSessionResponseSchema.parse(response); } catch (error: any) { console.error('Failed to start checkout session:', error); const parsedError = BasketOperationErrorSchema.safeParse(error.error?.body || error); if (parsedError.success) return parsedError.data; return { code: 'UNKNOWN', message: error.message } as BasketOperationError; } } // 5) Finalize the active checkout session export async function finalizeCheckoutSession(sessionId: string): Promise | BasketOperationError> { try { const response = await httpClient.post(`/checkout/${sessionId}/finalize`, {}); return FinalizeCheckoutResponseSchema.parse(response); } catch (error: any) { console.error('Failed to finalize checkout session:', error); const parsedError = BasketOperationErrorSchema.safeParse(error.error?.body || error); if (parsedError.success) return parsedError.data; return { code: 'UNKNOWN', message: error.message } as BasketOperationError; } } // Example Usage: async function handleBasketFlow() { const guestBasket = await createGuestBasket(); if ('userId' in guestBasket) { const productDetails = await checkProductDetails(guestBasket.userId, ['product1']); if (Array.isArray(productDetails)) { const addResult = await addFirstAvailableProductToBasket(guestBasket.userId, [{ productId: 'product1' }]); if (!('code' in addResult)) { const checkoutSession = await startCheckoutSession(guestBasket.userId); if (!('code' in checkoutSession)) { // Use checkoutSession.clientSecret with Stripe Elements console.log('Stripe Client Secret:', checkoutSession.clientSecret); // Assume payment is successful, then finalize const finalizeResult = await finalizeCheckoutSession('some-session-id'); // Replace with actual session ID console.log('Checkout Finalization:', finalizeResult); } else { console.error('Checkout Session Error:', addResult); } } else { console.error('Add Product Error:', addResult); } } else { console.error('Product Details Error:', productDetails); } } else { console.error('Create Guest Basket Error:', guestBasket); } } // handleBasketFlow(); // Uncomment to run example ``` -------------------------------- ### GET /playouts/tracking/session Source: https://docs.jay-metadata.com/platform/how-to/do-tracking Retrieves an existing tracking session using headers. ```APIDOC ## GET /playouts/tracking/session ### Description Retrieves an existing tracking session using headers. ### Method GET ### Endpoint /v1/playouts/tracking/session ### Parameters #### Headers - **x-jay-api-version** (string) - Required - Specifies the API version to use. Defaults to the latest version if not provided. - **X-API-Key** (string) - Required - Your API key for authentication. ### Response #### Success Response (200) - **session_id** (string) - Unique identifier for the tracking session. - **start_time** (string) - ISO 8601 formatted timestamp of when the session started. - **source** (string) - Identifier of the system or API version that created this session. - **user_id** (string) - Optional identifier to track users across multiple sessions. Only present if provided in the request. #### Response Example ```json { "session_id": "550e8400-e29b-41d4-a716-446655440000", "start_time": "2023-01-15T14:30:24.123456", "source": "jay.api.playout.1.0.0", "user_id": "user-123456" } ``` ``` -------------------------------- ### Header-based Jay Tracking Setup and Requests (JavaScript) Source: https://docs.jay-metadata.com/platform/how-to/do-tracking Manages tracking sessions for platforms without cookie support. `setupTracking` creates a session, extracts the session ID, and saves it for later use. `fetchWithTracking` makes requests including the stored session ID in the `__Secure-jay_tracking` header. `deleteTrackingSession` removes the session and clears the stored ID. ```javascript // Create a session and store the ID async function setupTracking(userId = null) { const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-jay-api-version': '2025-05-19', 'X-API-Key': 'your_api_key_here' } }; if (userId) { options.body = JSON.stringify({ userId }); } const response = await fetch('https://your-api-domain/v1/playouts/tracking/session', options); const data = await response.json(); // Extract the session ID from the response const sessionId = data.session_id; // Store the session ID locally (e.g., localStorage, AsyncStorage, etc.) saveSessionId(sessionId); // Assume saveSessionId is implemented elsewhere return sessionId; } // Example for a request with the stored session ID async function fetchWithTracking(url) { const sessionId = getStoredSessionId(); // Assume getStoredSessionId is implemented elsewhere const response = await fetch(url, { headers: { '__Secure-jay_tracking': sessionId, 'x-jay-api-version': '2025-05-19', 'X-API-Key': 'your_api_key_here' } }); return response.json(); } // Example to delete a tracking session async function deleteTrackingSession() { const sessionId = getStoredSessionId(); // Assume getStoredSessionId is implemented elsewhere const response = await fetch('https://your-api-domain/v1/playouts/tracking/session', { method: 'DELETE', headers: { '__Secure-jay_tracking': sessionId, 'x-jay-api-version': '2025-05-19', 'X-API-Key': 'your_api_key_here' } }); if (response.ok) { // Clear the stored session ID clearSessionId(); // Assume clearSessionId is implemented elsewhere return true; } return false; } ``` -------------------------------- ### Get Product Groups Source: https://docs.jay-metadata.com/platform/how-to/show-products Retrieves product groups, which can be used to organize products by merchant or other common attributes, potentially for menu display. ```APIDOC ## GET /playouts/{playoutId}/episodes/{episodeId}/groups ### Description Retrieves product groups. Groups can be used to organize products by merchant or other common attributes, and some are designated as 'menu groups' for navigation. ### Method GET ### Endpoint /playouts/{playoutId}/episodes/{episodeId}/groups ### Parameters #### Path Parameters - **playoutId** (string) - Required - The ID of the playout. - **episodeId** (string) - Required - The ID of the episode. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **groups** (array) - A list of group objects. - **groupId** (string) - The unique identifier for the group. - **name** (string) - The name of the group. - **mainMenu** (boolean) - Indicates if this group is a main menu group. - **products** (array) - A list of product IDs within this group. #### Response Example ```json { "groups": [ { "groupId": "group_abc", "name": "Urban Streetwear", "mainMenu": true, "products": ["prod_123", "prod_456"] } ] } ``` ``` -------------------------------- ### Start Checkout Session Source: https://docs.jay-metadata.com/platform/how-to/checkout-stripe Initiate the checkout process by creating a checkout session. This endpoint generates the necessary Stripe payment details and order summary. ```APIDOC ## POST /v2/baskets/users/{userId}/checkout/sessions ### Description Initiates the checkout process by creating a checkout session and returning Stripe payment details. ### Method POST ### Endpoint /v2/baskets/users/{userId}/checkout/sessions ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user whose basket is being checked out. #### Request Body - **mode** (string) - Optional - The checkout mode, either 'test' or 'live'. Defaults to the tenant's default mode if omitted. ### Request Example ```json { "mode": "test" } ``` ### Response #### Success Response (200) - **sessionId** (string) - The unique identifier for the checkout session. - **stripe** (object) - Stripe-related configuration. - **publishableKey** (string) - The Stripe publishable key for the current environment. - **clientSecret** (string) - The client secret for the Stripe Payment Intent. - **accountId** (string) - The Stripe account ID. - **amount** (object) - Breakdown of the total amount. - **total** (string) - The total amount to be charged. - **currency** (string) - The currency of the total amount (e.g., 'EUR'). - **shipping** (string) - The shipping cost. - **tax** (string) - The tax amount. #### Response Example ```json { "sessionId": "cs_123456789", "stripe": { "publishableKey": "pk_test_1234567890abcdef", "clientSecret": "pi_1234_secret_5678", "accountId": "acct_12345" }, "amount": { "total": "49.99", "currency": "EUR", "shipping": "5.00", "tax": "7.96" } } ``` ``` -------------------------------- ### Start Checkout Session Source: https://docs.jay-metadata.com/platform/how-to/use-the-basket Initiates a checkout session for a user's basket. This action locks the basket for 30 minutes to prevent concurrent modifications. ```APIDOC ## POST /baskets/users/{userId}/checkout/sessions ### Description Initiates a checkout session for a user's basket. This locks the basket for 30 minutes, moving products to a separate "checkout" list. The basket remains locked until the checkout is completed or canceled. ### Method POST ### Endpoint /baskets/users/{userId}/checkout/sessions ### Parameters #### Path Parameters - **userId** (string) - Required - The unique identifier of the user. ### Request Example ```json { "example": "No request body required for starting checkout." } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message that the checkout session has started. #### Response Example ```json { "message": "Checkout session started successfully. Basket locked for 30 minutes." } ``` ```