openapi: 3.1.0
info:
  title: Loops OpenAPI Spec
  description: This is the OpenAPI Spec for the [Loops API](https://loops.so/docs/api).
  version: 1.8.0
servers:
  - url: https://app.loops.so/api/v1
tags:
  - name: API key
  - name: Contacts
    description: Manage contacts in your audience
  - name: Contact properties
    description: Manage contact properties
  - name: Mailing lists
    description: View mailing lists
  - name: Events
    description: Trigger email sending with events
  - name: Transactional emails
    description: Send and view transactional emails
  - name: Dedicated sending IPs
    description: View dedicated sending IP addresses
paths:
  /api-key:
    get:
      tags:
        - API key
      summary: Test your API key
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    examples:
                      - true
                  teamName:
                    type: string
                    description: The name of the team the API key belongs to.
                    examples:
                      - "Company name"
                required:
                  - success
                  - teamName
        "401":
          description: Invalid API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    examples:
                      - false
                  message:
                    type: string
                    examples:
                      - Invalid API key
                  error:
                    type: string
                    examples:
                      - Invalid API key
      security:
        - apiKey: []
  /contacts/create:
    post:
      tags:
        - Contacts
      summary: Create a contact
      description: Add a contact to your audience.
      requestBody:
        description: You can add custom contact properties as keys in this request (of type `string`, `number`, `boolean` or `date` ([see available date formats](https://loops.so/docs/contacts/properties#dates))).<br>Make sure to create the properties in Loops before using them in API calls.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactRequest"
        required: true
      responses:
        "200":
          description: Successful create.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuccessResponse"
        "400":
          description: Bad request (e.g. invalid email address).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Email or `userId` already exists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
      security:
        - apiKey: []
  /contacts/update:
    put:
      tags:
        - Contacts
      summary: Update a contact
      description: Update a contact by `email` or `userId`. You must provide one of these parameters.<br>If you want to update a contact’s email address, the contact will first need a `userId` value. You can then make a request containing the userId field along with an updated email address.
      requestBody:
        description: You can add custom contact properties as keys in this request (of type `string`, `number`, `boolean` or `date` ([see available date formats](https://loops.so/docs/contacts/properties#dates))).<br>Make sure to create the properties in Loops before using them in API calls.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactUpdateRequest"
        required: true
      responses:
        "200":
          description: Successful update.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuccessResponse"
        "400":
          description: Bad request (e.g. `email` or `userId` are missing).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /contacts/find:
    get:
      tags:
        - Contacts
      summary: Find a contact
      description: Search for a contact by `email` or `userId`. Only one parameter is allowed.
      parameters:
        - name: email
          in: query
          required: false
          description: Email address (URI-encoded)
          schema:
            type: string
        - name: userId
          in: query
          required: false
          schema:
            type: string
      responses:
        "200":
          description: List of contacts (or an empty array if no contact was found). Contact objects will include any custom properties.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Contact"
        "400":
          description: Bad request (e.g. invalid email address).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /contacts/delete:
    post:
      tags:
        - Contacts
      summary: Delete a contact
      description: Delete a contact by `email` or `userId`.
      requestBody:
        description: Include only one of `email` or `userId`.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactDeleteRequest"
        required: true
      responses:
        "200":
          description: Successful delete.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactDeleteResponse"
        "400":
          description: Bad request (e.g. `email` and `userId` are both provided).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "404":
          description: Contact not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /contacts/suppression:
    get:
      tags:
        - Contacts
      summary: Get suppression status for a contact
      description: Retrieve suppression status and removal quota for a contact by `email` or `userId`. Include only one query parameter.
      parameters:
        - name: email
          in: query
          required: false
          description: Email address (URI-encoded)
          schema:
            type: string
        - name: userId
          in: query
          required: false
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuppressionStatusResponse"
        "400":
          description: Bad request (e.g. invalid email address).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "404":
          description: Contact not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    delete:
      tags:
        - Contacts
      summary: Remove a contact from suppression list
      description: Remove a suppressed contact from the suppression list by `email` or `userId`. Include only one query parameter.
      parameters:
        - name: email
          in: query
          required: false
          description: Email address (URI-encoded)
          schema:
            type: string
        - name: userId
          in: query
          required: false
          schema:
            type: string
      responses:
        "200":
          description: Successful removal.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactSuppressionRemoveResponse"
        "400":
          description: Bad request (e.g. contact is not suppressed).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "404":
          description: Contact not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /contacts/properties:
    post:
      tags:
        - Contact properties
      summary: Create a contact property
      description: Add a contact property to your team.
      requestBody:
        description: The name value must be in camelCase, like `planName`.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ContactPropertyCreateRequest"
        required: true
      responses:
        "200":
          description: Successful create.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactPropertySuccessResponse"
        "400":
          description: Bad request (e.g. invalid type).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContactPropertyFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    get:
      tags:
        - Contact properties
      summary: Get a list of contact properties
      description: Retrieve a list of your account's contact properties.<br>Use the `list` parameter to query "all" or "custom" properties.
      parameters:
        - name: list
          in: query
          required: false
          description: \"all\" (default) or \"custom\"
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ContactProperty"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /dedicated-sending-ips:
    get:
      tags:
        - Dedicated sending IPs
      summary: Get dedicated sending IP addresses
      description: Retrieve a list of Loops' dedicated sending IP addresses.
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                type: array
                description: List of dedicated sending IP addresses
                items:
                  type: string
                  description: IP address
                  examples:
                    - "1.2.3.4"
        "405":
          description: Wrong HTTP request method.
        "500":
          description: Internal server error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                required:
                  - success
                  - message
      security:
        - apiKey: []
  /lists:
    get:
      tags:
        - Mailing lists
      summary: Get a list of mailing lists
      description: Retrieve a list of your account's mailing lists.
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MailingList"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /events/send:
    post:
      tags:
        - Events
      summary: Send an event
      description: Send events to trigger emails in Loops.
      requestBody:
        description: Provide either `email` or `userId` to identify the contact ([read more](https://loops.so/docs/api-reference/send-event#body)).<br>You can add event properties, which will be available in emails sent by this event. Values can be of type string, number, boolean or date ([see allowed date formats](https://loops.so/docs/events/properties#important-information-about-event-properties)).<br>Make sure to create the properties in Loops before using them in API calls.<br>You can add contact properties as keys in this request (of type `string`, `number`, `boolean` or `date` ([see available date formats](https://loops.so/docs/contacts/properties#dates))).
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EventRequest"
        required: true
      parameters:
        - in: header
          name: Idempotency-Key
          description: Include a unique ID for this request (maximum 100 characters) to avoid duplicate events. [More info](https://loops.so/docs/api-reference/send-event#param-idempotency-key)
          schema:
            type: string
            maxLength: 100
      responses:
        "200":
          description: Successful send.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventSuccessResponse"
        "400":
          description: Bad request (e.g. `eventName` is missing).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Idempotency key has been used.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdempotencyKeyFailureResponse"
      security:
        - apiKey: []
  /transactional:
    post:
      tags:
        - Transactional emails
      summary: Send a transactional email
      description: Send a transactional email to a contact.<br>Please [email us](mailto:help@loops.so) to enable attachments on your account before using them with the API.
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TransactionalRequest"
        required: true
      parameters:
        - in: header
          name: Idempotency-Key
          description: Include a unique ID for this request (maximum 100 characters) to avoid duplicate emails. [More info](https://loops.so/docs/api-reference/send-transactional-email#param-idempotency-key)
          schema:
            type: string
            maxLength: 100
      responses:
        "200":
          description: Successful send.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalSuccessResponse"
        "400":
          description: Bad request (e.g. transactional email is not published).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/TransactionalFailureResponse"
                  - $ref: "#/components/schemas/TransactionalFailure2Response"
                  - $ref: "#/components/schemas/TransactionalFailure3Response"
                  - $ref: "#/components/schemas/TransactionalFailure4Response"
                  - $ref: "#/components/schemas/TransactionalFailure5Response"
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailure3Response"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Idempotency key has been used.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdempotencyKeyFailureResponse"
      security:
        - apiKey: []
    get:
      tags:
        - Transactional emails
      summary: List transactional emails
      description: Get a list of published transactional emails.
      parameters:
        - name: perPage
          in: query
          required: false
          description: How many results to return in each request. Must be between 10 and 50. Default is 20.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response.
          schema:
            type: string
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListTransactionalsResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
components:
  schemas:
    Contact:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
        firstName:
          type:
            - string
            - "null"
        lastName:
          type:
            - string
            - "null"
        source:
          type: string
        subscribed:
          type: boolean
        userGroup:
          type: string
        userId:
          type:
            - string
            - "null"
        mailingLists:
          type: object
          description: An object of mailing list IDs and boolean subscription statuses.
          examples:
            - list_123: true
        optInStatus:
          type:
            - string
            - "null"
          description: Double opt-in status.
          enum: [accepted, pending, rejected, null]
    ContactRequest:
      type: object
      required:
        - email
      properties:
        email:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        subscribed:
          type: boolean
        userGroup:
          type: string
        userId:
          type: string
        mailingLists:
          type: object
          description: An object of mailing list IDs and boolean subscription statuses.
          examples:
            - list_123: true
      additionalProperties:
        oneOf:
          - type: string
          - type: number
          - type: boolean
    ContactUpdateRequest:
      type: object
      properties:
        email:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        subscribed:
          type: boolean
        userGroup:
          type: string
        userId:
          type: string
        mailingLists:
          type: object
          description: An object of mailing list IDs and boolean subscription statuses.
          examples:
            - list_123: true
      additionalProperties:
        oneOf:
          - type: string
          - type: number
          - type: boolean
    ContactSuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
        id:
          type: string
      required:
        - success
        - id
    ContactFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
      required:
        - success
        - message
    ContactDeleteRequest:
      type: object
      properties:
        email:
          type: string
        userId:
          type: string
      required:
        - email
        - userId
    ContactDeleteResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
        message:
          type: string
          examples:
            - Contact deleted.
      required:
        - success
        - message
    ContactSuppressionStatusResponse:
      type: object
      properties:
        contact:
          type: object
          properties:
            id:
              type: string
            email:
              type: string
            userId:
              type:
                - string
                - "null"
          required:
            - id
            - email
            - userId
        isSuppressed:
          type: boolean
        removalQuota:
          $ref: "#/components/schemas/ContactSuppressionRemovalQuota"
      required:
        - contact
        - isSuppressed
        - removalQuota
    ContactSuppressionRemoveResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
        message:
          type: string
          examples:
            - Email removed from suppression list.
        removalQuota:
          $ref: "#/components/schemas/ContactSuppressionRemovalQuota"
      required:
        - success
        - message
        - removalQuota
    ContactSuppressionRemovalQuota:
      type: object
      properties:
        limit:
          type: number
        remaining:
          type: number
      required:
        - limit
        - remaining
    ContactPropertyCreateRequest:
      type: object
      required:
        - name
        - type
      properties:
        name:
          type: string
        type:
          type: string
    ContactPropertySuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
      required:
        - success
    ContactPropertyFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
      required:
        - success
        - message
    EventRequest:
      type: object
      required:
        - eventName
      properties:
        email:
          type: string
        userId:
          type: string
        eventName:
          type: string
        eventProperties:
          type: object
          description: An object containing event property data for the event, available in emails sent by the event.
        mailingLists:
          type: object
          description: An object of mailing list IDs and boolean subscription statuses.
          examples:
            - list_123: true
      additionalProperties:
        oneOf:
          - type: string
          - type: number
          - type: boolean
    EventSuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
      required:
        - success
    EventFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
      required:
        - success
        - message
    TransactionalRequest:
      type: object
      required:
        - email
        - transactionalId
      properties:
        email:
          type: string
        transactionalId:
          type: string
          description: The ID of the transactional email to send.
        addToAudience:
          type: boolean
          description: If `true`, a contact will be created in your audience using the `email` value (if a matching contact doesn't already exist).
        dataVariables:
          type: object
          description: An object containing contact data as defined by the data variables added to the transactional email template.
          examples:
            - name: Chris
              passwordResetLink: https://example.com/reset-password
        attachments:
          type: array
          description: A list containing file objects to be sent along with an email message.
          items:
            type: object
            required:
              - filename
              - contentType
              - data
            properties:
              filename:
                type: string
                description: The name of the file, shown in email clients.
              contentType:
                type: string
                description: The MIME type of the file.
              data:
                type: string
                description: The base64-encoded content of the file.
    TransactionalSuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - true
      required:
        - success
    TransactionalFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
      required:
        - success
        - message
    TransactionalFailure2Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        path:
          type: string
      required:
        - success
        - message
        - path
    TransactionalFailure3Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        error:
          type: object
          properties:
            path:
              type: string
            message:
              type: string
      required:
        - success
        - message
        - error
    TransactionalFailure4Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        error:
          type: object
          properties:
            path:
              type: string
            reason:
              type: string
      required:
        - success
        - message
        - error
    TransactionalFailure5Response:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
        error:
          type: object
          properties:
            path:
              type: string
            message:
              type: string
        transactionalId:
          type: string
      required:
        - success
        - message
        - error
        - transactionalId
    IdempotencyKeyFailureResponse:
      type: object
      properties:
        success:
          type: boolean
          examples:
            - false
        message:
          type: string
      required:
        - success
        - message
    TransactionalEmail:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        lastUpdated:
          type: string
        dataVariables:
          type: array
      examples:
        - id: cll42l54f20i1la0lfooe3z12
          name: Sign up confirmation
          lastUpdated: "2025-02-02T02:56:28.845Z"
          dataVariables: ["confirmationUrl"]
      required:
        - id
        - name
        - lastUpdated
        - dataVariables
    ListTransactionalsResponse:
      type: object
      properties:
        pagination:
          type: object
          properties:
            totalResults:
              type: number
            returnedResults:
              type: number
            perPage:
              type: number
            totalPages:
              type: number
            nextCursor:
              type:
                - string
                - "null"
            nextPage:
              type:
                - string
                - "null"
        data:
          type: array
          items:
            $ref: "#/components/schemas/TransactionalEmail"
    ContactProperty:
      type: object
      properties:
        key:
          type: string
        label:
          type: string
        type:
          type: string
      examples:
        - key: favoriteColor
          label: Favorite color
          type: string
      required:
        - key
        - label
        - type
    MailingList:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        isPublic:
          type: boolean
      examples:
        - id: list_123
          name: Main mailing list
          description: Mailing list description
          isPublic: true
      required:
        - id
        - name
        - description
        - isPublic
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
