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

# Create a project

> Create a project and set it up as the app's Add project flow does: the project on the workspace's plan cadence, its competitors, brand profile, default location and onboarding record, counted toward the workspace's project quota. It requires the same details the app asks for (brand name and summary, reach, country, at least one competitor); `generatePrompts: true` starts the app's prompt generation in the background, and the prompts are tracked within the prompt allowance. Requires a connection minted with the `project:provision` capability (not the bare `write` scope); a project-bound credential is refused outright, since creating a project is a workspace-level action. Supports `Idempotency-Key` replay; a reused key with a different body returns 409 `idempotency_conflict` instead of replaying the first project. A duplicate domain in the same workspace returns 409 `duplicate_domain`.



## OpenAPI

````yaml /api-reference/openapi.json post /api/mcp/projects
openapi: 3.1.0
info:
  title: Searchable REST API
  version: 1.0.0
  summary: >-
    Query AI visibility, sources, sentiment, traffic, and content data, and
    trigger audits/reports/sitemap syncs.
  description: >-
    The Searchable REST API (`/api/mcp/*` and
    `/api/v1/projects/{projectId}/audits`) exposes the same data and actions
    available in the Searchable dashboard and MCP server, over plain HTTP with a
    bearer API key. It is a **read-mostly** surface — 75 of its 91 operations
    are GET. The mutating ones are capability-gated (a bare `write` scope does
    not satisfy a capability such as `prompt:draft`), and those listed under
    [Idempotency](/api-reference/introduction#idempotency) support
    `Idempotency-Key` replay.


    See **[Getting started](/api-reference/introduction)** for auth, rate
    limits, idempotency, and pagination conventions, and the **[error
    reference](/api/errors)** for every error `code` this API returns.


    `/api/mcp/*` is a frozen v1 contract — see the [changelog](/changelog) for
    the deprecation policy.
  contact:
    name: Searchable Support
    email: support@searchable.com
    url: https://docs.searchable.com/api-reference/introduction
servers:
  - url: https://app.searchable.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Projects
    description: List and inspect the projects an API key can reach.
  - name: Visibility
    description: >-
      AI visibility score, platform/topic/prompt/location breakdowns, and
      historical trend.
  - name: Share of Voice
    description: Brand vs. competitor mention-share ranking and its daily trend.
  - name: Competitors
    description: >-
      The project's tracked competitor roster — share of voice, sentiment, and
      mention/citation counts.
  - name: Sources
    description: >-
      Domains and URLs cited by AI answers — citation share, trend, and cached
      page content.
  - name: Sentiment
    description: Brand sentiment summary, trend, and head-to-head competitor comparison.
  - name: Query Fanout
    description: The sub-queries AI models generate when answering tracked prompts.
  - name: Traffic
    description: >-
      First-party AI-crawler and AI-referral traffic sourced from the
      tracker/CDN pipeline.
  - name: Shopping
    description: AI shopping/product-carousel visibility.
  - name: Ads
    description: >-
      Sponsored ads surfaced in AI answers — advertisers, individual creatives,
      ad-heavy prompts, and the frequency trend.
  - name: Answers
    description: Raw, per-response AI-answer data for a single prompt.
  - name: GSC
    description: Live Google Search Console performance data for the project's linked site.
  - name: GA4
    description: Live Google Analytics 4 traffic and AI-referral data.
  - name: Audits & Issues
    description: >-
      Page audits (technical + AEO), site issues, monitored pages, and sitemap
      sync.
  - name: Reports
    description: Generate and list shareable visibility/sentiment reports.
  - name: Articles
    description: Content pieces (articles) created in Searchable.
  - name: Opportunities
    description: >-
      Actionable, prioritized suggestions Searchable has surfaced for the
      project.
  - name: Brand
    description: Brand profile (knowledge base + AI-observed facts) and domain authority.
  - name: Prompts
    description: >-
      The project's prompt catalog (tracked, untracked, and AI-suggested
      prompts).
