# labs/openapi — OpenAPI 3.1 (generated)
---
openapi: 3.1.0
info:
  title: Accoil Labs API
  version: '1'
paths:
  "/{account_slug}/labs/products":
    post:
      operationId: create_product
      summary: Add a lead product to research
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                product:
                  type: object
                  properties:
                    name:
                      type: string
                    url:
                      type: string
                      format: uri
                      description: the product's site; scheme optional
                    description:
                      type: string
                      description: optional; normally filled by research
                  required:
                  - name
                  - url
              required:
              - product
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
  "/{account_slug}/labs/products/{id}":
    patch:
      operationId: update_product
      summary: Update a product's name, URL or description
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                product:
                  type: object
                  properties:
                    name:
                      type: string
                    url:
                      type: string
                      format: uri
                      description: the product's site; scheme optional
                    description:
                      type: string
                      description: optional; normally filled by research
              required:
              - product
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
  "/{account_slug}/labs/products/{product_id}/deliverables":
    post:
      operationId: generate_deliverable
      summary: Generate (or regenerate) one deliverable for this product
      description: 'One deliverable per (product, type): regenerating reuses the slot
        and replaces the content. Costs real AI spend against the account''s Labs
        spending cap; refused with a named reason when the cap is spent. A ready deliverable
        has a 24-hour regeneration cooldown; a failed one can be retried immediately.
        Throttled to 5 generations per account per minute (429 beyond that).'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                deliverable:
                  type: object
                  properties:
                    deliverable_type:
                      type: string
                      enum:
                      - product_analysis
                      - business_case
                      - tracking_plan
                      - customer_discovery
                      - engagement_playbook
                      - engagement_playbook_deep
                      - engagement_playbook_from_config
                      - whats_next
                      description: which report to generate; each type maps to one
                        Labs process
                  required:
                  - deliverable_type
              required:
              - deliverable
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
  "/{account_slug}/labs/products/{product_id}/intervention":
    post:
      operationId: run_intervention
      summary: Run the account intervention review (proof of concept)
      description: 'Assembles the demo account''s ledger, this product''s engagement
        playbook, and mocked Accoil/Intercom/HubSpot connector data into one payload,
        then runs the two-stage account-intervention process on it. Requires a ready
        engagement playbook for this product; refused otherwise. One intervention
        slot per product (across scenarios): running again replaces the previous review.
        Costs real AI spend against the account''s Labs spending cap.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                scenario:
                  type: string
                  enum:
                  - acme-inc
                  - beacon-labs
                  description: which demo account to review; defaults to acme-inc
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
  "/{account_slug}/labs/products/{product_id}/logo":
    post:
      operationId: fetch_logo
      summary: Discover and attach a logo for this product
      description: Queues a background fetch of the logo Brandfetch's CDN serves for
        the product URL's domain. Replaces the current logo when one is already attached;
        finding none leaves the product as it was.
      requestBody:
        description: No body — an empty request.
        required: false
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
  "/{account_slug}/labs/products/{product_id}/share_links":
    post:
      operationId: create_share_link
      summary: Create a public share portal for chosen reports
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                share_link:
                  type: object
                  properties:
                    label:
                      type: string
                      description: what you call this portal; viewers never see it
                    allowed_email_domains:
                      type: array
                      items:
                        type: string
                      description: domains whose emails pass the viewer gate; EMPTY
                        ADMITS NOBODY (fail closed). The HTML form also accepts a
                        comma-separated string.
                    expires_at:
                      type: string
                      format: date-time
                      description: optional; the portal 404s after this moment
                    deliverable_ids:
                      type: array
                      items:
                        type: integer
                      description: the reports to expose — required; nothing defaults
                        onto a portal
                  required:
                  - deliverable_ids
              required:
              - share_link
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
  "/{account_slug}/labs/products/{product_id}/share_links/{id}":
    delete:
      operationId: revoke_share_link
      summary: Revoke a share link
      description: 'Revokes rather than deletes: the portal stops answering immediately,
        but the link and its viewer history are kept.'
      requestBody:
        description: No body — an empty request.
        required: false
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
  "/share/{token}/viewers":
    post:
      operationId: pass_email_gate
      summary: Pass a share portal's email gate (public — no account token needed)
      description: Admits you when your email's domain is on the link's allow list,
        and sets a viewer cookie. An empty allow list admits nobody — ask the sender
        to add your domain.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                viewer:
                  type: object
                  properties:
                    email:
                      type: string
                      format: email
                      description: the work email the link was sent to
                  required:
                  - email
              required:
              - viewer
      responses:
        '200':
          description: OK
        '403':
          description: Read-only token, or not permitted
