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

# Resolve a composition UUID to a published widget URL

> Public customer embed lookup. No API key. Used by embed-sdk.js on third-party sites.
If the composition's owner listed the websites it may appear on (the workspace's domain list, or the `allowedDomains` of a partner the owner administers), a request from any other website is refused with 403 `DOMAIN_NOT_ALLOWED`. The website is read from the `Origin` header, or the host of `Referer` when there is no `Origin`; a request that names neither (a server, a tool) is not refused. An owner who listed nothing is not restricted, and a page on the visitor's own machine (`localhost`, `127.0.0.1` or `[::1]`, on any port) is always allowed. So is the website where a partner integrates Widgetic, with every subdomain of it (`platformDomain` in the answer of `GET /partners/mine`), for the widgets of that partner: a partner's list never has to name it. The list stops other websites from showing the embed in a visitor's browser; it does not hide the published content from someone who holds the composition ID.
**Address.** `https://api.widgetic.com/embed/compositions/{compositionId}`: the root of the API host, NOT under `/v1`. A client generated from this description for `https://api.widgetic.com/v1` must be given the base address `https://api.widgetic.com` for the calls of the `Public Embed` tag.
**Limit.** 500 calls for each visitor address and browser in one counting window, shared with the frame and the status routes. Over it the answer is 429 `RATE_LIMITED` with a `Retry-After` header.




## OpenAPI

````yaml /openapi/widgetic-api-public.json get /embed/compositions/{compositionId}
openapi: 3.0.0
info:
  title: Widgetic API Gateway
  version: 1.0.0
  description: API documentation for the Widgetic API Gateway
  license:
    name: Widgetic Integration License
    url: https://docs.widgetic.com/resources/license
servers:
  - url: https://api.widgetic.com/v1
    description: Production server
    variables:
      env:
        default: production
        description: Environment
      apiUrl:
        default: https://api.widgetic.com
        description: API URL
      apiVersion:
        default: /v1
        description: API Version path prefix
