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

# Create a brand report

> Creates a brand report in a workspace, the same as creating it in the UI. The prompts must already exist in that workspace — create them with `POST /v1/workspaces/{id}/prompts` — and the report tracks their countries. Domains are normalized (protocol, `www.` and path stripped). Detect the brand either by `brand` and `brandVariations`, or by `brandRegex` together with `reportTitle`. Competitors can come straight from `POST /v1/competitors/suggestions`. Data for the report is collected asynchronously. Sending the same request again within 2 minutes returns the report the first request created instead of a second one; if that report is still being set up, the response is a 409 carrying its ID.



## OpenAPI

````yaml https://data.otterly.ai/v1/openapi.json post /v1/reports/brand
openapi: 3.0.0
info:
  title: Otterly Public API
  version: 1.0.0
servers:
  - url: https://data.otterly.ai
security: []
tags:
  - name: Engines
  - name: Workspaces
  - name: Tags
  - name: Prompts
  - name: Brand Reports
  - name: Competitors
  - name: Audits
  - name: Accounts
paths:
  /v1/reports/brand:
    post:
      tags:
        - Brand Reports
      summary: Create a brand report
      description: >-
        Creates a brand report in a workspace, the same as creating it in the
        UI. The prompts must already exist in that workspace — create them with
        `POST /v1/workspaces/{id}/prompts` — and the report tracks their
        countries. Domains are normalized (protocol, `www.` and path stripped).
        Detect the brand either by `brand` and `brandVariations`, or by
        `brandRegex` together with `reportTitle`. Competitors can come straight
        from `POST /v1/competitors/suggestions`. Data for the report is
        collected asynchronously. Sending the same request again within 2
        minutes returns the report the first request created instead of a second
        one; if that report is still being set up, the response is a 409
        carrying its ID.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicApiCreateBrandReportRequest'
      responses:
        '201':
          description: The created brand report.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiBrandReport'
        '400':
          description: Validation failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiValidationErrorResponse'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiErrorResponse'
        '403':
          description: Forbidden.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiErrorResponse'
        '409':
          description: >-
            An identical create is still in progress. Retry `GET
            /v1/reports/brand/{reportId}` with the ID in the message.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiErrorResponse'
        '429':
          description: Quota exhausted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiErrorResponse'
      security:
        - BearerAuth: []
