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.11.0
servers:
  - url: https://app.loops.so/api
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: Campaigns
    description: Create and manage email campaigns
  - name: Email messages
    description: Manage email message content for campaigns
  - name: Uploads
    description: Upload image assets
  - name: Themes
    description: View email themes
  - name: Components
    description: View email components
  - name: Events
    description: Trigger email sending with events
  - name: Transactional emails
    description: Create, manage, and send transactional emails
  - name: Dedicated sending IPs
    description: View dedicated sending IP addresses
paths:
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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: []
  /v1/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/TransactionalSendFailureResponse"
                  - $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:
      deprecated: true
      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: []
  /v1/transactional-emails:
    get:
      tags:
        - Transactional emails
      summary: List transactional emails
      description: Retrieve a paginated list of transactional emails, most recently created first.
      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/ListTransactionalsResourceResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      tags:
        - Transactional emails
      summary: Create a transactional email
      description:
        Create a new transactional email. An empty draft email message is created
        automatically and its `draftEmailMessageId` is returned. Use the
        `/api/v1/email-messages/{emailMessageId}` endpoint to set subject, sender,
        preview text, and LMX content, then call
        `/api/v1/transactional-emails/{transactionalId}/publish` to publish.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTransactionalRequest"
      responses:
        "201":
          description: Transactional email created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalDraftResponse"
        "400":
          description: Invalid request body or no sending domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  "/v1/transactional-emails/{transactionalId}":
    parameters:
      - name: transactionalId
        in: path
        required: true
        description: The ID of the transactional email.
        schema:
          type: string
    get:
      tags:
        - Transactional emails
      summary: Get a transactional email
      description: Retrieve a single transactional email by ID.
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalResponse"
        "400":
          description: Invalid `transactionalId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      tags:
        - Transactional emails
      summary: Update a transactional email
      description: Update a transactional email by ID.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateTransactionalRequest"
      responses:
        "200":
          description: Transactional email updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalResponse"
        "400":
          description: Invalid request body or `transactionalId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  "/v1/transactional-emails/{transactionalId}/draft":
    parameters:
      - name: transactionalId
        in: path
        required: true
        description: The ID of the transactional email.
        schema:
          type: string
    post:
      tags:
        - Transactional emails
      summary: Ensure a draft email message
      description:
        Ensure the transactional email has a draft email message. If a
        draft already exists it is returned unchanged; otherwise a new empty
        draft is created (seeded from the most recent published version when
        present). Use `/v1/email-messages/{emailMessageId}` to edit the draft's
        content.
      responses:
        "200":
          description: Draft ready.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalDraftResponse"
        "400":
          description: Invalid `transactionalId` or no sending domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  "/v1/transactional-emails/{transactionalId}/publish":
    parameters:
      - name: transactionalId
        in: path
        required: true
        description: The ID of the transactional email.
        schema:
          type: string
    post:
      tags:
        - Transactional emails
      summary: Publish a transactional email draft
      description:
        Publish the transactional email's current draft email message. The
        draft becomes the published version and the draft is cleared.
      responses:
        "200":
          description: Transactional email published.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalResponse"
        "400":
          description: Invalid `transactionalId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Transactional email not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: No draft to publish.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
        "422":
          description:
            Draft failed validation, sending domain is not verified, or content
            was flagged as unsafe.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionalFailureResponse"
      security:
        - apiKey: []
  "/v1/themes/{themeId}":
    parameters:
      - name: themeId
        in: path
        required: true
        description: The ID of the theme.
        schema:
          type: string
    get:
      tags:
        - Themes
      summary: Get a theme
      description: Retrieve a single theme by ID.
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeResponse"
        "400":
          description: Invalid `themeId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Theme not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/themes:
    get:
      tags:
        - Themes
      summary: List themes
      description: Retrieve a paginated list of email themes, most recently created first.
      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/ListThemesResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemeFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  "/v1/components/{componentId}":
    parameters:
      - name: componentId
        in: path
        required: true
        description: The ID of the component.
        schema:
          type: string
    get:
      tags:
        - Components
      summary: Get a component
      description: Retrieve a single component by ID.
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentResponse"
        "400":
          description: Invalid `componentId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Component not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/components:
    get:
      tags:
        - Components
      summary: List components
      description: Retrieve a paginated list of email components.
      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/ListComponentsResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  /v1/campaigns:
    get:
      tags:
        - Campaigns
      summary: List campaigns
      description: Retrieve a paginated list of campaigns.
      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/ListCampaignsResponse"
        "400":
          description: Invalid `perPage` value.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      tags:
        - Campaigns
      summary: Create a campaign
      description:
        Create a new draft campaign. An empty email message is created
        automatically and its `emailMessageId` is returned. Use the
        `/email-messages/{emailMessageId}` endpoint to set subject, sender,
        preview text, and LMX content.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateCampaignRequest"
      responses:
        "201":
          description: Campaign created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateCampaignResponse"
        "400":
          description: Invalid request body or no sending domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
  "/v1/campaigns/{campaignId}":
    parameters:
      - name: campaignId
        in: path
        required: true
        description: The ID of the campaign.
        schema:
          type: string
    get:
      tags:
        - Campaigns
      summary: Get a campaign
      description: Retrieve a single campaign by ID.
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignResponse"
        "400":
          description: Invalid `campaignId`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Campaign not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "405":
          description: Wrong HTTP request method.
      security:
        - apiKey: []
    post:
      tags:
        - Campaigns
      summary: Update a campaign
      description:
        Update a draft campaign's name. Campaigns can only be updated while
        in draft status.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateCampaignRequest"
      responses:
        "200":
          description: Campaign updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignResponse"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Campaign not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Campaign is not in draft status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignFailureResponse"
      security:
        - apiKey: []
  "/v1/email-messages/{emailMessageId}":
    parameters:
      - name: emailMessageId
        in: path
        required: true
        description: The ID of the email message.
        schema:
          type: string
    get:
      tags:
        - Email messages
      summary: Get an email message
      description: Retrieve an email message, including its compiled LMX content.
      responses:
        "200":
          description: Successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageResponse"
        "400":
          description: Invalid `emailMessageId` or no sending domain configured.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Email message not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description: Email message uses MJML format or content cannot be parsed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
      security:
        - apiKey: []
    post:
      tags:
        - Email messages
      summary: Update an email message
      description:
        Update fields on an email message (subject, preview text, sender,
        LMX content). The campaign must be in draft status. Supply
        `expectedRevisionId` matching the current `contentRevisionId` — the
        server rejects mismatched revisions with 409.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateEmailMessageRequest"
      responses:
        "200":
          description: Email message updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageResponse"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Email message not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "405":
          description: Wrong HTTP request method.
        "409":
          description:
            Campaign is not in draft status, `contentRevisionId` is stale,
            content cannot be parsed, or email message uses MJML format.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "413":
          description: LMX payload exceeds the 100KB limit.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
        "422":
          description: LMX failed to compile.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmailMessageFailureResponse"
      security:
        - apiKey: []
  /v1/uploads:
    post:
      tags:
        - Uploads
      summary: Create an upload
      description:
        Request a pre-signed URL to upload an image asset. Upload the file
        with an HTTP `PUT` to the returned `presignedUrl` (sending the same
        `Content-Type` and `Content-Length`), then call `/uploads/{id}/complete`
        to finalize the asset.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateUploadRequest"
      responses:
        "200":
          description: Pre-signed upload URL created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateUploadResponse"
        "400":
          description: Invalid request body or unsupported `contentType`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "405":
          description: Wrong HTTP request method.
        "413":
          description: Upload exceeds the maximum allowed size.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
        "429":
          description: Upload limit exceeded.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadLimitExceededFailureResponse"
      security:
        - apiKey: []
  "/v1/uploads/{id}/complete":
    parameters:
      - name: id
        in: path
        required: true
        description: The `emailAssetId` returned when the upload was created.
        schema:
          type: string
    post:
      tags:
        - Uploads
      summary: Complete an upload
      description: Finalize an asset after the file has been uploaded to the
        pre-signed URL. Returns the public URL of the uploaded asset.
      responses:
        "200":
          description: Upload completed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CompleteUploadResponse"
        "400":
          description:
            Upload id is missing or the uploaded file has an unsupported
            content type.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
        "401":
          description: Invalid API key or content API not enabled for this team.
        "404":
          description: Upload not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadFailureResponse"
        "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:
        message:
          type: string
      required:
        - message
    TransactionalSendFailureResponse:
      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"
    TransactionalEmailResource:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        draftEmailMessageId:
          type:
            - string
            - "null"
        publishedEmailMessageId:
          type:
            - string
            - "null"
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        dataVariables:
          type: array
          description:
            Data variable names used by the published email. Empty for
            unpublished transactional emails.
          items:
            type: string
      required:
        - id
        - name
        - draftEmailMessageId
        - publishedEmailMessageId
        - createdAt
        - updatedAt
        - dataVariables
    TransactionalResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        draftEmailMessageId:
          type:
            - string
            - "null"
        publishedEmailMessageId:
          type:
            - string
            - "null"
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        dataVariables:
          type: array
          description:
            Data variable names used by the published email. Empty for
            unpublished transactional emails.
          items:
            type: string
      required:
        - id
        - name
        - draftEmailMessageId
        - publishedEmailMessageId
        - createdAt
        - updatedAt
        - dataVariables
    TransactionalDraftResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        draftEmailMessageId:
          type:
            - string
            - "null"
        draftEmailMessageContentRevisionId:
          type:
            - string
            - "null"
          description:
            The `contentRevisionId` of the draft email message. Pass this as
            `expectedRevisionId` on your first update via
            `/email-messages/{emailMessageId}`.
        publishedEmailMessageId:
          type:
            - string
            - "null"
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        dataVariables:
          type: array
          description:
            Data variable names used by the published email. Empty for
            unpublished transactional emails.
          items:
            type: string
      required:
        - id
        - name
        - draftEmailMessageId
        - draftEmailMessageContentRevisionId
        - publishedEmailMessageId
        - createdAt
        - updatedAt
        - dataVariables
    ListTransactionalsResourceResponse:
      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/TransactionalEmailResource"
      required:
        - pagination
        - data
    CreateTransactionalRequest:
      type: object
      properties:
        name:
          type: string
          description: The name of the transactional email.
          examples:
            - Welcome email
      required:
        - name
      additionalProperties: false
    UpdateTransactionalRequest:
      type: object
      properties:
        name:
          type: string
      required:
        - name
      additionalProperties: false
    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
    Theme:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        styles:
          $ref: "#/components/schemas/ThemeStyles"
        isDefault:
          type: boolean
          description: Whether this theme is the team's default.
        createdAt:
          type: string
          description: ISO 8601 timestamp.
        updatedAt:
          type: string
          description: ISO 8601 timestamp.
      required:
        - id
        - name
        - styles
        - isDefault
        - createdAt
        - updatedAt
    ThemeStyles:
      type: object
      description:
        Flat map of style attributes, matching the attribute names accepted
        by the LMX `<Style />` tag. All attributes are returned with the values
        stored on the theme.
      properties:
        backgroundColor:
          type: string
        backgroundXPadding:
          type: number
        backgroundYPadding:
          type: number
        bodyColor:
          type: string
        bodyXPadding:
          type: number
        bodyYPadding:
          type: number
        bodyFontFamily:
          type: string
        bodyFontCategory:
          type: string
        borderColor:
          type: string
        borderWidth:
          type: number
        borderRadius:
          type: number
        buttonBodyColor:
          type: string
        buttonBodyXPadding:
          type: number
        buttonBodyYPadding:
          type: number
        buttonBorderColor:
          type: string
        buttonBorderWidth:
          type: number
        buttonBorderRadius:
          type: number
        buttonTextColor:
          type: string
        buttonTextFormat:
          type: number
        buttonTextFontSize:
          type: number
        dividerColor:
          type: string
        dividerBorderWidth:
          type: number
        textBaseColor:
          type: string
        textBaseFontSize:
          type: number
        textBaseLineHeight:
          type: number
        textBaseLetterSpacing:
          type: number
        textLinkColor:
          type: string
        heading1Color:
          type: string
        heading1FontSize:
          type: number
        heading1LineHeight:
          type: number
        heading1LetterSpacing:
          type: number
        heading2Color:
          type: string
        heading2FontSize:
          type: number
        heading2LineHeight:
          type: number
        heading2LetterSpacing:
          type: number
        heading3Color:
          type: string
        heading3FontSize:
          type: number
        heading3LineHeight:
          type: number
        heading3LetterSpacing:
          type: number
    ListThemesResponse:
      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/Theme"
      required:
        - pagination
        - data
    ThemeResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        styles:
          $ref: "#/components/schemas/ThemeStyles"
        isDefault:
          type: boolean
          description: Whether this theme is the team's default.
        createdAt:
          type: string
          description: ISO 8601 timestamp.
        updatedAt:
          type: string
          description: ISO 8601 timestamp.
      required:
        - id
        - name
        - styles
        - isDefault
        - createdAt
        - updatedAt
    ThemeFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
    Component:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        lmx:
          type: string
          description: The component body serialized as LMX.
      required:
        - id
        - name
        - lmx
    ListComponentsResponse:
      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/Component"
      required:
        - pagination
        - data
    ComponentResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        lmx:
          type: string
          description: The component body serialized as LMX.
      required:
        - id
        - name
        - lmx
    ComponentFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
    CampaignListItem:
      type: object
      properties:
        id:
          type: string
        emailMessageId:
          type:
            - string
            - "null"
        name:
          type: string
        subject:
          type: string
        status:
          type: string
          description: Campaign lifecycle status.
          examples:
            - Draft
            - Scheduled
            - Sending
            - Sent
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - emailMessageId
        - name
        - subject
        - status
        - createdAt
        - updatedAt
    ListCampaignsResponse:
      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/CampaignListItem"
      required:
        - pagination
        - data
    CreateCampaignRequest:
      type: object
      properties:
        name:
          type: string
          description: The campaign name.
          examples:
            - Spring announcement
      required:
        - name
      additionalProperties: false
    CreateCampaignResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        status:
          type: string
          examples:
            - Draft
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        emailMessageId:
          type: string
          description:
            The ID of the empty email message created for this campaign. Use
            `/email-messages/{emailMessageId}` to set its fields and LMX
            content.
        emailMessageContentRevisionId:
          type:
            - string
            - "null"
          description:
            The `contentRevisionId` of the newly created email message. Pass
            this as `expectedRevisionId` on your first update.
      required:
        - id
        - name
        - status
        - createdAt
        - updatedAt
        - emailMessageId
        - emailMessageContentRevisionId
    UpdateCampaignRequest:
      type: object
      properties:
        name:
          type: string
      required:
        - name
      additionalProperties: false
    CampaignResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        status:
          type: string
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        emailMessageId:
          type:
            - string
            - "null"
      required:
        - id
        - name
        - status
        - createdAt
        - updatedAt
        - emailMessageId
    CampaignFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
    UpdateEmailMessageRequest:
      type: object
      properties:
        expectedRevisionId:
          type: string
          description:
            The `contentRevisionId` you last fetched. Used for optimistic
            concurrency — the request is rejected with 409 if the server's
            revision has advanced.
        subject:
          type: string
        previewText:
          type: string
        fromName:
          type: string
        fromEmail:
          type: string
          description:
            The sender username (without `@` or domain). The team's sending
            domain is appended automatically.
        replyToEmail:
          type: string
          description: Reply-to email. Must be empty or a valid email address.
        lmx:
          type: string
          description:
            The email body serialized as LMX. Styles must be embedded in the
            LMX `<Style />` tag.
      additionalProperties: false
    EmailMessageResponse:
      type: object
      properties:
        id:
          type: string
        campaignId:
          type:
            - string
            - "null"
        subject:
          type: string
        previewText:
          type: string
        fromName:
          type: string
        fromEmail:
          type: string
        replyToEmail:
          type: string
        lmx:
          type: string
          description: The email body serialized as LMX.
        contentRevisionId:
          type:
            - string
            - "null"
          description:
            The current content revision. Pass this as `expectedRevisionId` on
            your next update.
        updatedAt:
          type: string
          format: date-time
        warnings:
          type: array
          description:
            Non-fatal issues raised while compiling the submitted LMX. Only
            present on update responses when warnings were produced.
          items:
            type: object
            properties:
              rule:
                type: string
              severity:
                type: string
                enum:
                  - warning
              message:
                type: string
              path:
                type: string
            required:
              - rule
              - severity
              - message
      required:
        - id
        - campaignId
        - subject
        - previewText
        - fromName
        - fromEmail
        - replyToEmail
        - lmx
        - contentRevisionId
        - updatedAt
    EmailMessageFailureResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
    CreateUploadRequest:
      type: object
      properties:
        contentType:
          type: string
          description: The MIME type of the file to upload. Supported types are
            `image/jpeg`, `image/png`, `image/gif` and `image/webp`.
          examples:
            - image/png
        contentLength:
          type: integer
          description:
            The size of the file in bytes. Must be a positive integer no
            greater than 4,000,000 bytes.
          examples:
            - 102400
      required:
        - contentType
        - contentLength
      additionalProperties: false
    CreateUploadResponse:
      type: object
      properties:
        emailAssetId:
          type: string
          description: The ID of the created asset. Pass this as `id` to
            `/uploads/{id}/complete` once the file has been uploaded.
        presignedUrl:
          type: string
          description:
            The pre-signed URL to upload the file to with an HTTP `PUT`
            request. Send the same `Content-Type` and `Content-Length` used in
            the create request.
      required:
        - emailAssetId
        - presignedUrl
    CompleteUploadResponse:
      type: object
      properties:
        emailAssetId:
          type: string
        finalUrl:
          type: string
          description: The public URL of the uploaded asset.
      required:
        - emailAssetId
        - finalUrl
    UploadLimitExceededFailureResponse:
      type: object
      properties:
        message:
          type: string
          examples:
            - "Upload limit exceeded: max 50 uploads per 24 hours. Please
              contact support if you need to increase your upload limit."
        maxUploads:
          type: integer
          description: The maximum number of uploads allowed per window.
          examples:
            - 50
        windowHours:
          type: integer
          description: The number of hours in the upload limit window.
          examples:
            - 24
    UploadFailureResponse:
      type: object
      properties:
        message:
          type: string
        supportedContentTypes:
          type: array
          description: Present when the request was rejected for an unsupported
            `contentType`. Lists the accepted MIME types.
          items:
            type: string
        maxBytes:
          type: integer
          description:
            Present when the upload exceeds the size limit. The maximum allowed
            size in bytes.
      required:
        - message
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
