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

# Validate Content

> Checks content against the composition's widget schema without saving it. Send what a content update (`PUT /compositions/{id}/content`) would store, `{ "design": {...}, "content": {...} }`, or the widget's values alone. Each value is checked by the kind of field the widget declares for it: text, a number within the limits of its slider, true or false, one of the choices of a dropdown, a color, a font, the address of an image, a date. The items of the widget's list are checked the same way, and their number against the limits of the list. A value that cannot be what the field holds, or a number outside its range, is an error and `valid` is false. Text longer than the field takes, a number or true/false sent as text, and a name the widget has no field for are warnings, and `valid` stays true. The design is not checked here. Nothing is saved and nothing in the body is changed.



## OpenAPI

````yaml /openapi/widgetic-api-public.json post /compositions/{id}/content/validate
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:
  /compositions/{id}/content/validate:
    post:
      tags:
        - Compositions
      summary: Validate Content
      description: >-
        Checks content against the composition's widget schema without saving
        it. Send what a content update (`PUT /compositions/{id}/content`) would
        store, `{ "design": {...}, "content": {...} }`, or the widget's values
        alone. Each value is checked by the kind of field the widget declares
        for it: text, a number within the limits of its slider, true or false,
        one of the choices of a dropdown, a color, a font, the address of an
        image, a date. The items of the widget's list are checked the same way,
        and their number against the limits of the list. A value that cannot be
        what the field holds, or a number outside its range, is an error and
        `valid` is false. Text longer than the field takes, a number or
        true/false sent as text, and a name the widget has no field for are
        warnings, and `valid` stays true. The design is not checked here.
        Nothing is saved and nothing in the body is changed.
      operationId: validateCompositionContent
      parameters:
        - in: path
          name: id
          schema:
            type: string
            format: uuid
          required: true
          description: ID of the composition
        - $ref: '#/components/parameters/IdempotencyKeyRequired'
        - $ref: '#/components/parameters/ManagedUserScopeId'
        - $ref: '#/components/parameters/ManagedUserScopeExternalId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
              description: >-
                The content to check, as a content update stores it: `{
                "design": {...}, "content": {...} }`, or the widget's values
                alone.
      responses:
        '200':
          description: The check ran; `valid` says whether the content passed it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidateCompositionContentResponse'
        '400':
          description: The body is not a JSON object.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Composition not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKeyAuth: []