paths:
  /api/mcp/projects:
    post:
      tags:
        - Projects
      summary: Create a project
      description: >-
        Create a project and set it up as the app's Add project flow does: the
        project on the workspace's plan cadence, its competitors, brand profile,
        default location and onboarding record, counted toward the workspace's
        project quota. It requires the same details the app asks for (brand name
        and summary, reach, country, at least one competitor); `generatePrompts:
        true` starts the app's prompt generation in the background, and the
        prompts are tracked within the prompt allowance. Requires a connection
        minted with the `project:provision` capability (not the bare `write`
        scope); a project-bound credential is refused outright, since creating a
        project is a workspace-level action. Supports `Idempotency-Key` replay;
        a reused key with a different body returns 409 `idempotency_conflict`
        instead of replaying the first project. A duplicate domain in the same
        workspace returns 409 `duplicate_domain`.
      operationId: createProject
      parameters:
        - $ref: '#/components/parameters/idempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                workspaceId:
                  type: string
                  description: >-
                    A workspace from `GET /api/mcp/workspaces` whose
                    `canCreateProjects` is true.
                domain:
                  type: string
                  description: The brand's website domain, e.g. example.com
                brandName:
                  type: string
                  description: The brand's name, as it's referred to in prompts and reports
                brandSummary:
                  type: string
                  description: >-
                    2-3 sentences: what the brand sells, who it serves, and what
                    makes it distinct
                brandNameDisambiguation:
                  type: string
                  description: >-
                    When the name is ambiguous, a short note on which brand this
                    is; empty when the name is distinctive
                reach:
                  type: string
                  enum:
                    - global
                    - national-global
                    - nationwide
                    - regional
                    - local
                  description: >-
                    Where the brand sells; national-global is a primary market
                    plus international reach
                country:
                  type: string
                  description: >-
                    Where most customers are: an ISO 3166-1 alpha-2 code, e.g.
                    GB
                city:
                  type: string
                  description: City or area, for regional or local reach
                language:
                  type: string
                  description: >-
                    Language for the prompts, e.g. en-GB; defaults from the
                    country
                competitors:
                  type: array
                  minItems: 1
                  maxItems: 20
                  description: Direct competitors, each a website domain or {domain, name}
                  items:
                    oneOf:
                      - type: string
                      - type: object
                        properties:
                          domain:
                            type: string
                          name:
                            type: string
                        required:
                          - domain
                brandAliases:
                  type: array
                  maxItems: 25
                  items:
                    type: string
                  description: Other names the brand goes by, counted as mentions of it
                name:
                  type: string
                  description: Project name; defaults to the brand name
                description:
                  type: string
                generatePrompts:
                  type: boolean
                  description: >-
                    Start the app's prompt generation in the background (tracked
                    prompts, within the prompt allowance)
              required:
                - workspaceId
                - domain
                - brandName
                - brandSummary
                - reach
                - country
                - competitors
                - generatePrompts
      responses:
        '200':
          description: Project created.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
            X-Idempotent-Replay:
              $ref: '#/components/headers/XIdempotentReplay'
            X-Idempotent-Skipped:
              $ref: '#/components/headers/XIdempotentSkipped'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateProjectResponse'
        '400':
          $ref: '#/components/responses/defaultError'
        '401':
          $ref: '#/components/responses/defaultError'
        '403':
          $ref: '#/components/responses/defaultError'
        '409':
          $ref: '#/components/responses/idempotencyInFlight'
        '429':
          $ref: '#/components/responses/rateLimited'
