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

# Compare stored screenshots



## OpenAPI

````yaml /api-reference/openapi.json post /render/diff
openapi: 3.1.0
info:
  title: Scrinly Browser API
  version: 1.0.0
  description: >-
    Public screenshot, region, Visual Style Guide, visual diff, monitoring,
    batch, job-status, and usage API.
servers:
  - url: https://api.scrinly.com
    description: Production
security:
  - BearerAuth: []
tags:
  - name: Screenshots
  - name: Batches
  - name: Diffs
  - name: Jobs
  - name: Usage
  - name: Monitors
  - name: Recipients
paths:
  /render/diff:
    post:
      tags:
        - Diffs
      summary: Compare stored screenshots
      operationId: createScreenshotDiff
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DiffRequest'
            example:
              before:
                media:
                  url: https://storage.example.com/before.jpg
              after:
                media:
                  url: https://storage.example.com/after.jpg
              mode: perceptual
              visualization: overlay
      responses:
        '200':
          description: Completed comparison
          headers:
            X-Scrinly-Storage-URL:
              $ref: '#/components/headers/StorageUrl'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DiffResponse'
        '202':
          $ref: '#/components/responses/AsyncAccepted'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '413':
          $ref: '#/components/responses/TooLarge'
        '422':
          $ref: '#/components/responses/DiffFailed'
