openapi: 3.1.0
info:
  title: Browserbeam API
  version: "1.0"
  description: |
    LLM-optimized browser automation API. Create browser sessions, execute steps (navigate, click, fill, extract, screenshot), and get structured page state back.

    ## Authentication
    All endpoints require a Bearer token via the `Authorization` header:
    ```
    Authorization: Bearer sk_live_your_api_key
    ```

    ## Concepts
    - **Session** — an isolated browser tab with its own cookies, storage, and viewport.
    - **Steps** — sequential browser actions sent as a JSON array.
    - **Refs** — stable element identifiers (e1, e2, ...) assigned during observation.
    - **Auto-observe** — every successful call returns fresh page state automatically.
  contact:
    name: Browserbeam
    url: https://browserbeam.com
  license:
    name: Proprietary

servers:
  - url: https://api.browserbeam.com
    description: Production

security:
  - BearerAuth: []

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: "API key prefixed with `sk_live_` or `sk_test_`"

  headers:
    X-RateLimit-Limit:
      description: Requests allowed per minute
      schema:
        type: integer
        example: 600
    X-RateLimit-Remaining:
      description: Requests remaining in current window
      schema:
        type: integer
        example: 598
    X-RateLimit-Reset:
      description: Unix timestamp when window resets
      schema:
        type: integer
        example: 1679148060
    X-Request-Id:
      description: Unique request identifier for debugging
      schema:
        type: string
        example: req_8f3a2bc1d4e5
    Retry-After:
      description: Seconds to wait before retrying
      schema:
        type: integer
        example: 30

  schemas:
    Step:
      type: object
      description: "A step object with exactly one key (the step type) and its params as the value."
      minProperties: 1
      maxProperties: 1
      additionalProperties:
        type: object
      example:
        click:
          ref: "e3"

    PageState:
      type: object
      properties:
        url:
          type: string
          example: "https://example.com"
        title:
          type: string
          example: "Example Domain"
        stable:
          type: boolean
        markdown:
          type: object
          properties:
            content:
              type: string
            length:
              type: object
              properties:
                shown:
                  type: integer
                total:
                  type: integer
        interactive_elements:
          type: array
          items:
            type: object
            properties:
              ref:
                type: string
                example: "e1"
              tag:
                type: string
                example: "a"
              role:
                type: string
                example: "link"
              label:
                type: string
                example: "More information..."
              value:
                type: string
        forms:
          type: array
          items:
            type: object
        changes:
          type: object
          nullable: true
          properties:
            content_changed:
              type: boolean
            content_delta:
              type: string
              nullable: true
            elements_added:
              type: array
              items:
                type: object
            elements_removed:
              type: array
              items:
                type: object
        scroll:
          type: object
          properties:
            y:
              type: integer
            height:
              type: integer
            viewport:
              type: integer
            percent:
              type: integer

    MediaItem:
      type: object
      properties:
        type:
          type: string
          enum: [screenshot, pdf]
        format:
          type: string
          example: "png"
        data:
          type: string
          description: Base64-encoded binary data

    StepError:
      type: object
      properties:
        step:
          type: integer
          description: Zero-indexed step that failed
        action:
          type: string
          description: Step type that failed
        code:
          type: string
          enum: [element_not_found, navigation_failed, captcha_detected, captcha_unsolvable, access_denied, action_failed, extract_failed, invalid_request]
        message:
          type: string
        context:
          type: object

    SessionEnvelope:
      type: object
      properties:
        session_id:
          type: string
          pattern: "^ses_"
          example: "ses_abc123def456"
        expires_at:
          type: string
          format: date-time
        request_id:
          type: string
          pattern: "^req_"
          example: "req_8f3a2bc1d4e5"
        completed:
          type: integer
          description: Number of steps successfully executed
        page:
          $ref: "#/components/schemas/PageState"
          nullable: true
        media:
          type: array
          items:
            $ref: "#/components/schemas/MediaItem"
        extraction:
          type: object
          nullable: true
          description: "Structured extraction results. null when no extract steps are used."
        blockers_dismissed:
          type: array
          items:
            type: string
          example: ["cookie_consent"]
        error:
          $ref: "#/components/schemas/StepError"
          nullable: true

    SessionInfo:
      type: object
      properties:
        session_id:
          type: string
          example: "ses_abc123def456"
        status:
          type: string
          enum: [active, closed, failed]
        started_at:
          type: string
          format: date-time
        ended_at:
          type: string
          format: date-time
          nullable: true
        duration_seconds:
          type: integer
          nullable: true
        expires_at:
          type: string
          format: date-time
        error_code:
          type: string
          nullable: true
          description: When status is `failed`, engine error code (e.g. `access_denied`, `captcha_unsolvable`)
        error_message:
          type: string
          nullable: true
          description: Human-readable details when the session failed

    SessionListItem:
      type: object
      properties:
        session_id:
          type: string
        status:
          type: string
        started_at:
          type: string
          format: date-time

    Error:
      type: object
      required: [error]
      properties:
        error:
          type: object
          required: [code, message]
          properties:
            code:
              type: string
            message:
              type: string
            context:
              type: object

  responses:
    Unauthorized:
      description: Missing or invalid API key
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: unauthorized
              message: Invalid API key

    RateLimited:
      description: Rate limit exceeded
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
        Retry-After:
          $ref: "#/components/headers/Retry-After"
        X-RateLimit-Limit:
          $ref: "#/components/headers/X-RateLimit-Limit"
        X-RateLimit-Remaining:
          $ref: "#/components/headers/X-RateLimit-Remaining"
        X-RateLimit-Reset:
          $ref: "#/components/headers/X-RateLimit-Reset"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: rate_limited
              message: Rate limit exceeded. Try again shortly.

    QuotaExceeded:
      description: Runtime quota exhausted
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
        Retry-After:
          $ref: "#/components/headers/Retry-After"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: quota_exceeded
              message: Runtime quota exhausted. Upgrade your plan for more hours.

    SessionNotFound:
      description: Session not found or expired
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: session_not_found
              message: Session ses_nonexistent not found

    EngineUnavailable:
      description: Browser engine temporarily unavailable
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
        Retry-After:
          $ref: "#/components/headers/Retry-After"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: engine_unavailable
              message: Browser engine is temporarily unavailable. Please retry.

