> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modulex.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Loops Integration for AI Agents & Workflows

> Integrate Loops into the workflow. Create and manage contacts, send transactional emails, and trigger event-based automations.

{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}

<img src="https://mintcdn.com/modulexaillc/df8MOr-hXotYLTh5/logos/placeholder.svg?fit=max&auto=format&n=df8MOr-hXotYLTh5&q=85&s=a4046f9cd6d738c81259050e9833913c" alt="Loops logo" width="72" height="72" data-path="logos/placeholder.svg" />

## Overview

Add **Loops** to any ModuleX agent or workflow. Manage contacts and send emails with Loops. Create and manage contacts, send transactional emails, and trigger event-based automations against the Loops REST API (`app.loops.so/api/v1`).

<Info>
  **Categories**: Marketing & Advertising · Email Marketing · Automation · **Auth**: API Key · **Actions**: 10
</Info>

## Authentication

### API Key Authentication

Authenticate using your Loops API key

<Steps>
  <Step title="Step 1">
    Log in to your Loops account at [https://app.loops.so](https://app.loops.so)
  </Step>

  <Step title="Step 2">
    Go to Settings > API
  </Step>

  <Step title="Step 3">
    Create a new API key or copy your existing one
  </Step>

  <Step title="Step 4">
    Paste the API key below
  </Step>
</Steps>

#### Required Credentials

| Field         | Description                            | Required | Format |
| ------------- | -------------------------------------- | -------- | ------ |
| Loops API Key | Your Loops API key from Settings > API | Yes      | `-`    |

## Available Actions

<AccordionGroup>
  <Accordion title="create_contact — Create a new contact in your Loops audience with an email address and optional properties like name, user group, and mailing list subscriptions.">
    ### Parameters

    <ResponseField name="email" type="string" required>
      The email address for the new contact
    </ResponseField>

    <ResponseField name="first_name" type="string">
      The contact first name
    </ResponseField>

    <ResponseField name="last_name" type="string">
      The contact last name
    </ResponseField>

    <ResponseField name="source" type="string">
      Custom source value replacing the default "API"
    </ResponseField>

    <ResponseField name="subscribed" type="boolean">
      Whether the contact receives campaign emails (defaults to true)
    </ResponseField>

    <ResponseField name="user_group" type="string">
      Group to segment the contact into (one group per contact)
    </ResponseField>

    <ResponseField name="user_id" type="string">
      Unique user identifier from your application
    </ResponseField>

    <ResponseField name="mailing_lists" type="object">
      Mailing list IDs mapped to boolean values (true to subscribe, false to unsubscribe)
    </ResponseField>

    <ResponseField name="custom_properties" type="object">
      Custom contact properties as key-value pairs (string, number, boolean, or date values)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Id"
        }
      },
      "required": [
        "success"
      ],
      "title": "CreateContactOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="update_contact — Update an existing contact in Loops by email or userId. Creates a new contact if no match is found (upsert). Can update name, subscription status, user group, mailing lists, and custom properties.">
    ### Parameters

    <ResponseField name="email" type="string">
      The contact email address (at least one of email or user\_id is required)
    </ResponseField>

    <ResponseField name="user_id" type="string">
      The contact userId (at least one of email or user\_id is required)
    </ResponseField>

    <ResponseField name="first_name" type="string">
      The contact first name
    </ResponseField>

    <ResponseField name="last_name" type="string">
      The contact last name
    </ResponseField>

    <ResponseField name="source" type="string">
      Custom source value replacing the default "API"
    </ResponseField>

    <ResponseField name="subscribed" type="boolean">
      Whether the contact receives campaign emails (sending true re-subscribes unsubscribed contacts)
    </ResponseField>

    <ResponseField name="user_group" type="string">
      Group to segment the contact into (one group per contact)
    </ResponseField>

    <ResponseField name="mailing_lists" type="object">
      Mailing list IDs mapped to boolean values (true to subscribe, false to unsubscribe)
    </ResponseField>

    <ResponseField name="custom_properties" type="object">
      Custom contact properties as key-value pairs (send null to reset a property)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Id"
        }
      },
      "required": [
        "success"
      ],
      "title": "UpdateContactOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="find_contact — Find a contact in Loops by email address or userId. Returns an array of matching contacts with all their properties including name, subscription status, user group, and mailing lists.">
    ### Parameters

    <ResponseField name="email" type="string">
      The contact email address to search for (at least one of email or user\_id is required)
    </ResponseField>

    <ResponseField name="user_id" type="string">
      The contact userId to search for (at least one of email or user\_id is required)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "$defs": {
        "Contact": {
          "additionalProperties": false,
          "description": "A single contact row in ``find_contact``.",
          "properties": {
            "id": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Id"
            },
            "email": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Email"
            },
            "first_name": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "First Name"
            },
            "last_name": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Last Name"
            },
            "source": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Source"
            },
            "subscribed": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Subscribed"
            },
            "user_group": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "User Group"
            },
            "user_id": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "User Id"
            },
            "mailing_lists": {
              "additionalProperties": true,
              "title": "Mailing Lists",
              "type": "object"
            },
            "opt_in_status": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Opt In Status"
            }
          },
          "title": "Contact",
          "type": "object"
        }
      },
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "contacts": {
          "items": {
            "$ref": "#/$defs/Contact"
          },
          "title": "Contacts",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "FindContactOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="delete_contact — Delete a contact from Loops by email address or userId. At least one identifier must be provided.">
    ### Parameters

    <ResponseField name="email" type="string">
      The email address of the contact to delete (at least one of email or user\_id is required)
    </ResponseField>

    <ResponseField name="user_id" type="string">
      The userId of the contact to delete (at least one of email or user\_id is required)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "message": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Message"
        }
      },
      "required": [
        "success"
      ],
      "title": "DeleteContactOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="send_transactional_email — Send a transactional email to a recipient using a Loops template. Supports dynamic data variables for personalization and optionally adds the recipient to your audience.">
    ### Parameters

    <ResponseField name="email" type="string" required>
      The email address of the recipient
    </ResponseField>

    <ResponseField name="transactional_id" type="string" required>
      The ID of the transactional email template to send
    </ResponseField>

    <ResponseField name="data_variables" type="object">
      Template data variables as key-value pairs (string or number values)
    </ResponseField>

    <ResponseField name="add_to_audience" type="boolean">
      Whether to create the recipient as a contact if they do not already exist (default: false)
    </ResponseField>

    <ResponseField name="attachments" type="array">
      Array of file attachments. Each object must have filename (string), contentType (MIME type string), and data (base64-encoded string).
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        }
      },
      "required": [
        "success"
      ],
      "title": "SendTransactionalEmailOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="send_event — Send an event to Loops to trigger automated email sequences for a contact. Identify the contact by email or userId and include optional event properties and mailing list changes.">
    ### Parameters

    <ResponseField name="event_name" type="string" required>
      The name of the event to trigger
    </ResponseField>

    <ResponseField name="email" type="string">
      The email address of the contact (at least one of email or user\_id is required)
    </ResponseField>

    <ResponseField name="user_id" type="string">
      The userId of the contact (at least one of email or user\_id is required)
    </ResponseField>

    <ResponseField name="event_properties" type="object">
      Event data as key-value pairs (string, number, boolean, or date values)
    </ResponseField>

    <ResponseField name="mailing_lists" type="object">
      Mailing list IDs mapped to boolean values (true to subscribe, false to unsubscribe)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        }
      },
      "required": [
        "success"
      ],
      "title": "SendEventOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_mailing_lists — Retrieve all mailing lists from your Loops account. Returns each list with its ID, name, description, and public/private status.">
    ### Response

    ```json theme={null}
    {
      "$defs": {
        "MailingList": {
          "additionalProperties": false,
          "description": "A single mailing list row in ``list_mailing_lists``.",
          "properties": {
            "id": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Id"
            },
            "name": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Name"
            },
            "description": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Description"
            },
            "is_public": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Is Public"
            }
          },
          "title": "MailingList",
          "type": "object"
        }
      },
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "mailing_lists": {
          "items": {
            "$ref": "#/$defs/MailingList"
          },
          "title": "Mailing Lists",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "ListMailingListsOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_transactional_emails — Retrieve a list of published transactional email templates from your Loops account. Returns each template with its ID, name, last updated timestamp, and data variables.">
    ### Parameters

    <ResponseField name="per_page" type="string">
      Number of results per page (10-50, default: 20)
    </ResponseField>

    <ResponseField name="cursor" type="string">
      Pagination cursor from a previous response to fetch the next page
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "$defs": {
        "Pagination": {
          "additionalProperties": false,
          "description": "Pagination block returned by ``list_transactional_emails``.",
          "properties": {
            "total_results": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Total Results"
            },
            "returned_results": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Returned Results"
            },
            "per_page": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Per Page"
            },
            "total_pages": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Total Pages"
            },
            "next_cursor": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Next Cursor"
            },
            "next_page": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Next Page"
            }
          },
          "title": "Pagination",
          "type": "object"
        },
        "TransactionalEmail": {
          "additionalProperties": false,
          "description": "A single template row in ``list_transactional_emails``.",
          "properties": {
            "id": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Id"
            },
            "name": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Name"
            },
            "last_updated": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Last Updated"
            },
            "data_variables": {
              "items": {
                "type": "string"
              },
              "title": "Data Variables",
              "type": "array"
            }
          },
          "title": "TransactionalEmail",
          "type": "object"
        }
      },
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "transactional_emails": {
          "items": {
            "$ref": "#/$defs/TransactionalEmail"
          },
          "title": "Transactional Emails",
          "type": "array"
        },
        "pagination": {
          "anyOf": [
            {
              "$ref": "#/$defs/Pagination"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "required": [
        "success"
      ],
      "title": "ListTransactionalEmailsOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="create_contact_property — Create a new custom contact property in your Loops account. The property name must be in camelCase format.">
    ### Parameters

    <ResponseField name="name" type="string" required>
      The property name in camelCase format (e.g., "favoriteColor")
    </ResponseField>

    <ResponseField name="type" type="string" required>
      The property data type (e.g., "string", "number", "boolean", "date")
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        }
      },
      "required": [
        "success"
      ],
      "title": "CreateContactPropertyOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_contact_properties — Retrieve a list of contact properties from your Loops account. Returns each property with its key, label, and data type. Can filter to show all properties or only custom ones.">
    ### Parameters

    <ResponseField name="list" type="string">
      Filter type: "all" for all properties (default) or "custom" for custom properties only
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "$defs": {
        "ContactProperty": {
          "additionalProperties": false,
          "description": "A single property row in ``list_contact_properties``.",
          "properties": {
            "key": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Key"
            },
            "label": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Label"
            },
            "type": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": null,
              "title": "Type"
            }
          },
          "title": "ContactProperty",
          "type": "object"
        }
      },
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "properties": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ContactProperty"
          },
          "title": "Properties"
        }
      },
      "required": [
        "success"
      ],
      "title": "ListContactPropertiesOutput",
      "type": "object"
    }
    ```
  </Accordion>
</AccordionGroup>

## Limits & Quotas

* Loops applies per-account API rate limits; check your plan in the
  Loops dashboard for current values.
* `list_transactional_emails` accepts `per_page` (10-50, default 20)
  and a `cursor` for pagination; the response carries a `pagination`
  block with `next_cursor`/`next_page` for fetching subsequent pages.
* **Error model**: non-2xx responses and timeouts are caught and
  returned as `success=False` + `error` rather than raising. Mutating
  endpoints also return HTTP 200 with `{"success": false, "message":
  ...}` for business-logic failures, which is surfaced as `error`.

## Related integrations

<CardGroup cols={3}>
  <Card title="Klaviyo" href="/integrations/tools/klaviyo" />

  <Card title="SendGrid" href="/integrations/tools/sendgrid" />

  <Card title="AgentMail" href="/integrations/tools/agentmail" />
</CardGroup>

## Links

* [Loops](https://loops.so)
