Omnisend EmailUniversalLayouts API

The EmailUniversalLayouts API from Omnisend — 5 operation(s) for emailuniversallayouts. Version 2026-03-15, harvested from Omnisend's published contract.

OpenAPI Specification

omnisend-emailuniversallayouts-api-openapi.yml Raw ↑
openapi: 3.0.0
info:
  contact: {}
  description: API for managing email content, templates and universal layouts
  title: Email Universal Layouts API
  version: '5.0'
  x-api-evangelist:
    harvested: '2026-08-13'
    method: searched
    source: https://dash.readme.com/api/v1/api-registry/9c1ckrq8msfxryye
    source-note: Published by Omnisend on its own docs host api-docs.omnisend.com (ReadMe project @omnisend,
      branch v2026-03-15); registry document referenced by the reference page as oasPublicUrl.
paths:
  /email-universal-layouts:
    get:
      description: 'With this endpoint you can get a paginated list of universal layouts.


        **Sorting:**

        Items are returned in descending order by creation time (newest first).

        This is based on the internal document ID which contains a timestamp.


        **Pagination:**

        This endpoint uses cursor-based pagination for efficient traversal of large datasets.

        - Use the `paging.cursors.after` value from the response to get the next page

        - Use the `paging.cursors.before` value from the response to get the previous page

        - The `paging.hasMore` field indicates if more results are available

        - Do not use both `after` and `before` parameters simultaneously

        - Maximum page size is 250 items (default 100)

        - If `limit` is less than 1 or greater than 250, returns 400 Bad Request


        **Filtering:**

        Use `nameContains` to filter layouts by name (case-insensitive partial match, max 200 characters)


        **Scopes:**

        `email-templates.read`


        **Rate Limiting:**

        This endpoint is rate limited to 400 requests per minute.'
      parameters:
      - description: Number of items per page (1-250, default 100)
        in: query
        name: limit
        schema:
          type: integer
          minimum: 1
          maximum: 250
      - description: Cursor for next page (base64-encoded, from previous response)
        in: query
        name: after
        schema:
          type: string
      - description: Cursor for previous page (base64-encoded, from previous response)
        in: query
        name: before
        schema:
          type: string
      - description: Filter layouts by name (case-insensitive partial match, max 200 characters)
        in: query
        name: nameContains
        schema:
          type: string
          maxLength: 200
      - $ref: '#/components/parameters/APIVersionHeader'
      responses:
        '200':
          description: List of universal layouts with pagination
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListUniversalLayoutsResponse'
        '400':
          description: Invalid query parameters or missing brand ID
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '401':
          description: Authentication is missing or invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '403':
          description: Insufficient permissions for this operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '410':
          description: API version has been retired
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '500':
          description: Unexpected error occurred
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
      security:
      - Bearer:
        - email-templates.read
      - ApiKeyAuth: []
      summary: Get universal layouts
      tags:
      - Email Universal Layouts
    post:
      description: 'With this endpoint you can create a new universal layout.


        **Scopes:**

        `email-templates.write`


        **Rate Limiting:**

        This endpoint is rate limited to 400 requests per minute.'
      parameters:
      - $ref: '#/components/parameters/APIVersionHeader'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UniversalLayout'
        description: Universal layout to create
        required: true
      responses:
        '201':
          description: Created Universal Layout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UniversalLayout'
        '400':
          description: Invalid request body, missing brand ID, invalid layout structure, or validation
            errors
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '401':
          description: Authentication is missing or invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '403':
          description: Insufficient permissions for this operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '410':
          description: API version has been retired
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '413':
          description: Request body too large - exceeds 1 MB limit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '500':
          description: Unexpected error occurred
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
      security:
      - Bearer:
        - email-templates.write
      - ApiKeyAuth: []
      summary: Create universal layout
      tags:
      - Email Universal Layouts
  /email-universal-layouts/{id}:
    delete:
      description: 'With this endpoint you can delete a universal layout by ID.


        **Scopes:**

        `email-templates.write`


        **Rate Limiting:**

        This endpoint is rate limited to 400 requests per minute.'
      parameters:
      - description: Universal Layout ID (24 character hexadecimal)
        in: path
        name: id
        required: true
        schema:
          type: string
      - $ref: '#/components/parameters/APIVersionHeader'
      responses:
        '204':
          description: Universal layout deleted successfully
        '400':
          description: Invalid layout ID or missing brand ID
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '401':
          description: Authentication is missing or invalid
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '403':
          description: Insufficient permissions for this operation
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '410':
          description: API version has been retired
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '500':
          description: Unexpected error occurred
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
      security:
      - Bearer:
        - email-templates.write
      - ApiKeyAuth: []
      summary: Delete universal layout
      tags:
      - Email Universal Layouts
    get:
      description: 'With this endpoint you can get a universal layout by ID.


        **Scopes:**

        `email-templates.read`


        **Rate Limiting:**

        This endpoint is rate limited to 400 requests per minute.'
      parameters:
      - description: Universal Layout ID (24 character hexadecimal)
        in: path
        name: id
        required: true
        schema:
          type: string
      - $ref: '#/components/parameters/APIVersionHeader'
      responses:
        '200':
          description: Universal Layout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UniversalLayout'
        '400':
          description: Invalid layout ID or missing brand ID
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '401':
          description: Authentication is missing or invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '403':
          description: Insufficient permissions for this operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '404':
          description: Universal layout not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '410':
          description: API version has been retired
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '500':
          description: Unexpected error occurred
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
      security:
      - Bearer:
        - email-templates.read
      - ApiKeyAuth: []
      summary: Get universal layout
      tags:
      - Email Universal Layouts
    put:
      description: 'With this endpoint you can update (fully replace) a universal layout by ID.


        **Scopes:**

        `email-templates.write`


        **Rate Limiting:**

        This endpoint is rate limited to 400 requests per minute.'
      parameters:
      - description: Universal Layout ID (24 character hexadecimal)
        in: path
        name: id
        required: true
        schema:
          type: string
      - $ref: '#/components/parameters/APIVersionHeader'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UniversalLayout'
        description: Universal layout to update
        required: true
      responses:
        '200':
          description: Updated Universal Layout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UniversalLayout'
        '400':
          description: Invalid layout ID, request body, missing brand ID, invalid layout structure, or
            validation errors
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '401':
          description: Authentication is missing or invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '403':
          description: Insufficient permissions for this operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '404':
          description: Universal layout not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '410':
          description: API version has been retired
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '413':
          description: Request body too large - exceeds 1 MB limit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
        '500':
          description: Unexpected error occurred
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIErrorResponse'
      security:
      - Bearer:
        - email-templates.write
      - ApiKeyAuth: []
      summary: Update universal layout
      tags:
      - Email Universal Layouts
