### Minimum Loops.js Client Setup Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Initialize the LoopsClient with your API key. Ensure the API key is securely stored, for example, in environment variables. ```typescript import { LoopsClient } from "loops"; const loops = new LoopsClient(process.env.LOOPS_API_KEY); ``` -------------------------------- ### Node.js Environment Setup Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md Complete setup for a Node.js application, including API key validation and client initialization. ```typescript // config.ts import { LoopsClient } from "loops"; if (!process.env.LOOPS_API_KEY) { throw new Error("LOOPS_API_KEY environment variable is required"); } export const loopsClient = new LoopsClient(process.env.LOOPS_API_KEY); ``` ```typescript // main.ts import { loopsClient } from "./config"; import { APIError, RateLimitExceededError, ValidationError } from "loops"; async function main() { try { // Verify API key is valid const keyTest = await loopsClient.testApiKey(); console.log(`Connected to team: ${keyTest.teamName}`); // Use the client... const resp = await loopsClient.createContact({ email: "user@example.com" }); console.log(`Created contact: ${resp.id}`); } catch (error) { if (error instanceof ValidationError) { console.error("Validation error:", error.message); } else if (error instanceof RateLimitExceededError) { console.error("Rate limited:", error.message); } else if (error instanceof APIError) { console.error(`API error (${error.statusCode}):`, error.json?.message); } else { console.error("Unknown error:", error); } process.exit(1); } } main(); ``` -------------------------------- ### Loops.js Client Setup with Error Handling Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Set up the LoopsClient with basic error handling for a missing API key. This example demonstrates how to catch the specific error and exit gracefully. ```typescript try { const loops = new LoopsClient(process.env.LOOPS_API_KEY); } catch (error) { if (error instanceof Error && error.message === "API key is required") { console.error("Please set LOOPS_API_KEY"); process.exit(1); } } ``` -------------------------------- ### Install Loops SDK Source: https://github.com/loops-so/loops-js/blob/main/README.md Install the Loops SDK package from npm. Ensure you are using Node.js version 18.0.0 or higher. ```bash npm install loops ``` -------------------------------- ### Import Loops SDK Components Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Contacts.md Example of importing necessary classes and types from the 'loops' SDK for use in your project. This setup is required before interacting with the Loops API. ```typescript import { LoopsClient, Contact, ContactProperties, ValidationError, APIError } from "loops"; ``` -------------------------------- ### Minimum Setup Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Provides the basic code required to initialize the LoopsClient with an API key. ```APIDOC ## Initialization ### Description Initializes the Loops client with your API key. ### Usage ```typescript import { LoopsClient } from "loops"; const loops = new LoopsClient(process.env.LOOPS_API_KEY); ``` ``` -------------------------------- ### Setup with Error Handling Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Demonstrates how to initialize the LoopsClient with error handling for a missing API key. ```APIDOC ## Initialization with Error Handling ### Description Initializes the Loops client and includes error handling for cases where the API key is missing. ### Usage ```typescript try { const loops = new LoopsClient(process.env.LOOPS_API_KEY); } catch (error) { if (error instanceof Error && error.message === "API key is required") { console.error("Please set LOOPS_API_KEY"); process.exit(1); } } ``` ``` -------------------------------- ### Check Node.js Version Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md Verify your installed Node.js version. The SDK requires a minimum of Node.js 18.0.0. ```bash node --version ``` -------------------------------- ### Get All Themes Source: https://github.com/loops-so/loops-js/blob/main/README.md Fetches all available themes. Supports pagination with perPage and cursor options. ```javascript const resp = await loops.getThemes(); ``` ```javascript const resp = await loops.getThemes({ perPage: 15, cursor: "clyo0q4wo01p59fsecyxqsh38" }); ``` -------------------------------- ### Create Contact with Properties and Mailing Lists Source: https://github.com/loops-so/loops-js/blob/main/README.md This example demonstrates creating a contact with additional properties and specifying their subscription status for mailing lists. Ensure custom properties are added to your Loops account beforehand. ```javascript const contactProperties = { firstName: "Bob" /* Default property */, favoriteColor: "Red" /* Custom property */, }; const mailingLists = { cm06f5v0e45nf0ml5754o9cix: true /* Subscribe */, cm16k73gq014h0mmj5b6jdi9r: false /* Unsubscribe */, }; const resp = await loops.createContact({ email: "hello@gmail.com", properties: contactProperties, mailingLists, }); ``` -------------------------------- ### API Error Response Example Source: https://github.com/loops-so/loops-js/blob/main/README.md Example of an API error response when a campaign is not in draft status. ```json HTTP 409 Conflict { "success": false, "message": "Campaign is not in draft status." } ``` -------------------------------- ### Get Campaign Details Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves the details of a specific campaign. ```APIDOC ## GET /campaigns/{campaignId} ### Description Retrieves the details of a specific campaign. ### Method GET ### Endpoint /campaigns/{campaignId} ### Parameters #### Path Parameters - **campaignId** (string) - Required - The ID of the campaign to retrieve. ### Response #### Success Response (200) - **name** (string) - The name of the campaign. - **status** (string) - The current status of the campaign. - **emailMessageId** (string) - The ID of the associated email message. - **createdAt** (string) - The timestamp when the campaign was created. - **updatedAt** (string) - The timestamp when the campaign was last updated. ### Response Example ```json { "name": "Example Campaign", "status": "draft", "emailMessageId": "msg_abc123", "createdAt": "2023-10-27T10:00:00Z", "updatedAt": "2023-10-27T10:05:00Z" } ``` ``` -------------------------------- ### Get Campaigns Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieves a list of campaigns. Can be used with or without pagination parameters. ```javascript const resp = await loops.getCampaigns(); ``` ```javascript const resp = await loops.getCampaigns({ perPage: 15 }); ``` -------------------------------- ### Get Components Source: https://github.com/loops-so/loops-js/blob/main/README.md Fetches a paginated list of email components. Supports perPage and cursor for pagination. ```javascript const resp = await loops.getComponents(); ``` ```javascript const resp = await loops.getComponents({ perPage: 15 }); ``` -------------------------------- ### LMX Email Markup Example Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Demonstrates the structure of LMX (Loops Markup Language) for defining email content, including styles, sections, text, and buttons. Supports Handlebars variables for dynamic content. ```xml
Hello {{firstName}}! Welcome You've been selected.
``` -------------------------------- ### Get Campaigns Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieves a paginated list of campaigns. Supports perPage and cursor for pagination. ```javascript const resp = await loops.getCampaigns(); ``` -------------------------------- ### Contact Object Response Source: https://github.com/loops-so/loops-js/blob/main/README.md This is an example of a contact object returned when a contact is found. It includes default and custom properties, subscription status, and mailing list information. ```json [ { "id": "cll6b3i8901a9jx0oyktl2m4u", "email": "hello@gmail.com", "firstName": "Bob", "lastName": null, "source": "API", "subscribed": true, "userGroup": "", "userId": "12345", "mailingLists": { "cm06f5v0e45nf0ml5754o9cix": true }, "optInStatus": null, "favoriteColor": "Blue" /* Custom property */ } ] ``` -------------------------------- ### Get Themes Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Fetches a paginated list of email themes. Use this to retrieve available themes for selection or review. Supports pagination. ```typescript async getThemes(params?: { perPage?: number; cursor?: string; }): Promise ``` ```typescript const resp = await loops.getThemes(); resp.data.forEach(theme => { console.log(`${theme.themeId}: ${theme.name}`); console.log(` Default: ${theme.isDefault}`); console.log(` Background: ${theme.styles.backgroundColor}`); }); ``` -------------------------------- ### Event Properties Example Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Events-and-Emails.md Demonstrates the structure of event properties for the `sendEvent` API call. Note the limitations on data types (arrays and nested objects are not supported). ```typescript // Limited types const eventProperties = { eventName: "string", score: 100, isPremium: true // Can't use arrays or nested objects }; // Not supported: const eventProperties = { items: [1, 2, 3], // ❌ Arrays not supported metadata: { key: "value" } // ❌ Objects not supported }; ``` -------------------------------- ### Paginate Through List Endpoints Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md Fetch data in chunks using `perPage` and `cursor` parameters. The `nextCursor` in the response allows fetching subsequent pages. This example demonstrates fetching all items across multiple pages. ```typescript // Page 1 (default 20 items) const page1 = await loops.getThemes(); console.log(page1.pagination.nextCursor); // Specify per-page count const page1 = await loops.getThemes({ perPage: 50 }); // Fetch next page const page2 = await loops.getThemes({ perPage: 50, cursor: page1.pagination.nextCursor }); // Fetch all pages async function getAllThemes() { const allThemes = []; let cursor; while (true) { const resp = await loops.getThemes({ perPage: 50, cursor }); allThemes.push(...resp.data); if (!resp.pagination.nextCursor) break; cursor = resp.pagination.nextCursor; } return allThemes; } ``` -------------------------------- ### Successful Contact Creation Response Source: https://github.com/loops-so/loops-js/blob/main/README.md This is an example of a successful response when creating a contact. It confirms the operation's success and provides the unique ID of the newly created contact. ```json { "success": true, "id": "id_of_contact" } ``` -------------------------------- ### Get Components Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Retrieves a paginated list of email components. Use this to fetch available components for use in email templates. Supports pagination. ```typescript async getComponents(params?: { perPage?: number; cursor?: string; }): Promise ``` ```typescript const resp = await loops.getComponents(); resp.data.forEach(comp => { console.log(`${comp.componentId}: ${comp.name}`); }); ``` -------------------------------- ### Successful API Key Test Response Source: https://github.com/loops-so/loops-js/blob/main/README.md Example of a successful response when testing an API key, indicating the key is valid and the team name. ```json { "success": true, "teamName": "My team" } ``` -------------------------------- ### API Error Response Example Source: https://github.com/loops-so/loops-js/blob/main/README.md Illustrates a typical error response from the API, including the HTTP status code and a JSON body detailing the error. Error handling can be managed using the `APIError` class. ```json HTTP 400 Bad Request { "success": false, "message": "An error message here." } ``` -------------------------------- ### Implement Rate Limit Safety with Delays Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md To avoid hitting API rate limits, introduce small delays between requests. This example spaces requests approximately 100ms apart. ```typescript for (const email of emails) { await loops.updateContact({ email, properties: { /* ... */ } }); await new Promise(resolve => setTimeout(resolve, 100)); } ``` -------------------------------- ### Constructor Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Initializes the LoopsClient with an API key. ```APIDOC ## Constructor ### Description Initializes the LoopsClient with an API key. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **apiKey** (string) - Required - The Loops API key. Can be generated at https://app.loops.so/settings?page=api ### Throws - `Error` if apiKey is not provided (empty, null, or undefined). ### Example ```typescript import { LoopsClient } from "loops"; const loops = new LoopsClient(process.env.LOOPS_API_KEY); ``` ``` -------------------------------- ### Get Theme by ID Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Retrieves a specific email theme using its unique ID. Use this to get detailed styling and information for a particular theme. ```typescript async getTheme(themeId: string): Promise ``` ```typescript const theme = await loops.getTheme("theme_123"); console.log(theme.name); console.log(theme.styles.backgroundColor); ``` -------------------------------- ### createCampaign() Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Creates a new campaign in a draft state, ready for content to be added. ```APIDOC ## createCampaign() ### Description Create a new draft campaign with an empty email message. ### Method POST (implied) ### Endpoint /campaigns (implied) ### Parameters #### Request Body - **name** (string) - Required - The campaign name. ### Response #### Success Response (200) - **success** (boolean) - Indicates if the request was successful. - **campaignId** (string) - The ID of the newly created campaign. - **name** (string) - The name of the campaign. - **status** (string) - The status of the campaign (typically "Draft"). - **emailMessageId** (string) - The associated email message ID. - **emailMessageContentRevisionId** (string | null) - The content revision ID for the email message. ### Request Example ```typescript const resp = await loops.createCampaign({ name: "Spring announcement" }); console.log(resp.campaignId); console.log(resp.emailMessageId); // Use this with updateEmailMessage() ``` ``` -------------------------------- ### Get Email Message Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves the details of a specific email message. ```APIDOC ## GET /email-messages/{messageId} ### Description Retrieves the details of a specific email message. ### Method GET ### Endpoint /email-messages/{messageId} ### Parameters #### Path Parameters - **messageId** (string) - Required - The ID of the email message to retrieve. ### Response #### Success Response (200) - **subject** (string) - The subject line of the email. - **previewText** (string) - The preview text displayed in email clients. - **fromName** (string) - The sender's display name. - **fromEmail** (string) - The sender's username (domain is appended automatically). - **replyToEmail** (string) - The reply-to email address. - **lmx** (string) - The email content in LMX markup format. - **contentRevisionId** (string) - The current revision ID, used for optimistic concurrency control. - **warnings** (array) - A list of validation warnings for the email content. ### Response Example ```json { "subject": "Check This Out", "previewText": "You won't believe this", "fromName": "My Company", "fromEmail": "hello", "replyToEmail": "", "lmx": "...", "contentRevisionId": "rev_def456", "warnings": [] } ``` ``` -------------------------------- ### Get Specific Campaign Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a single campaign by its unique identifier. ```APIDOC ## GET /campaigns/{campaignId} ### Description Retrieves a single campaign by its unique identifier. ### Method GET ### Endpoint /campaigns/{campaignId} ### Parameters #### Path Parameters - **campaignId** (string) - Required - The unique identifier of the campaign to retrieve. ### Response #### Success Response (200) - **campaignId** (string) - The unique identifier for the campaign. - **name** (string) - The name of the campaign. - **status** (string) - The current status of the campaign. - **subject** (string) - The subject line of the campaign's email. - **emailMessageId** (string) - The ID of the associated email message. ### Request Example ```javascript const campaign = await loops.getCampaign("camp_abc"); console.log(campaign.name); console.log(campaign.status); ``` ``` -------------------------------- ### Initialize Loops Client and Create Contact Source: https://github.com/loops-so/loops-js/blob/main/README.md Initialize the LoopsClient with your API key and create a new contact. Includes basic error handling for API errors. ```javascript import { LoopsClient, APIError } from "loops"; const loops = new LoopsClient(process.env.LOOPS_API_KEY); try { const resp = await loops.createContact("email@provider.com"); // resp.success and resp.id available when successful } catch (error) { if (error instanceof APIError) { // JSON returned by the API is in error.json and the HTTP code is in error.statusCode // error.json may be null if the response was not valid JSON (e.g., from a load balancer) // In that case, the raw response text is available in error.rawBody console.log(error.json); console.log(error.statusCode); console.log(error.rawBody); } else { // Non-API errors } } ``` -------------------------------- ### Get Email Message Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves an email message, including its LMX content. ```APIDOC ## GET /email-messages/{messageId} ### Description Retrieves an email message, including its LMX content. ### Method GET ### Endpoint /email-messages/{messageId} ### Parameters #### Path Parameters - **messageId** (string) - Required - The unique identifier of the email message to retrieve. ### Response #### Success Response (200) - **messageId** (string) - The unique identifier for the email message. - **lmx** (string) - The LMX markup of the email message. - **subject** (string) - The subject of the email message. ### Request Example ```javascript const message = await loops.getEmailMessage("msg_xyz"); console.log(message.lmx); console.log(message.subject); ``` ``` -------------------------------- ### Create and Use Custom Contact Properties Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Contacts.md Demonstrates how to define custom string, number, boolean, and date properties for contacts and then update a contact with these properties. It also shows how to list all properties to verify creation. ```typescript async function setupCustomProperties() { await loops.createContactProperty("planTier", "string"); await loops.createContactProperty("monthlySpend", "number"); await loops.createContactProperty("isPremium", "boolean"); await loops.createContactProperty("joinDate", "date"); } // 2. Use it in contacts await loops.updateContact({ email: "user@example.com", properties: { planTier: "enterprise", monthlySpend: 999.99, isPremium: true, joinDate: "2024-01-15" } }); // 3. List all properties to verify const props = await loops.getContactProperties(); console.log(props.filter(p => p.type === "string")); ``` -------------------------------- ### Initialize LoopsClient with API Key Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md Instantiate the LoopsClient using your API key. It's recommended to use environment variables for security. Hardcoding keys is not advised for production environments. ```typescript import { LoopsClient } from "loops"; // From environment variable const loops = new LoopsClient(process.env.LOOPS_API_KEY); // From hardcoded string (not recommended for production) const loops = new LoopsClient("api_key_12345"); // With error handling try { const loops = new LoopsClient(apiKeyFromConfig); } catch (error) { console.error("Invalid API key:", error.message); } ``` -------------------------------- ### Get Specific Component Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a single email component by its unique identifier. ```APIDOC ## GET /components/{componentId} ### Description Retrieves a single email component by its unique identifier. ### Method GET ### Endpoint /components/{componentId} ### Parameters #### Path Parameters - **componentId** (string) - Required - The unique identifier of the component to retrieve. ### Response #### Success Response (200) - **componentId** (string) - The unique identifier for the component. - **name** (string) - The name of the component. - **lmx** (string) - The LMX markup for the component. ### Request Example ```javascript const comp = await loops.getComponent("comp_header"); console.log(comp.name); // "Email Header" console.log(comp.lmx); // The LMX markup ``` ``` -------------------------------- ### Import Loops Client and Entities Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Demonstrates how to import the main LoopsClient class and various other entities like Theme, Component, and CampaignListItem from the 'loops' package. ```typescript import { LoopsClient, Theme, Component, CampaignListItem, EmailMessageResponse, TransactionalEmail } from "loops"; ``` -------------------------------- ### Get Specific Theme Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a single email theme by its unique identifier. ```APIDOC ## GET /themes/{themeId} ### Description Retrieves a single email theme by its unique identifier. ### Method GET ### Endpoint /themes/{themeId} ### Parameters #### Path Parameters - **themeId** (string) - Required - The unique identifier of the theme to retrieve. ### Response #### Success Response (200) - **themeId** (string) - The unique identifier for the theme. - **name** (string) - The name of the theme. - **styles** (object) - An object containing the theme's style properties. - **backgroundColor** (string) - The background color of the theme. - **buttonTextColor** (string) - The text color for buttons. - ... (other style properties) ### Request Example ```javascript const theme = await loops.getTheme("theme_123"); console.log(theme.name); console.log(theme.styles.backgroundColor); console.log(theme.styles.buttonTextColor); ``` ``` -------------------------------- ### Get Specific Theme Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a single email theme by its unique identifier. ```typescript const theme = await loops.getTheme("theme_123"); console.log(theme.name); console.log(theme.styles.backgroundColor); console.log(theme.styles.buttonTextColor); ``` -------------------------------- ### Project File Organization Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Illustrates the directory structure of the loops-js project, categorizing documentation files by their respective API domains. ```markdown /api-reference/ LoopsClient.md # Main client class & all methods Contacts.md # Contact management workflows Events-and-Emails.md # Event & transactional email patterns Content-Management.md # Themes, components, campaigns Mailing-Lists.md # Mailing list operations types.md # All exported types errors.md # Error classes & handling configuration.md # Setup, options, constraints README.md # This file ``` -------------------------------- ### Set API Key via Environment Variable Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md Store your API key in a .env file for secure access. This method is preferred over hardcoding. ```bash # .env LOOPS_API_KEY=your_api_key_here ``` -------------------------------- ### Using Components in Campaign Email Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Demonstrates how to reference reusable components within an email message's LMX markup. ```typescript const lmx = "
Hello {{firstName}}!
"; await loops.updateEmailMessage("msg_123", { lmx, subject: "Newsletter" }); ``` -------------------------------- ### Create Contact with Mailing List Subscriptions Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Mailing-Lists.md Creates a new contact and specifies their initial subscription status for multiple mailing lists. Use `true` to subscribe and `false` to not subscribe. ```typescript // Create a contact and subscribe to lists await loops.createContact({ email: "user@example.com", mailingLists: { "list_id_1": true, // Subscribe to this list "list_id_2": false // Don't subscribe to this list } }); ``` -------------------------------- ### Get Campaigns Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Retrieves a paginated list of campaigns. Supports filtering by perPage and cursor for pagination. ```typescript async getCampaigns(params?: { perPage?: number; cursor?: string; }): Promise ``` ```typescript const resp = await loops.getCampaigns(); resp.data.forEach(campaign => { console.log(`${campaign.campaignId}: ${campaign.name}`); console.log(` Status: ${campaign.status}`); console.log(` Subject: ${campaign.subject}`); }); ``` -------------------------------- ### Get Dedicated Sending IPs Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves information about Loops' dedicated sending IP addresses. ```APIDOC ## GET /settings/sending-ips ### Description Retrieves information about Loops' dedicated sending IP addresses. ### Method GET ### Endpoint /settings/sending-ips ### Response #### Success Response (200) - **data** (array) - An array of objects, each representing a dedicated sending IP address. - **ipAddress** (string) - The IP address. - **status** (string) - The status of the IP address (e.g., "Active", "Inactive"). - **createdAt** (string) - The date the IP address was created. ### Request Example ```javascript const resp = await loops.getDedicatedSendingIps(); resp.data.forEach(ipInfo => { console.log(`IP: ${ipInfo.ipAddress}, Status: ${ipInfo.status}`); }); ``` ``` -------------------------------- ### ESM and CommonJS Imports Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md Demonstrates how to import the LoopsClient using either ECMAScript Modules (ESM) or CommonJS module systems. ```typescript // ESM (recommended) import { LoopsClient } from "loops"; ``` ```typescript // CommonJS const { LoopsClient } = require("loops"); ``` -------------------------------- ### Get Component LMX Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a specific email component by its ID, returning its LMX markup. ```typescript const comp = await loops.getComponent("comp_header"); console.log(comp.name); // "Email Header" console.log(comp.lmx); // The LMX markup ``` -------------------------------- ### createCampaign() Source: https://github.com/loops-so/loops-js/blob/main/README.md Creates a new draft campaign. An empty email message is created automatically, and its `emailMessageId` is returned. Use `updateEmailMessage()` to set subject, sender, preview text, and LMX content. ```APIDOC ## createCampaign() ### Description Create a new draft campaign. An empty email message is created automatically and its `emailMessageId` is returned. Use [`updateEmailMessage()`](#updateemailmessage) to set subject, sender, preview text, and LMX content. Requires the content API to be enabled for your team. ### Method POST ### Endpoint /campaigns ### Parameters #### Request Body - **name** (string) - Required - The campaign name. ### Request Example ```javascript const resp = await loops.createCampaign({ name: "Spring announcement" }); ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the request was successful. - **campaignId** (string) - The unique identifier for the newly created campaign. - **name** (string) - The name of the campaign. - **status** (string) - The status of the campaign (e.g., 'Draft'). - **createdAt** (string) - The timestamp when the campaign was created. - **updatedAt** (string) - The timestamp when the campaign was last updated. - **emailMessageId** (string) - The ID of the automatically created email message. - **emailMessageContentRevisionId** (string) - The ID of the email message content revision. #### Response Example ```json { "success": true, "campaignId": "camp_123", "name": "Spring announcement", "status": "Draft", "createdAt": "2025-01-01T00:00:00.000Z", "updatedAt": "2025-01-01T00:00:00.000Z", "emailMessageId": "msg_123", "emailMessageContentRevisionId": "rev_123" } ``` ``` -------------------------------- ### Link External ID and Email Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Contacts.md Demonstrates how to associate an external system's user ID with a contact's email. It shows creating a contact with an email first, then updating it with the userId, or vice-versa. ```typescript // First create with email await loops.createContact({ email: "newuser@example.com" }); // Later, when you have their external ID, update it await loops.updateContact({ email: "newuser@example.com", userId: "user_12345" // External system ID }); // Or if you already know the external ID await loops.updateContact({ userId: "user_12345", email: "user@example.com" }); ``` -------------------------------- ### List All Components Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a list of all available email components. Supports pagination. ```APIDOC ## GET /components ### Description Retrieves a list of all available email components. Supports pagination. ### Method GET ### Endpoint /components ### Parameters #### Query Parameters - **cursor** (string) - Optional - The cursor for the next page of results. - **perPage** (number) - Optional - The number of results to return per page. Defaults to 50. ### Response #### Success Response (200) - **data** (array) - An array of component objects. - **componentId** (string) - The unique identifier for the component. - **name** (string) - The name of the component. - **pagination** (object) - Pagination information. - **nextCursor** (string) - The cursor for the next page of results, or null if there are no more pages. ### Request Example ```javascript const resp = await loops.getComponents(); resp.data.forEach(comp => { console.log(`${comp.componentId}: ${comp.name}`); }); // Paginate if (resp.pagination.nextCursor) { const nextPage = await loops.getComponents({ cursor: resp.pagination.nextCursor }); } ``` ``` -------------------------------- ### Get Campaign by ID Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieves a single campaign by its ID. Requires the content API to be enabled for your team. ```javascript const resp = await loops.getCampaign("camp_123"); ``` -------------------------------- ### Get Contact Properties Source: https://github.com/loops-so/loops-js/blob/main/README.md Fetches all contact properties or custom properties. Use this to retrieve schema information for contacts. ```javascript const resp = await loops.getContactProperties(); ``` ```javascript const resp = await loops.getContactProperties("custom"); ``` -------------------------------- ### Workflow: Subscribe New User to Newsletter Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Mailing-Lists.md Automates the process of subscribing a new user to a specific newsletter list upon signup. It finds the 'Newsletter' list by name and creates the contact with the correct subscription. ```typescript async function signupToNewsletter(email, firstName) { // Get newsletter list const lists = await loops.getMailingLists(); const newsletter = lists.find(l => l.name === "Newsletter"); if (!newsletter) { throw new Error("Newsletter list not found"); } // Create contact and subscribe await loops.createContact({ email, properties: { firstName, source: "newsletter_signup" }, mailingLists: { [newsletter.id]: true } }); } ``` -------------------------------- ### Get Single Theme by ID Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieves a specific theme using its unique ID. Requires the content API to be enabled. ```javascript const resp = await loops.getTheme("theme_123"); ``` -------------------------------- ### Paginate Through All Themes Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Illustrates how to fetch all themes from the Loops API by handling pagination. This function repeatedly calls `getThemes` until all pages of results are retrieved. ```typescript async function getAllThemes() { const allThemes = []; let cursor; while (true) { const resp = await loops.getThemes({ perPage: 50, cursor }); allThemes.push(...resp.data); if (!resp.pagination.nextCursor) break; cursor = resp.pagination.nextCursor; } return allThemes; } ``` -------------------------------- ### Import Loops Client and Types Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Mailing-Lists.md Import necessary components from the 'loops' SDK, including the client, MailingList type, and MailingLists type. ```typescript import { LoopsClient, MailingList, MailingLists } from "loops"; ``` -------------------------------- ### Get Dedicated Sending IPs Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieve a list of Loops' dedicated sending IP addresses. This is primarily for whitelisting purposes. ```javascript const resp = await loops.getDedicatedSendingIps(); ``` -------------------------------- ### Get Mailing Lists Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieves a list of all mailing lists associated with the account. Returns an empty list if none exist. ```javascript const resp = await loops.getMailingLists(); ``` -------------------------------- ### Create Contact with Dynamically Managed Mailing Lists Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md Creates a contact by dynamically fetching available mailing lists and setting subscription statuses based on specific criteria. ```typescript // Get available lists first const lists = await loops.getMailingLists(); const listMap = {}; lists.forEach(list => { listMap[list.id] = false; // Unsubscribe from all if (list.name === "Newsletter") { listMap[list.id] = true; // But subscribe to Newsletter } }); const resp = await loops.createContact({ email: "user@example.com", mailingLists: listMap }); ``` -------------------------------- ### Get Email Message Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieves an email message, including its compiled LMX content. Requires the content API to be enabled for your team. ```javascript const resp = await loops.getEmailMessage("msg_123"); ``` -------------------------------- ### Pagination Efficiency Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Explains how to optimize list operations for performance by specifying a `perPage` limit, recommended at 50. ```APIDOC ## Efficient List Operations ### Description Optimizes retrieval of lists by using the `perPage` parameter to control the number of items returned per request. ### Method GET (for list operations like `getThemes`) ### Parameters #### Query Parameters - **perPage** (integer) - Optional - The number of items to return per page. Recommended value: 50. ### Usage ```typescript const resp = await loops.getThemes({ perPage: 50 }); ``` ``` -------------------------------- ### Create Draft Campaign Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Creates a new draft campaign. ```APIDOC ## POST /campaigns ### Description Creates a new draft campaign. ### Method POST ### Endpoint /campaigns ### Parameters #### Request Body - **name** (string) - Required - The name for the new campaign. ### Response #### Success Response (201) - **campaignId** (string) - The unique identifier for the newly created campaign. - **emailMessageId** (string) - The ID of the associated email message. - **status** (string) - The status of the new campaign, which will be "Draft". ### Request Example ```javascript const resp = await loops.createCampaign({ name: "Spring Announcement 2024" }); console.log(resp.campaignId); // camp_xxx console.log(resp.emailMessageId); // msg_xxx console.log(resp.status); // "Draft" ``` ``` -------------------------------- ### Get Single Component by ID Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieves a specific email component using its unique ID. Requires the content API to be enabled. ```javascript const resp = await loops.getComponent("comp_123"); ``` -------------------------------- ### List All Themes Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a list of all available email themes. Supports pagination. ```APIDOC ## GET /themes ### Description Retrieves a list of all available email themes. Supports pagination. ### Method GET ### Endpoint /themes ### Parameters #### Query Parameters - **cursor** (string) - Optional - The cursor for the next page of results. - **perPage** (number) - Optional - The number of results to return per page. Defaults to 50. ### Response #### Success Response (200) - **data** (array) - An array of theme objects. - **themeId** (string) - The unique identifier for the theme. - **name** (string) - The name of the theme. - **isDefault** (boolean) - Indicates if this is the default theme. - **styles** (object) - An object containing the theme's style properties. - **pagination** (object) - Pagination information. - **nextCursor** (string) - The cursor for the next page of results, or null if there are no more pages. ### Request Example ```javascript const resp = await loops.getThemes(); resp.data.forEach(theme => { console.log(`${theme.themeId}: ${theme.name}`); console.log(` Default: ${theme.isDefault}`); console.log(` Background: ${theme.styles.backgroundColor}`); }); // Check for next page if (resp.pagination.nextCursor) { const nextPage = await loops.getThemes({ cursor: resp.pagination.nextCursor, perPage: 50 }); } ``` ``` -------------------------------- ### Get Component by ID Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Fetches a single email component by its ID. Use this to retrieve the LMX markup and details of a specific component. ```typescript async getComponent(componentId: string): Promise ``` ```typescript const comp = await loops.getComponent("comp_123"); console.log(comp.name); console.log(comp.lmx); // LMX markup ``` -------------------------------- ### Unauthorized API Key Error Response Source: https://github.com/loops-so/loops-js/blob/main/README.md Example of an error response when an invalid API key is used, resulting in a 401 Unauthorized status. ```json HTTP 401 Unauthorized { "error": "Invalid API key" } ``` -------------------------------- ### Utility Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/README.md Utility methods for testing and other common tasks. ```APIDOC ## Utility ### Test API Key Tests the validity of the provided API key. ### Method GET ### Endpoint /api-key/test ``` -------------------------------- ### Configure Query Parameters for List Endpoints Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/configuration.md List endpoints automatically construct query parameters from provided objects. Use `perPage` to set the number of items per page and `cursor` to navigate through pages. ```typescript // perPage and cursor automatically become query params const resp = await loops.getThemes({ perPage: 15, cursor: "xyz" }); // Results in: GET /api/v1/themes?perPage=15&cursor=xyz ``` -------------------------------- ### Get Themes Source: https://github.com/loops-so/loops-js/blob/main/README.md Retrieve a paginated list of email themes, sorted by creation date (most recent first). This feature requires the content API to be enabled. ```javascript const resp = await loops.getThemes(); ``` -------------------------------- ### List All Components Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a list of all reusable email components. Supports pagination. ```typescript const resp = await loops.getComponents(); resp.data.forEach(comp => { console.log(`${comp.componentId}: ${comp.name}`); }); // Paginate if (resp.pagination.nextCursor) { const nextPage = await loops.getComponents({ cursor: resp.pagination.nextCursor }); } ``` -------------------------------- ### CreateCampaignResponse Interface Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/types.md Defines the structure for the response after successfully creating a new campaign. Includes details of the created campaign and associated message IDs. ```typescript interface CreateCampaignResponse { success: true; campaignId: string; name: string; status: string; createdAt: string; updatedAt: string; emailMessageId: string; emailMessageContentRevisionId: string | null; } ``` -------------------------------- ### Get Campaign by ID Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Retrieves a single campaign's details using its unique ID. Returns campaign information such as name, status, and timestamps. ```typescript async getCampaign(campaignId: string): Promise ``` ```typescript const campaign = await loops.getCampaign("camp_123"); console.log(campaign.name); console.log(campaign.status); console.log(campaign.emailMessageId); ``` -------------------------------- ### Get Contact Properties Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/LoopsClient.md Retrieve a list of all available contact properties, including default and custom ones. You can optionally filter to retrieve only custom properties. ```typescript async getContactProperties(list?: "all" | "custom"): Promise ``` ```typescript // Get all properties (default + custom) const props = await loops.getContactProperties(); // Get only custom properties const customProps = await loops.getContactProperties("custom"); customProps.forEach(prop => { console.log(`${prop.label} (${prop.key}): ${prop.type}`); }); ``` -------------------------------- ### List All Themes Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves a list of all available email themes. Supports pagination to fetch themes in batches. ```typescript const resp = await loops.getThemes(); resp.data.forEach(theme => { console.log(`${theme.themeId}: ${theme.name}`); console.log(` Default: ${theme.isDefault}`); console.log(` Background: ${theme.styles.backgroundColor}`); }); // Check for next page if (resp.pagination.nextCursor) { const nextPage = await loops.getThemes({ cursor: resp.pagination.nextCursor, perPage: 50 }); } ``` -------------------------------- ### Get Campaign Details Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md Retrieves the details of a specific campaign using its ID. Useful for inspecting campaign properties like name, status, and timestamps. ```typescript const campaign = await loops.getCampaign("camp_123"); console.log(campaign.name); console.log(campaign.status); console.log(campaign.emailMessageId); console.log(campaign.createdAt); console.log(campaign.updatedAt); ``` -------------------------------- ### Successful Email Message Update Response Source: https://github.com/loops-so/loops-js/blob/main/README.md This is an example of a successful response after updating an email message. It includes details of the updated message and its new revision ID. ```json { "success": true, "emailMessageId": "msg_123", "campaignId": "camp_123", "subject": "Hello", "previewText": "Preview text", "fromName": "Loops", "fromEmail": "hello", "replyToEmail": "", "lmx": "...", "contentRevisionId": "rev_456", "updatedAt": "2025-01-02T00:00:00.000Z", "warnings": [ { "rule": "example", "severity": "warning", "message": "Example warning" } ] } ``` -------------------------------- ### Data Variables Example Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Events-and-Emails.md Illustrates the structure of data variables for the `sendTransactionalEmail` API call. This supports richer data types, including arrays and nested objects. ```typescript // Rich types including arrays const dataVariables = { message: "string", amount: 99.99, items: [ // ✅ Arrays supported { name: "Item 1", price: 10 } ] }; ``` -------------------------------- ### Full Campaign Creation Flow Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/api-reference/Content-Management.md A comprehensive workflow for creating a campaign, retrieving its associated email message, and configuring the email content. This function handles multiple API calls sequentially. ```typescript async function createAndConfigureCampaign(name, emailConfig) { // 1. Create the campaign const campaign = await loops.createCampaign({ name }); // 2. Get the email message (created automatically) const message = await loops.getEmailMessage(campaign.emailMessageId); // 3. Configure the email content const updated = await loops.updateEmailMessage( campaign.emailMessageId, { expectedRevisionId: message.contentRevisionId, subject: emailConfig.subject, previewText: emailConfig.preview, fromName: emailConfig.fromName, fromEmail: emailConfig.fromEmail, lmx: emailConfig.lmx } ); return { campaignId: campaign.campaignId, emailMessageId: campaign.emailMessageId, revisionId: updated.contentRevisionId }; } const campaign = await createAndConfigureCampaign( "My Campaign", { subject: "Check This Out", preview: "You won't believe this", fromName: "My Company", fromEmail: "hello", lmx: "..." } ); ``` -------------------------------- ### ListCampaignsResponse Interface Source: https://github.com/loops-so/loops-js/blob/main/_autodocs/types.md Defines the structure for the response when listing campaigns. Includes pagination data and an array of campaign list items. ```typescript interface ListCampaignsResponse { success: true; pagination: PaginationData; data: CampaignListItem[]; } ``` -------------------------------- ### Response for Get Transactional Emails Source: https://github.com/loops-so/loops-js/blob/main/README.md A successful response includes pagination details and a list of transactional emails, each with its ID, last updated timestamp, and data variables. ```json { "pagination": { "totalResults": 23, "returnedResults": 20, "perPage": 20, "totalPages": 2, "nextCursor": "clyo0q4wo01p59fsecyxqsh38", "nextPage": "https://app.loops.so/api/v1/transactional?cursor=clyo0q4wo01p59fsecyxqsh38&perPage=20" }, "data": [ { "id": "clfn0k1yg001imo0fdeqg30i8", "lastUpdated": "2023-11-06T17:48:07.249Z", "dataVariables": [] }, { "id": "cll42l54f20i1la0lfooe3z12", "lastUpdated": "2025-02-02T02:56:28.845Z", "dataVariables": [ "confirmationUrl" ] }, { "id": "clw6rbuwp01rmeiyndm80155l", "lastUpdated": "2024-05-14T19:02:52.000Z", "dataVariables": [ "firstName", "lastName", "inviteLink" ] }, ... ] } ```