security: []
tags: []
paths:
  /embed/compositions/{compositionId}:
    servers:
      - url: https://api.widgetic.com
        description: >-
          The public embed routes are served at the root of the API host, not
          under /v1.
    get:
      tags:
        - Public Embed
      summary: Resolve a composition UUID to a published widget URL
      description: >
        Public customer embed lookup. No API key. Used by embed-sdk.js on
        third-party sites.

        If the composition's owner listed the websites it may appear on (the
        workspace's domain list, or the `allowedDomains` of a partner the owner
        administers), a request from any other website is refused with 403
        `DOMAIN_NOT_ALLOWED`. The website is read from the `Origin` header, or
        the host of `Referer` when there is no `Origin`; a request that names
        neither (a server, a tool) is not refused. An owner who listed nothing
        is not restricted, and a page on the visitor's own machine (`localhost`,
        `127.0.0.1` or `[::1]`, on any port) is always allowed. So is the
        website where a partner integrates Widgetic, with every subdomain of it
        (`platformDomain` in the answer of `GET /partners/mine`), for the
        widgets of that partner: a partner's list never has to name it. The list
        stops other websites from showing the embed in a visitor's browser; it
        does not hide the published content from someone who holds the
        composition ID.

        **Address.**
        `https://api.widgetic.com/embed/compositions/{compositionId}`: the root
        of the API host, NOT under `/v1`. A client generated from this
        description for `https://api.widgetic.com/v1` must be given the base
        address `https://api.widgetic.com` for the calls of the `Public Embed`
        tag.

        **Limit.** 500 calls for each visitor address and browser in one
        counting window, shared with the frame and the status routes. Over it
        the answer is 429 `RATE_LIMITED` with a `Retry-After` header.
      operationId: getPublicCompositionEmbed
      parameters:
        - in: path
          name: compositionId
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Published embed URL and optional direct frameless module
          content:
            application/json:
              schema:
                type: object
                properties:
                  compositionId:
                    type: string
                  widgetId:
                    type: string
                  version:
                    type: integer
                  widgetVersion:
                    type: integer
                    description: >-
                      Published widget version on the CDN artifact this
                      composition uses.
                  playerVersion:
                    type: integer
                    description: >-
                      Version of the player: the gateway frame wrapper that
                      shows the widget, and the host bridge it speaks with the
                      embedding page and the widget (currently 6). Raised when
                      the messages between page, frame, and widget change in a
                      way a widget could notice, such as a new `widgetic:host`
                      field or a new forwarded event (2 added `entries`, 3 added
                      `adapters`, 4 added `entries.writeToken`, 5 added the A/B
                      goal: `widgetic:ab-goal` to the widget and `widgetic:goal`
                      back, 6 added the watch of a workflow:
                      `widgetic:workflow-watch` to the widget, the watched
                      values in `widgetic:submitted` and the watched action in
                      `widgetic:goal`). It is not `widgetVersion` (the version
                      of the published widget) and not the `version` inside a
                      `widgetic:host` message.
                  dataSource:
                    type: object
                    nullable: true
                    properties:
                      url:
                        type: string
                      refreshSeconds:
                        type: integer
                  embedUrl:
                    type: string
                  entryWriteToken:
                    type: string
                    description: >-
                      Signed per-composition write token for `POST
                      /embed/compositions/{compositionId}/entries/{table}`, also
                      handed to the widget inside `widgetic:host` as
                      `entries.writeToken`.
                  entries:
                    type: object
                    description: Where a direct or iframe embed writes visitor entries.
                    properties:
                      url:
                        type: string
                      writeToken:
                        type: string
                  adapters:
                    type: object
                    description: >-
                      Where the widget's adapter modules (e-mail, upload, AI
                      answers, decision, ...) call the gateway, and the public
                      key of the CAPTCHA an operation may ask a visitor to
                      solve. The same two facts the frame page gives the widget,
                      so an embed that does not use the frame page (the Embed
                      SDK, a widget mounted directly) can tell the widget too:
                      the SDK passes them to the widget with `entries`.
                      `entries.url` is where the widget writes visitor entries;
                      this is where it calls operations.
                    properties:
                      url:
                        type: string
                        description: >-
                          The operations' address; an operation is
                          `{url}/{adapterId}/{operation}`.
                        example: >-
                          https://api.widgetic.com/embed/compositions/0f6f7f0e-3c2a-4b86-9e51-2d8d5f4a7c11/adapters
                      captcha:
                        type: object
                        description: >-
                          Present only when the gateway has a CAPTCHA. There is
                          one, so no provider is named.
                        properties:
                          siteKey:
                            type: string
                            description: The public site key of the CAPTCHA widget.
                  width:
                    type: integer
                  height:
                    type: integer
                  design:
                    type: object
                  content:
                    type: object
                  contentItems:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                  iframeAllow:
                    type: string
                    description: >-
                      The browser features the widget needs the iframe that
                      shows it to be allowed to use, as the value of that
                      iframe's `allow` attribute (for example `camera;
                      microphone`; the words are `camera`, `display-capture` and
                      `microphone`). Present only for a widget that uses a
                      module that needs one, and absent for every other widget.
                      A page that embeds the frame itself copies it onto its own
                      iframe (`allow="..."`); a page that does not leaves the
                      widget to say, in its own words, that the feature is
                      blocked there. The frame wrapper already passes it on to
                      the iframe it holds.
                    example: camera; microphone
                  media:
                    type: object
                    description: How the owner wants the images of this embed delivered.
                    properties:
                      optimize:
                        type: boolean
                        description: >-
                          The owner's "Optimize images for the web" account
                          setting (ON until they turn it off). When true the
                          Embed SDK may ask Cloudflare for a right-sized,
                          modern-format copy of each content image; when false
                          it uses the originals.
                  direct:
                    type: object
                    nullable: true
                    description: >-
                      Present only when a confirmed direct (frameless) ESM
                      artifact was published for this version
                    properties:
                      moduleUrl:
                        type: string
                      contractVersion:
                        type: integer
                      moduleHash:
                        type: string
                        nullable: true
          x-response-envelope: raw
        '403':
          description: >
            The composition's owner limited it to the websites they listed, and
            this request came from another (`code` is `DOMAIN_NOT_ALLOWED`;
            `details.reason` is `domain_not_allowed` or `opaque_origin`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '404':
          description: >-
            Composition not found, not published, or embed suspended for billing
            (`code` is `NOT_FOUND`, `UNPUBLISHED` or `SUSPENDED`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '429':
          description: >-
            Embed rate limit exceeded (`code` is `RATE_LIMITED`; the
            `Retry-After` header says when to ask again)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
components:
  schemas:
    PublicEmbedFailure:
      type: object
      required:
        - success
        - message
        - error
        - code
      description: >-
        What a public embed route answers when it refuses or fails. It is the
        standard error answer of the API (`success`, `message`, `error`), and
        the short `code` (with `details` and `correlationId` when the route has
        them) is also at the top level, because a page that embeds a composition
        branches on it there. `error.code` is the same word in the codes of the
        rest of the API where those have it: `NOT_FOUND` is
        `RESOURCE_NOT_FOUND`, `RATE_LIMITED` is `RATE_LIMIT_EXCEEDED`, and the
        others (`DOMAIN_NOT_ALLOWED`, `UNPUBLISHED`, `SUSPENDED`, the codes of
        the entry route) are the same in both places.
      properties:
        success:
          type: boolean
          enum:
            - false
        message:
          type: string
          description: What happened, for a person.
        code:
          type: string
          description: >-
            The short code a page branches on: `DOMAIN_NOT_ALLOWED`,
            `UNPUBLISHED`, `SUSPENDED`, `NOT_FOUND`, `RATE_LIMITED`, and for the
            entry route the codes listed with its answers.
          example: NOT_FOUND
        details:
          type: object
          additionalProperties: true
          description: >-
            What tells the cases of one code apart, such as `reason` of
            `DOMAIN_NOT_ALLOWED`.
          properties:
            reason:
              type: string
              description: For `DOMAIN_NOT_ALLOWED`, why the website was refused.
              enum:
                - domain_not_allowed
                - opaque_origin
            hasDomainsConfigured:
              type: boolean
              description: >-
                For `DOMAIN_NOT_ALLOWED`, always true (an owner who listed
                nothing is never refused).
        correlationId:
          type: string
          description: The id of the request, for the routes that carry it.
        error:
          type: object
          required:
            - code
            - message
            - timestamp
          properties:
            code:
              type: string
              example: RESOURCE_NOT_FOUND
            message:
              type: string
            details:
              type: object
              additionalProperties: true
            correlationId:
              type: string
            retryAfter:
              type: integer
              description: Seconds to wait before asking again, for a rate-limit refusal.
            timestamp:
              type: string
              format: date-time
      example:
        success: true
        message: Example message
        code: NOT_FOUND
        details: {}
        correlationId: Example correlationId
        error: {}

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.