components:
  schemas:
    DiffRequest:
      type: object
      required:
        - before
        - after
      properties:
        before:
          $ref: '#/components/schemas/DiffSide'
        after:
          $ref: '#/components/schemas/DiffSide'
        mode:
          type: string
          enum:
            - pixel
            - perceptual
          default: perceptual
        visualization:
          type: string
          enum:
            - overlay
            - heatmap
            - mask
            - none
          default: overlay
        async:
          type: boolean
          default: false
        webhookUrl:
          type: string
          format: uri
        webhookSecret:
          type: string
          writeOnly: true
        storage_provider:
          type: string
          enum:
            - b2
            - s3
            - r2
        storage_path:
          type: string
          default: diffs
      additionalProperties: false
    DiffResponse:
      type: object
      required:
        - success
        - type
        - before
        - after
        - diff
        - credits
      properties:
        success:
          type: boolean
          const: true
        type:
          type: string
          const: diff
        before:
          type: object
          properties:
            width:
              type: integer
            height:
              type: integer
            contentType:
              type: string
            sha256:
              type: string
        after:
          type: object
          properties:
            width:
              type: integer
            height:
              type: integer
            contentType:
              type: string
            sha256:
              type: string
        diff:
          type: object
          properties:
            version:
              type: string
              const: screenshot-diff-v2
            mode:
              type: string
              enum:
                - pixel
                - perceptual
            visualization:
              type: string
              enum:
                - overlay
                - heatmap
                - mask
                - none
            changed:
              type: boolean
            changedPixels:
              type: integer
            comparedPixels:
              type: integer
            differenceRatio:
              type: number
            similarity:
              type: number
            comparisonCoverage:
              type: number
            changedBounds:
              type: array
              maxItems: 128
              items:
                allOf:
                  - $ref: '#/components/schemas/Bounds'
                  - type: object
                    properties:
                      status:
                        type: string
                        enum:
                          - changed
                          - added
                          - removed
                      coordinateSpace:
                        type: string
                        enum:
                          - before
                          - after
            boundsTruncated:
              type: boolean
            omittedBounds:
              type: integer
            regionMatching:
              type: object
              properties:
                status:
                  type: string
                  enum:
                    - available
                    - unavailable
            regions:
              type: array
              items:
                $ref: '#/components/schemas/DiffRegion'
        media:
          oneOf:
            - $ref: '#/components/schemas/Media'
            - type: 'null'
        credits:
          $ref: '#/components/schemas/Credits'
    DiffSide:
      type: object
      required:
        - media
      properties:
        media:
          type: object
          required:
            - url
          properties:
            url:
              type: string
              format: uri
              pattern: ^https://
            contentType:
              type: string
            width:
              type: integer
            height:
              type: integer
            sha256:
              type: string
          additionalProperties: true
        regions:
          $ref: '#/components/schemas/Regions'
      additionalProperties: false
    Bounds:
      type: object
      required:
        - x
        - 'y'
        - width
        - height
      properties:
        x:
          type: integer
          minimum: 0
        'y':
          type: integer
          minimum: 0
        width:
          type: integer
          minimum: 1
        height:
          type: integer
          minimum: 1
    DiffRegion:
      type: object
      properties:
        status:
          type: string
          enum:
            - unchanged
            - changed
            - added
            - removed
        kind:
          type: string
        beforeId:
          type:
            - string
            - 'null'
        afterId:
          type:
            - string
            - 'null'
        differenceRatio:
          type: number
        similarity:
          type: number
        positionChanged:
          type: boolean
        sizeChanged:
          type: boolean
        bounds:
          $ref: '#/components/schemas/Bounds'
    Media:
      type: object
      required:
        - stored
        - url
        - contentType
      properties:
        stored:
          type: boolean
          const: true
        url:
          type: string
          format: uri
          description: Direct B2, S3, or R2 URL.
        key:
          type: string
        location:
          type: string
        contentType:
          type: string
          enum:
            - image/jpeg
            - image/png
        width:
          type: integer
        height:
          type: integer
        bytes:
          type: integer
        sha256:
          type: string
          pattern: ^[a-f0-9]{64}$
      additionalProperties: true
    Credits:
      type: object
      required:
        - charged
        - refunded
        - net
      properties:
        charged:
          type: integer
          minimum: 0
        refunded:
          type: integer
          minimum: 0
        net:
          type: integer
          minimum: 0
    AsyncAccepted:
      type: object
      required:
        - success
        - id
        - statusUrl
      properties:
        success:
          type: boolean
          const: true
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - screenshot
            - diff
            - transform
        statusUrl:
          type: string
        message:
          type: string
        credits:
          $ref: '#/components/schemas/Credits'
    Error:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          const: false
        error:
          type: string
        type:
          type: string
        code:
          type: string
        retryable:
          type: boolean
        fields:
          type: array
          items:
            $ref: '#/components/schemas/ErrorField'
        credits:
          $ref: '#/components/schemas/Credits'
    Regions:
      type: object
      required:
        - version
        - coordinateSpace
        - screenshot
        - limits
        - items
        - coverage
      properties:
        version:
          type: string
          enum:
            - regions-v1
            - regions-v2
          description: >-
            New captures return regions-v2. Saved v1 manifests remain valid diff
            inputs, including mixed-version comparisons.
        coordinateSpace:
          type: string
          const: screenshot_pixels
        screenshot:
          type: object
          properties:
            width:
              type: integer
            height:
              type: integer
            sha256:
              type: string
          required:
            - width
            - height
            - sha256
        limits:
          type: object
          properties:
            maxRegionHeight:
              type: integer
              const: 1600
            maxAssets:
              type: integer
              const: 32
          required:
            - maxRegionHeight
            - maxAssets
        items:
          type: array
          maxItems: 32
          items:
            $ref: '#/components/schemas/Region'
        coverage:
          $ref: '#/components/schemas/Coverage'
    ErrorField:
      type: object
      required:
        - field
        - message
      properties:
        field:
          type: string
        message:
          type: string
    Region:
      type: object
      required:
        - id
        - order
        - kind
        - label
        - confidence
        - evidenceKinds
        - bounds
        - parts
      properties:
        id:
          type: string
        order:
          type: integer
          minimum: 0
        kind:
          type: string
          enum:
            - navigation
            - hero
            - content
            - features
            - pricing
            - testimonials
            - faq
            - logos
            - cta
            - footer
        label:
          type: string
        confidence:
          type: string
          enum:
            - high
            - medium
            - low
        evidenceKinds:
          type: array
          items:
            type: string
        bounds:
          $ref: '#/components/schemas/Bounds'
        parts:
          type: array
          items:
            $ref: '#/components/schemas/RegionPart'
        spec:
          $ref: '#/components/schemas/RegionSpec'
    Coverage:
      type: object
      properties:
        ratio:
          type: number
          minimum: 0
          maximum: 1
        truncated:
          type: boolean
        omittedAssets:
          type: integer
          minimum: 0
        segmentationDegraded:
          type: boolean
          description: >-
            True when unresolved geometry fallback was needed. Included in new
            v2 captures; absent from historical v1 manifests.
        safeCuts:
          type: integer
          minimum: 0
        forcedCuts:
          type: integer
          minimum: 0
      additionalProperties: true
    RegionPart:
      type: object
      required:
        - id
        - index
        - bounds
        - media
      properties:
        id:
          type: string
        index:
          type: integer
          minimum: 0
        bounds:
          $ref: '#/components/schemas/Bounds'
        media:
          $ref: '#/components/schemas/Media'
    RegionSpec:
      type: object
      required:
        - summary
        - claims
        - confidence
        - evidencePartIds
      properties:
        summary:
          type: string
        claims:
          type: array
          items:
            $ref: '#/components/schemas/StyleClaim'
        confidence:
          type: string
          enum:
            - high
            - medium
            - low
        evidencePartIds:
          type: array
          items:
            type: string
    StyleClaim:
      type: object
      required:
        - category
        - basis
        - statement
      properties:
        category:
          type: string
          enum:
            - visual_role
            - layout
            - hierarchy
            - color
            - typography
            - spacing
            - components
            - states
            - motion
            - responsive
        basis:
          type: string
          enum:
            - observed
            - inferred
        statement:
          type: string
  headers:
    StorageUrl:
      description: Direct URL for the complete stored output.
      schema:
        type: string
        format: uri
  responses:
    AsyncAccepted:
      description: Job accepted
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/AsyncAccepted'
    BadRequest:
      description: Validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Invalid or missing Scrinly key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentRequired:
      description: Credit allowance exhausted
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    TooLarge:
      description: Request or image exceeds limits
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    DiffFailed:
      description: Source integrity or diff processing failed; credit refunded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Scrinly API key

````

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