servers:
- url: https://api.omnisend.com/api
components:
  parameters:
    APIVersionHeader:
      description: API version that specifies the response format and behaviour
      in: header
      name: Omnisend-Version
      required: true
      schema:
        type: string
        default: '2026-03-15'
  securitySchemes:
    ApiKeyAuth:
      in: header
      name: Authorization
      type: apiKey
    Bearer:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://app.omnisend.com/oauth2/token
          scopes:
            email-templates.read: Allows reading email templates and universal layouts
            email-templates.write: Allows create, update, delete email templates and universal layouts
  schemas:
    APIErrorResponse:
      description: RFC 9457 Problem Details error response
      properties:
        detail:
          description: Human-readable explanation specific to this occurrence
          example: One or more fields are invalid.
          type: string
        errors:
          description: List of field-level validation errors
          items:
            $ref: '#/components/schemas/FieldError'
          type: array
        instance:
          description: URI reference identifying the specific occurrence
          example: urn:omnisend:request:abc123
          type: string
        status:
          description: HTTP status code
          example: 400
          type: integer
        title:
          description: Short human-readable summary of the problem
          example: Validation failed
          type: string
        type:
          description: URI reference identifying the problem type
          example: https://problems.omnisend.com/validation-failed
          type: string
      type: object
    Annotation:
      description: Gmail annotation settings
      properties:
        discountDescription:
          description: Gmail discount description - description of the discount or promotion to display
            in Gmail promotion tab together with the discount code.
          example: 15% off
          type: string
        isEnabled:
          description: Gmail annotation enabled
          example: true
          type: boolean
      type: object
    Block:
      description: Block is a single element in the email template
      properties:
        button:
          $ref: '#/components/schemas/Button'
        components:
          description: 'Components - the parts a block renders that are not covered by its own content
            field.

            Some blocks tag each part with a ''role'', and which roles they need is decided by their ''type'':

            a ''discount'' block holds the code, the redeem button and the expiry date, a ''menu'' block
            holds

            its items, a ''product'' block holds the product''s image, title, description, prices and
            button.

            Other blocks nest components without a role, and blocks that render everything from a dedicated

            content field have no components at all. See BlockComponent.'
          items:
            $ref: '#/components/schemas/BlockComponent'
          type: array
        discount:
          $ref: '#/components/schemas/Discount'
        dynamicDiscount:
          $ref: '#/components/schemas/Discount'
        html:
          description: 'Deprecated: use HTMLCode instead. Read-only, will be removed in future versions.'
          example: <p>Hello</p>
          readOnly: true
          type: string
        htmlCode:
          $ref: '#/components/schemas/HTMLCode'
        id:
          description: Block unique identifier - must be unique within the template
          example: 6699a0000000000000000000
          maxLength: 24
          minLength: 24
          type: string
        image:
          $ref: '#/components/schemas/Image'
        lineSpace:
          $ref: '#/components/schemas/LineSpace'
        logo:
          $ref: '#/components/schemas/Logo'
        orderAddresses:
          $ref: '#/components/schemas/OrderAddresses'
        orderProducts:
          $ref: '#/components/schemas/OrderProducts'
        orderSummary:
          $ref: '#/components/schemas/OrderSummary'
        orderTotal:
          $ref: '#/components/schemas/OrderTotal'
        preheader:
          $ref: '#/components/schemas/Preheader'
        product:
          $ref: '#/components/schemas/Product'
        role:
          description: Block role
          enum:
          - product_image
          - product_title
          - product_description
          - product_prices
          - product_price
          - product_button
          - discount_code
          - discount_button
          - discount_expiration_date
          - product_current_price
          - product_old_price
          - menu_text
          example: product_title
          type: string
        secondaryStylePresetID:
          description: Secondary style preset ID - ID of the secondary style preset. Used for order blocks
            styling as smaller text style.
          example: paragraph
          type: string
        social:
          $ref: '#/components/schemas/Social'
        staticDiscount:
          $ref: '#/components/schemas/Discount'
        stylePresetID:
          description: 'Style preset ID - ID of the style preset. Used for Button or Text block styling.

            ID must be present in template General Settings.'
          example: paragraph
          type: string
        styleProperties:
          allOf:
          - $ref: '#/components/schemas/StyleProperties'
          description: Style properties - style properties of the block
        text:
          description: Text content of the block - supports HTML formatting and personalization tags
          example: <p>Hello [[contact.first_name]]</p>
          type: string
        type:
          description: "Block type.\nNotes:\n  - 'html' is read-only and cannot be set on create/update.\n\
            \  - 'menu' is a container block with no dedicated content field — items must be provided\
            \ via 'components' as text blocks with role 'menu_text', and styling is configured through\
            \ 'stylePresetID' and 'styleProperties'.\n  - 'discount' is the block for an offer. The offer\
            \ is configured in the 'discount' object, and everything the recipient sees must be provided\
            \ via 'components' as role-tagged blocks — a text block with role 'discount_code' (required,\
            \ exactly one), plus an optional button with role 'discount_button' and an optional text block\
            \ with role 'discount_expiration_date'. The store issues a code per recipient when the email\
            \ is sent, so 'discount.code' carries the placeholder XXXX-XXXX-XXXX. Writing the offer as\
            \ plain text instead leaves a code that was never created in the store, so the recipient cannot\
            \ redeem it.\n  - 'dynamicDiscount' is the WooCommerce equivalent of 'discount' — same object,\
            \ same components and placeholder, except that the 'discount_button' component is required.\
            \ A 'discount' block on a WooCommerce store is skipped when the email is sent, so it ships\
            \ the placeholder to the recipient as the code.\n  - 'staticDiscount' (WooCommerce) instead\
            \ carries one fixed code that already exists in the store, and gets no code at send time.\
            \ It does not accept a 'discount_button'. Use it only when the brand explicitly asked for\
            \ a fixed code."
          enum:
          - html
          - htmlCode
          - text
          - image
          - video
          - logo
          - menu
          - social
          - button
          - product
          - discount
          - staticDiscount
          - dynamicDiscount
          - orderSummary
          - orderProducts
          - orderTotal
          - orderAddresses
          - lineSpace
          - preheader
          - price
          example: text
          type: string
        video:
          $ref: '#/components/schemas/Video'
      type: object
    BlockComponent:
      description: 'BlockComponent is a block nested inside a parent block, carrying one part of what
        that parent renders. Some parent blocks assign a ''role'' to each of their parts, and then the
        parent''s ''type'' decides which roles it needs: a ''discount'' block requires text/discount_code
        and accepts button/discount_button and text/discount_expiration_date; its WooCommerce equivalents
        take the same roles, except that ''dynamicDiscount'' requires the button and ''staticDiscount''
        does not accept one. A ''menu'' block holds its items as text/menu_text. The product_* roles belong
        to a ''product'' block, whose price/product_prices component nests text/product_current_price
        and text/product_old_price components of its own. Blocks that do not assign roles nest their components
        without one.'
      properties:
        button:
          allOf:
          - $ref: '#/components/schemas/Button'
          description: Button content of the component - used by roles 'discount_button' and 'product_button'.
        components:
          description: Components nested inside this component. Only role 'product_prices' uses them.
          items:
            $ref: '#/components/schemas/BlockComponent'
          type: array
        html:
          description: 'Deprecated: use Text instead. Read-only, will be removed in future versions.'
          example: <p>Hello</p>
          readOnly: true
          type: string
        id:
          description: Component unique identifier - must be unique within the template
          example: 6699a0000000000000000000
          maxLength: 24
          minLength: 24
          type: string
        image:
          allOf:
          - $ref: '#/components/schemas/Image'
          description: Image content of the component - used by role 'product_image'.
        role:
          description: 'Role the component plays inside its parent block - set only where the parent block
            assigns

            roles to its parts, and omitted otherwise.'
          enum:
          - discount_code
          - discount_button
          - discount_expiration_date
          - menu_text
          - product_image
          - product_title
          - product_description
          - product_prices
          - product_price
          - product_button
          - product_current_price
          - product_old_price
          example: discount_code
          type: string
        stylePresetID:
          description: Style preset ID - ID of the style preset. ID must be present in template General
            Settings.
          example: paragraph
          type: string
        styleProperties:
          allOf:
          - $ref: '#/components/schemas/StyleProperties'
          description: Style properties - style properties of the component
        text:
          description: 'Text content of the component - supports HTML formatting and personalization tags.

            For role ''discount_code'' this is the code the recipient sees; on a platform that issues
            its own codes

            it is replaced at send time, so it carries the placeholder XXXX-XXXX-XXXX.'
          example: <p>XXXX-XXXX-XXXX</p>
          type: string
        type:
          description: Component type. Only these block types can be nested as a component.
          enum:
          - text
          - button
          - image
          - price
          example: text
          type: string
      type: object
    Body:
      description: Body settings for the template
      properties:
        backgroundColor:
          description: Body background color
          example: '#EDEEF0'
          type: string
        backgroundImageID:
          description: Body background image ID - must be present in Image API
          example: 68f0ad8a72105230579523cd
          maxLength: 24
          minLength: 24
          type: string
        backgroundRepeat:
          description: Body background repeat
          example: no-repeat
          type: string
        backgroundSize:
          description: Body background size
          example: cover
          type: string
      type: object
    Button:
      description: Button block settings
      properties:
        isFullWidth:
          description: Button is full width
          example: true
          type: boolean
        link:
          description: Button link
          example: https://www.omnisend.com
          type: string
        text:
          description: Button text
          example: Shop now
          type: string
        translationKey:
          description: Button translation key - used for internationalization support
          example: shop_now
          type: string
      type: object
    ButtonPreset:
      description: Button preset for consistent design
      properties:
        id:
          description: Button preset unique identifier
          example: primary_button
          type: string
        name:
          description: Button preset name
          example: Primary button
          type: string
        styles:
          allOf:
          - $ref: '#/components/schemas/ButtonStyle'
          description: Button preset styles
      type: object
    ButtonStyle:
      description: Button preset style properties
      properties:
        backgroundColor:
          description: Button background color
          example: '#383838'
          type: string
        border:
          description: Button border style
          example: '2px solid #BFDCFE'
          type: string
        borderRadius:
          description: Button border radius
          example: 0px
          type: string
        color:
          description: Button font color
          example: '#FFFFFF'
          type: string
        fontFamily:
          description: Button font family
          example: Alegreya, Georgia, Times New Roman, serif
          type: string
        fontSize:
          description: Button font size
          example: 16px
          type: string
        fontStyle:
          description: Button font style
          example: normal
          type: string
        fontWeight:
          description: Button font weight
          example: bold
          type: string
        letterSpacing:
          description: Button letter spacing - spacing between letters
          example: 0px
          type: string
        paddingBottom:
          description: Button padding bottom
          example: 16px
          type: string
        paddingLeft:
          description: Button padding left
          example: 16px
          type: string
        paddingRight:
          description: Button padding right
          example: 16px
          type: string
        paddingTop:
          description: Button padding top
          example: 16px
          type: string
        textDecoration:
          description: Button text decoration
          example: none
          type: string
      type: object
    Column:
      description: Column is a single column of the row
      properties:
        blocks:
          description: Column blocks - used to group content into logical blocks
          items:
            $ref: '#/components/schemas/Block'
          type: array
        id:
          description: Column unique identifier - must be unique within the template
          example: 69770b2f7f774c6fb6f57194
          maxLength: 24
          minLength: 24
          type: string
        styleProperties:
          allOf:
          - $ref: '#/components/schemas/StyleProperties'
          description: Column style properties - used to configure the column styling
        width:
          description: Column width - used to set the width of the column
          example: 552px
          type: string
      type: object
    Content:
      description: Email content
      properties:
        createdAt:
          description: Content created at (read-only)
          example: '2021-01-01T01:02:03Z'
          readOnly: true
          type: string
        generalSettings:
          allOf:
          - $ref: '#/components/schemas/GeneralSettings'
          description: Content general settings - global and template level styles
        id:
          description: Content unique identifier (read-only)
          example: 68beca12d2e99b0c8d19fd5e
          readOnly: true
          type: string
        sections:
          description: Content sections
          items:
            $ref: '#/components/schemas/Section'
          type: array
        updatedAt:
          description: Content updated at (read-only)
          example: '2021-01-01T01:02:03Z'
          readOnly: true
          type: string
      type: object
    CursorsResponse:
      description: Cursor pointers for paginating forward and backward through results
      properties:
        after:
          description: Opaque cursor for fetching the next page of results
          example: eyJpZCI6ImNhbXAtNDU2In0
          type: string
          nullable: true
        before:
          description: Opaque cursor for fetching the previous page of results
          example: eyJpZCI6ImNhbXAtMTIzIn0
          type: string
          nullable: true
      type: object
    CustomFont:
      description: Custom font reference
      properties:
        id:
          description: ID of the custom font
          example: 69ca539b38e3c1f5dc035867
          maxLength: 24
          minLength: 24
          type: string
      type: object
    Discount:
      description: Discount block settings. This object configures the offer only — the parts the recipient
        sees (code, redeem button, expiry) are separate role-tagged blocks in the parent block's 'components'.
        See the notes on the Block 'type' field for the roles each discount block type requires.  An offer
        needs 'discountType', the value that matches it ('valuePercentage' for a percentage, 'valueFixed'
        for an amount off), 'discountConditions', and 'endsIn' for how long it stays valid. 'staticDiscount'
        and 'dynamicDiscount' blocks require 'code', 'discountType', 'valuePercentage' and 'discountConditions'.
      properties:
        appliesToCustomCollectionID:
          description: ID of the custom collection that the discount applies to
          example: 0
          type: integer
        appliesToID:
          description: ID of the specific resource (product, collection) that the discount applies to
          example: 0
          type: integer
        appliesToResource:
          description: Type of resource the discount applies to
          example: all
          type: string
        appliesToSmartCollectionID:
          description: ID of the smart collection that the discount applies to
          example: 0
          type: integer
        code:
          description: 'Discount code customers use to apply the discount.

            In ''discount'' (Shopify, BigCommerce) and ''dynamicDiscount'' (WooCommerce) blocks the code
            is not taken from here:

            t

# --- truncated at 32 KB (78 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/omnisend/refs/heads/main/openapi/omnisend-emailuniversallayouts-api-openapi.yml