components:
  parameters:
    idempotencyKey:
      name: Idempotency-Key
      in: header
      schema:
        type: string
      description: >-
        Optional client-generated key (e.g. a UUID). Retrying with the same key
        within 24h replays the original stored response (`X-Idempotent-Replay:
        true`) instead of repeating the side effect. See
        [Idempotency](/api-reference/introduction#idempotency).
  headers:
    XRequestId:
      description: This request's id. Include it when contacting support.
      schema:
        type: string
        format: uuid
    RateLimit:
      description: >-
        IETF draft rate-limit header:
        `"default";r=<remaining>;t=<seconds-until-reset>`. Omitted on responses
        where the limiter did not run (e.g. a pre-auth validation error, or a
        degraded limiter failing open).
      schema:
        type: string
    RateLimitPolicy:
      description: >-
        IETF draft rate-limit policy: `"default";q=<quota>;w=<window-seconds>`.
        Currently `q=600;w=60`.
      schema:
        type: string
    XRateLimitLimit:
      description: Requests allowed per window (600/minute per key).
      schema:
        type: integer
    XRateLimitRemaining:
      description: Requests remaining in the current window.
      schema:
        type: integer
    XRateLimitReset:
      description: Absolute Unix-epoch second the current window resets.
      schema:
        type: integer
    XIdempotentReplay:
      description: >-
        `true` when this response is a replay of a previously stored successful
        response for the same `Idempotency-Key`.
      schema:
        type: string
        enum:
          - 'true'
    XIdempotentSkipped:
      description: >-
        `body-too-large` when a successful response exceeded the 100KB
        idempotency-store cap and was not cached (the request still ran
        normally).
      schema:
        type: string
        enum:
          - body-too-large
    RetryAfter:
      description: >-
        Seconds to wait before retrying. Set on 429s issued by Searchable's own
        rate limiter and on `409 idempotency_in_flight`; may be absent when an
        upstream provider (e.g. Google) rate-limits.
      schema:
        type: integer
  schemas:
    CreateProjectResponse:
      type: object
      properties:
        project:
          $ref: '#/components/schemas/ProjectLifecycleRecord'
        success:
          type: boolean
        promptGeneration:
          type: string
          enum:
            - started
            - not_requested
      required:
        - project
        - success
    ProjectLifecycleRecord:
      type: object
      description: >-
        The project shape create_project returns — curated, not the raw internal
        row (no userId, settings, workspaceId, or pitch fields; see the sibling
        ProjectListItem, which strips workspaceId the same way).
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        domain:
          type:
            - string
            - 'null'
        description:
          type:
            - string
            - 'null'
        iconUrl:
          type:
            - string
            - 'null'
        isActive:
          type: boolean
        currentRevision:
          type: integer
          description: >-
            Optimistic-concurrency counter — pass as `expectedRevision` on the
            next write to detect a concurrent change.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - name
        - isActive
        - currentRevision
    Problem:
      type: object
      description: >-
        RFC 9457 `application/problem+json` error body. `error` is retained
        verbatim as a legacy compat key equal to `message`. Some codes carry
        additional fields beyond the base shape (documented per-code in the
        [error reference](/api/errors)) — always additive, never replacing
        these.
      properties:
        type:
          type: string
          format: uri
          description: >-
            A URL identifying the error kind — the error reference page,
            anchored to `code`.
        title:
          type: string
          description: Human-readable summary of `code`.
        status:
          type: integer
          description: The HTTP status code (matches the response status).
        code:
          type: string
          description: >-
            Machine-readable, stable error code — safe to branch on. See the
            [error reference](/api/errors) for the full catalog.
          enum:
            - unauthorized
            - forbidden
            - missing_scope
            - plan_upgrade_required
            - not_found
            - invalid_argument
            - invalid_country
            - no_domain
            - no_workspace
            - no_pages
            - bulk_limit_exceeded
            - quota_exceeded
            - project_not_runnable
            - pitch_not_supported
            - rate_limited
            - idempotency_in_flight
            - query_timeout
            - gsc_not_connected
            - gsc_site_not_linked
            - gsc_access_denied
            - ga4_not_connected
            - traffic_not_connected
            - internal_error
        error:
          type: string
          description: Legacy compat key. Always equal to `message`.
        message:
          type: string
          description: Human-readable error message (identical to `error`).
        howToFix:
          type: string
          description: Present on actionable errors — a concrete next step.
        requestId:
          type: string
          format: uuid
          description: This request's id. Include it when contacting support.
        requiresUpgrade:
          type: boolean
          description: Present on `plan_upgrade_required` (403).
        retryable:
          type: boolean
          description: >-
            Present on `rate_limited`, `idempotency_in_flight`, and
            `query_timeout`.
        timeout:
          type: boolean
          description: Present on `query_timeout` (504).
        quotaExceeded:
          type: boolean
          description: Present on `quota_exceeded` (403).
        current:
          type: integer
          description: Present on `quota_exceeded` — current usage.
        limit:
          type: integer
          description: Present on `quota_exceeded` — the plan's limit.
        bulkLimitExceeded:
          type: boolean
          description: Present on `bulk_limit_exceeded` (400, `POST /audits`).
        requested:
          type: integer
          description: >-
            Present on `bulk_limit_exceeded` / `quota_exceeded` — the count
            requested.
        maxAllowed:
          type: integer
          description: Present on `bulk_limit_exceeded` — the plan's per-request cap.
        details:
          description: >-
            Present on some `invalid_argument` (400) responses — a Zod
            `.flatten()` validation breakdown.
          type: object
          properties:
            formErrors:
              type: array
              items:
                type: string
            fieldErrors:
              type: object
              additionalProperties:
                type: array
                items:
                  type: string
      required:
        - type
        - title
        - status
        - code
        - error
        - message
  responses:
    defaultError:
      description: >-
        Error response. `code` is the machine-readable reason — see the [error
        reference](/api/errors) for the full catalog and remediation per code.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        RateLimit:
          $ref: '#/components/headers/RateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    idempotencyInFlight:
      description: >-
        Another request with the same `Idempotency-Key` is still executing.
        `Retry-After` (5 seconds) is always present — retry with the SAME key
        once it elapses.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        RateLimit:
          $ref: '#/components/headers/RateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    rateLimited:
      description: >-
        Rate limited. Usually the per-API-key REST limit (600 requests/minute);
        on Google-backed endpoints it can also relay an upstream Google rate
        limit. `Retry-After` (seconds) is present when the limit was applied by
        Searchable's own rate limiter; it may be absent when an upstream
        provider rate-limits.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        RateLimit:
          $ref: '#/components/headers/RateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: sea_xxxxx
      description: >-
        A Searchable API key, created under **Settings → Workspace →
        Integrations**. Send as `Authorization: Bearer sea_xxxxx`. Every key
        carries one or more scopes (`read`, `write`, `admin`) and may optionally
        be bound to a single project — see [Getting
        started](/api-reference/introduction#authentication).

````

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