### 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}}!WelcomeYou'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"
]
},
...
]
}
```