components:
  parameters:
    IdempotencyKeyRequired:
      in: header
      name: Idempotency-Key
      required: true
      description: >-
        Required: a call without it is refused with `400`. A key of your own
        that names this one request; a UUID is ideal. It is 8 to 50 characters
        of letters, digits, `-` and `_`. Send the same key again when you retry
        (after a timeout, a dropped connection or a `5xx`) and the call is
        carried out once: the retry gets the first answer back, marked
        `X-Idempotency-Cached: true`. The same key with a different body is
        refused with `422`, and a retry that arrives while the first call is
        still running with `409` (see `Retry-After`).
      schema:
        type: string
        minLength: 8
        maxLength: 50
        pattern: ^[a-zA-Z0-9_-]{8,50}$
        example: 9b2d6f0a-3c41-4e5a-8d77-1f2e3a4b5c6d
    ManagedUserScopeId:
      in: header
      name: X-Managed-User-Id
      required: false
      description: >-
        The id Widgetic gave the managed user (`POST /managed-users`). Makes
        this call for one of your managed users, so that a mistake in your own
        code cannot reach another customer's work. Send this header, or the
        other one, never both. Left out, the call works on your whole account,
        as it always has. With it, the call reaches only that user's
        compositions and workflows: a list shows only theirs, a composition or a
        workflow the call makes is filed under them, and one of another user, or
        one that does not exist, answers `404` (the same answer, so the call
        cannot be used to find out what another customer has). A managed user
        that is not yours answers `404` with `MANAGED_USER_NOT_FOUND`. An empty,
        repeated or malformed header is `400` with `MANAGED_USER_SCOPE_INVALID`;
        an empty header is never read as no header. A call that is about the
        whole account, such as the list of your managed users, is refused with
        `403` and `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`: send it without the
        header. Only your API key can send it. The header is a limit the call
        asks for: whoever holds the key can leave it out, so for a credential
        that a customer's browser holds, use an editor session. An
        `Idempotency-Key` is kept apart for each managed user.
      schema:
        type: string
        format: uuid
        example: 3f2b8c1e-7a4d-4e0b-9c55-2d1a6b7e8f90
    ManagedUserScopeExternalId:
      in: header
      name: X-Managed-User-External-Id
      required: false
      description: >-
        Your own id for the managed user (its `externalId`), when you do not
        keep Widgetic's. Makes this call for one of your managed users, so that
        a mistake in your own code cannot reach another customer's work. Send
        this header, or the other one, never both. Left out, the call works on
        your whole account, as it always has. With it, the call reaches only
        that user's compositions and workflows: a list shows only theirs, a
        composition or a workflow the call makes is filed under them, and one of
        another user, or one that does not exist, answers `404` (the same
        answer, so the call cannot be used to find out what another customer
        has). A managed user that is not yours answers `404` with
        `MANAGED_USER_NOT_FOUND`. An empty, repeated or malformed header is
        `400` with `MANAGED_USER_SCOPE_INVALID`; an empty header is never read
        as no header. A call that is about the whole account, such as the list
        of your managed users, is refused with `403` and
        `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`: send it without the header.
        Only your API key can send it. The header is a limit the call asks for:
        whoever holds the key can leave it out, so for a credential that a
        customer's browser holds, use an editor session. An `Idempotency-Key` is
        kept apart for each managed user.
      schema:
        type: string
        minLength: 1
        maxLength: 255
        example: customer-1042
  schemas:
    ValidateCompositionContentResponse:
      type: object
      required:
        - success
        - data
      properties:
        success:
          type: boolean
          description: Always `true` on a success.
          example: true
        data:
          type: object
          required:
            - valid
          properties:
            valid:
              type: boolean
              description: >-
                False when there is at least one error. Warnings do not change
                it.
            errors:
              type: array
              description: What is wrong, at most 100. Absent when `valid` is true.
              items:
                $ref: '#/components/schemas/ContentCheckFinding'
            warnings:
              type: array
              description: >-
                What is worth a look but does not stop the content from being
                saved, at most 100.
              items:
                $ref: '#/components/schemas/ContentCheckFinding'
            sanitizedContent:
              type: object
              additionalProperties: true
              description: The body as it was sent; nothing is changed.
        meta:
          $ref: '#/components/schemas/ResponseMeta'
    ErrorResponse:
      type: object
      required:
        - success
        - message
        - error
      additionalProperties: true
      properties:
        success:
          type: boolean
          description: Always `false` on a failure.
          example: false
        message:
          type: string
          description: The same text as `error.message`, for a caller that reads one line.
        error:
          $ref: '#/components/schemas/ErrorDetail'
    ContentCheckFinding:
      type: object
      required:
        - path
        - message
      description: One thing the check of a body of content found.
      properties:
        path:
          type: string
          description: >-
            Where it is, for example `content.interval` or
            `content.items[2].caption`.
          example: content.items[2].caption
        message:
          type: string
          description: What is wrong, in a sentence.
          example: caption takes text, got a number
        expected:
          type: string
          description: What the field takes.
          example: text
        actual:
          type: string
          description: >-
            What was sent, shortened. Text and numbers as they were, anything
            else as its kind.
          example: a number
      example:
        path: content.items[2].caption
        message: caption takes text, got a number
        expected: text
        actual: a number
    ResponseMeta:
      type: object
      description: >-
        Extra information about the answer: where a page sits in a list, the
        cursor of the next page, or warnings about a call that succeeded with a
        caveat.
      additionalProperties: true
      properties:
        page:
          type: integer
          description: The page that was read, counting from 1.
          example: 1
        size:
          type: integer
          description: How many items one page holds.
          example: 20
        total:
          type: integer
          description: How many items the whole list has.
          example: 135
        limit:
          type: integer
          description: The same as `size`.
          example: 20
        offset:
          type: integer
          description: How many items come before this page.
          example: 0
        hasNextPage:
          type: boolean
          example: true
        hasPreviousPage:
          type: boolean
          example: false
        nextCursor:
          type: string
          nullable: true
          description: >-
            Pass this as `cursor` to read the next page of a list that is read
            by cursor. `null` on the last page.
        warnings:
          type: array
          items:
            type: string
          description: >-
            Things the call did not do, though it succeeded (for example a table
            that could not be created just now).
    ErrorDetail:
      type: object
      required:
        - code
        - message
        - timestamp
      properties:
        code:
          type: string
          description: Machine-readable error code.
          example: RESOURCE_NOT_FOUND
        message:
          type: string
          description: Human-readable explanation.
          example: Composition not found
        param:
          type: string
          description: The field that caused the error, when one did.
          example: name
        docUrl:
          type: string
          description: Where this error is explained.
        suggestedAction:
          type: string
          description: What to do about it.
        retryAfter:
          type: integer
          description: >-
            Seconds to wait before trying again (rate limits). The same number
            is in the `Retry-After` header.
          example: 60
        details:
          type: object
          additionalProperties: true
          description: >-
            More about the error: the fields that failed, a limit that was
            reached.
        correlationId:
          type: string
          description: Quote this when you ask support about the call.
          example: req_123e4567-e89b-12d3-a456-426614174000
        timestamp:
          type: string
          format: date-time
          example: '2026-10-15T10:00:00.000Z'
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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