paths:
  /v1/sessions:
    post:
      operationId: createSession
      summary: Create a browser session
      description: |
        Create a new browser session. Optionally navigate to a URL and/or execute steps in the same call.

        **Behavior matrix:**
        | url | steps | Result |
        |-----|-------|--------|
        | — | — | Bare session, no page loaded |
        | set | — | Navigate → auto-observe → page state returned |
        | set | set | Navigate → run steps → auto-observe |
        | — | set | Run steps (first should be `goto`) |
      tags: [Sessions]
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Unique key for idempotent session creation. Duplicate keys return the cached response.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  description: Navigate to this URL after creation
                steps:
                  type: array
                  items:
                    $ref: "#/components/schemas/Step"
                  description: Steps to execute after navigation
                timeout:
                  type: integer
                  minimum: 10
                  maximum: 1800
                  default: 300
                  description: Session lifetime in seconds
                viewport:
                  type: object
                  properties:
                    width:
                      type: integer
                      default: 1280
                    height:
                      type: integer
                      default: 720
                user_agent:
                  type: string
                locale:
                  type: string
                  example: "en-US"
                timezone:
                  type: string
                  example: "America/New_York"
                proxy:
                  description: "All sessions are routed through a proxy (datacenter by default). Pass an object to customize kind/country, or a string URL for bring-your-own proxy."
                  oneOf:
                    - type: object
                      properties:
                        kind:
                          type: string
                          enum: [datacenter, residential]
                          default: datacenter
                        country:
                          type: string
                          description: "ISO 3166-1 alpha-2 country code or `auto`"
                          default: "auto"
                          example: "us"
                    - type: string
                      description: "Bring-your-own proxy URL"
                      example: "http://user:pass@proxy:8080"
                block_resources:
                  type: array
                  default: [image, font]
                  description: "Resource types to block. Media (video/audio) is always blocked. Pass `[]` to unblock images and fonts."
                  items:
                    type: string
                    enum: [image, font, stylesheet, script]
                auto_dismiss_blockers:
                  type: boolean
                  default: true
                cookies:
                  type: array
                  description: "Cookie objects to inject before navigation"
                  items:
                    type: object
                    required: [name, value]
                    properties:
                      name:
                        type: string
                      value:
                        type: string
                      domain:
                        type: string
                        description: "Required if `url` is not set"
                      url:
                        type: string
                        description: "Required if `domain` is not set"
                      path:
                        type: string
                      expires:
                        type: number
                      httpOnly:
                        type: boolean
                      secure:
                        type: boolean
                      sameSite:
                        type: string
                        enum: [Strict, Lax, None]
      responses:
        "201":
          description: Session created
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionEnvelope"
        "400":
          description: Invalid request body
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          description: Rate limited or quota exceeded
          headers:
            Retry-After:
              $ref: "#/components/headers/Retry-After"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          $ref: "#/components/responses/EngineUnavailable"

    get:
      operationId: listSessions
      summary: List sessions
      description: List sessions for the authenticated API key with cursor-based pagination and status filtering.
      tags: [Sessions]
      parameters:
        - name: status
          in: query
          schema:
            type: string
            enum: [active, closed, failed]
          description: Filter by session status
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
          description: Results per page
        - name: after
          in: query
          schema:
            type: string
          description: "Cursor from `next_cursor` in previous response"
      responses:
        "200":
          description: Sessions list
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessions:
                    type: array
                    items:
                      $ref: "#/components/schemas/SessionListItem"
                  has_more:
                    type: boolean
                  next_cursor:
                    type: string
                    nullable: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"

  /v1/sessions/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          pattern: "^ses_"
        example: ses_abc123def456

    get:
      operationId: getSession
      summary: Get session info
      description: Get session status and metadata.
      tags: [Sessions]
      responses:
        "200":
          description: Session details
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionInfo"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/SessionNotFound"
        "429":
          $ref: "#/components/responses/RateLimited"

    delete:
      operationId: destroySession
      summary: Destroy a session
      description: Destroy a session and release browser resources. Runtime is recorded for billing.
      tags: [Sessions]
      responses:
        "204":
          description: Session destroyed
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/SessionNotFound"
        "429":
          $ref: "#/components/responses/RateLimited"

  /v1/sessions/{id}/act:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          pattern: "^ses_"
        example: ses_abc123def456

    post:
      operationId: executeSteps
      summary: Execute steps on a session
      description: |
        Execute steps on an existing session. Steps run sequentially. On failure, execution stops and the error is returned alongside the current page state.

        **Available step types:** `goto`, `observe`, `click`, `fill`, `type`, `select`, `check`, `scroll`, `scroll_collect`, `screenshot`, `wait`, `extract`, `upload`, `pdf`, `fill_form`, `close`
      tags: [Steps]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [steps]
              properties:
                steps:
                  type: array
                  minItems: 1
                  items:
                    $ref: "#/components/schemas/Step"
            examples:
              click:
                summary: Click an element
                value:
                  steps:
                    - click:
                        ref: "e3"
              fill_and_submit:
                summary: Fill form and submit
                value:
                  steps:
                    - fill_form:
                        fields:
                          Email: "user@example.com"
                          Password: "secret"
                        submit: true
              extract:
                summary: Extract structured data
                value:
                  steps:
                    - extract:
                        title: "h1 >> text"
                        links:
                          - "a >> href"
                        articles:
                          - _parent: ".article"
                            title: "h2 >> text"
                            url: "a >> href"
              screenshot:
                summary: Take a screenshot
                value:
                  steps:
                    - screenshot:
                        full_page: true
      responses:
        "200":
          description: Steps executed
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionEnvelope"
        "400":
          description: Invalid request (bad JSON, empty steps, unknown step type)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/SessionNotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/EngineUnavailable"

tags:
  - name: Sessions
    description: Create, inspect, list, and destroy browser sessions
  - name: Steps
    description: Execute browser automation steps on existing sessions