components:
  schemas:
    PublicApiCreateBrandReportRequest:
      type: object
      properties:
        workspaceId:
          type: string
          minLength: 1
          example: 01HX7K2YV9D3M8N0G6Q5R4S3T2
          description: >-
            Workspace to create the report in. The API key must have access to
            it.
        reportTitle:
          type: string
          minLength: 1
          description: >-
            Optional. Report name shown in the app. Defaults to `brand`.
            Required when `brandRegex` is set.
        brand:
          type: string
          minLength: 1
          description: >-
            Brand name to track. Required unless `brandRegex` is set, in which
            case `reportTitle` is used as the brand label.
        brandVariations:
          type: array
          items:
            type: string
            minLength: 1
          maxItems: 100
          description: >-
            Optional. Other names the brand goes by, at most 100. Cannot be
            combined with `brandRegex`.
        brandDomain:
          type: string
          minLength: 1
          description: >-
            Brand website domain, e.g. `acme.com`. Protocol, `www.` and path are
            stripped.
        brandDomainVariations:
          type: array
          items:
            type: string
            minLength: 1
          maxItems: 100
          description: >-
            Optional. Other domains the brand owns, at most 100. Each must
            differ from `brandDomain`.
        brandDomainWildcard:
          type: boolean
          description: >-
            Optional. When true, subdomains of `brandDomain` also count as the
            brand domain.
        brandRegex:
          type: string
          nullable: true
          description: >-
            Optional. Regular expression used to detect the brand in AI answers,
            instead of the name and its variations (so it cannot be combined
            with `brandVariations`). Up to 1000 characters. Send `null` to clear
            it.
        promptIds:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 64
          minItems: 1
          maxItems: 1000
          description: >-
            IDs of prompts that already exist in the report workspace — look
            them up with `GET /v1/workspaces/{id}/prompts`. The report tracks
            the countries of these prompts.
        competitors:
          type: array
          items:
            $ref: '#/components/schemas/PublicApiBrandCompetitorInput'
          maxItems: 100
          description: >-
            Optional. Competitors to track, at most 100. Each competitor domain
            must be unique. `POST /v1/competitors/suggestions` returns items in
            this shape.
      required:
        - workspaceId
        - brandDomain
        - promptIds
      example:
        workspaceId: 01HX7K2YV9D3M8N0G6Q5R4S3T2
        reportTitle: Adidas Visibility Report
        brand: Adidas
        brandDomain: adidas.com
        promptIds:
          - 01HXP1DRTM5G8Z2N3KQ7VAW4PA
        competitors:
          - brand: Nike
            brandDomain: nike.com
    PublicApiBrandReport:
      type: object
      properties:
        id:
          type: string
          minLength: 1
          example: 01HX7K2YV9D3M8N0G6Q5R4S3T2
        workspaceId:
          type: string
        brand:
          type: string
        reportTitle:
          type: string
        brandVariations:
          type: array
          items:
            type: string
        brandDomain:
          type: string
        brandDomainVariations:
          type: array
          items:
            type: string
        brandDomainWildcard:
          type: boolean
        brandRegex:
          type: string
          nullable: true
          description: >-
            Regular expression used to detect the brand in AI answers, instead
            of `brand` and `brandVariations`. `null` when not set.
        countries:
          type: array
          items:
            type: string
          description: >-
            Lowercase ISO 3166-1 alpha-2 country codes the report tracks (e.g.
            `us`, `de`), with `uk` used in place of `gb`.
        createdDate:
          type: string
        updatedDate:
          type: string
        promptIds:
          type: array
          items:
            type: string
        countryPromptsTotal:
          type: object
          additionalProperties:
            type: number
          description: >-
            Total prompt count keyed by country code (lowercase ISO 3166-1
            alpha-2; `uk` instead of `gb`).
        competitors:
          type: array
          items:
            $ref: '#/components/schemas/PublicApiBrandCompetitor'
        tags:
          type: array
          items:
            $ref: '#/components/schemas/PublicApiBrandReportTag'
      required:
        - id
        - workspaceId
        - brand
        - brandDomain
        - brandRegex
        - countries
        - createdDate
        - updatedDate
      example:
        id: 01HXBR1DGM5XY8Z2N3KQ7VAW4P
        workspaceId: 01HX7K2YV9D3M8N0G6Q5R4S3T2
        brand: Adidas
        brandVariations:
          - adidas
          - Adidas AG
        brandDomain: adidas.com
        brandDomainVariations:
          - adidas.de
          - adidas.co.uk
        brandDomainWildcard: false
        brandRegex: null
        countries:
          - us
          - de
          - uk
        competitors:
          - brand: Nike
            brandVariations:
              - nike
              - Nike Inc.
            brandDomain: nike.com
            brandDomainVariations:
              - nike.de
              - nike.co.uk
            brandDomainWildcard: false
            brandRegex: null
        reportTitle: Adidas Visibility Report
        createdDate: '2024-11-01T12:00:00.000Z'
        updatedDate: '2025-05-01T08:30:00.000Z'
        promptIds:
          - 01HXP1DRTM5G8Z2N3KQ7VAW4PA
          - 01HXP2DRTM5G8Z2N3KQ7VAW4PB
        countryPromptsTotal:
          us: 50
          de: 35
          uk: 28
        tags:
          - id: 01HX8AB3CDE4FG5HJ6KL7MN8PQ
            name: Running Shoes
            color: orange
    PublicApiValidationErrorResponse:
      type: object
      properties:
        message:
          type: string
        target:
          type: string
        errors:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
              message:
                type: string
              code:
                type: string
            required:
              - path
              - message
              - code
      required:
        - message
        - target
        - errors
      example:
        message: Validation failed
        target: query
        errors:
          - path: country
            message: Required
            code: invalid_type
    PublicApiErrorResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      example:
        message: Report not found
    PublicApiBrandCompetitorInput:
      type: object
      properties:
        brand:
          type: string
          minLength: 1
          description: Competitor brand name.
        brandVariations:
          type: array
          items:
            type: string
            minLength: 1
          maxItems: 100
        brandDomain:
          type: string
          minLength: 1
        brandDomainVariations:
          type: array
          items:
            type: string
            minLength: 1
          maxItems: 100
        brandDomainWildcard:
          type: boolean
        brandRegex:
          type: string
          nullable: true
          description: >-
            Optional. Regular expression used to detect the brand in AI answers,
            instead of the name and its variations (so it cannot be combined
            with `brandVariations`). Up to 1000 characters. Send `null` to clear
            it.
      required:
        - brand
        - brandDomain
      example:
        brand: Nike
        brandDomain: nike.com
        brandVariations:
          - Nike Inc.
    PublicApiBrandCompetitor:
      type: object
      properties:
        brand:
          type: string
          description: Competitor brand name.
        brandVariations:
          type: array
          items:
            type: string
        brandDomain:
          type: string
        brandDomainVariations:
          type: array
          items:
            type: string
        brandDomainWildcard:
          type: boolean
        brandRegex:
          type: string
          nullable: true
          description: >-
            Regular expression used to detect the brand in AI answers, instead
            of `brand` and `brandVariations`. `null` when not set.
      required:
        - brand
        - brandVariations
        - brandDomain
        - brandDomainVariations
        - brandDomainWildcard
        - brandRegex
      example:
        brand: Nike
        brandVariations:
          - nike
          - Nike Inc.
        brandDomain: nike.com
        brandDomainVariations:
          - nike.de
          - nike.co.uk
        brandDomainWildcard: false
        brandRegex: null
    PublicApiBrandReportTag:
      type: object
      properties:
        id:
          type: string
          minLength: 1
          example: 01HX7K2YV9D3M8N0G6Q5R4S3T2
        name:
          type: string
        color:
          type: string
          description: >-
            Tag color (Ant Design preset color name, e.g. 'gold', 'orange',
            'magenta', 'green', 'blue').
      required:
        - id
        - name
        - color
      example:
        id: 01HX8AB3CDE4FG5HJ6KL7MN8PQ
        name: Running Shoes
        color: orange
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Provide your API key as a Bearer token: `Authorization: Bearer
        YOUR_API_KEY`.

````