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

# Extract GTINs from a product photo via Claude Vision

> Server-side fallback for in-browser Tesseract.js OCR. Uploads a single product photo (JPEG/PNG/GIF/WebP) to Claude Vision, asks the vision model for barcode digit sequences, then keeps only candidates that pass the GS1 mod-10 check digit. The response is always shaped — on any backend failure it returns an empty ``candidates`` list rather than surfacing the error, so the calling UI can fall through to a manual-entry prompt without bespoke error handling.



## OpenAPI

````yaml /openapi/openapi-dashboard.json post /dashboard/api/v1/ocr/gtin
openapi: 3.1.0
info:
  title: Brand Dashboard API
  version: 1.0.0
  description: >
    Endpoints powering the brand dashboard: catalogue completeness, product
    images, nutrition and document management, OCR extraction, brand analytics,
    and data export. Every endpoint is scoped to an organization you are a
    member of — pass an org-scoped API key, or authenticate with a session, and
    you reach exactly the organizations your account belongs to. This is the
    same surface the Closient dashboard UI itself uses, so anything you can do
    in the dashboard you can do here.


    ## Authentication


    All endpoints require an API key passed via the `X-API-Key` HTTP header,
    unless otherwise noted.


    ```

    X-API-Key: csb_<body>_<checksum>

    ```


    Generate API keys in **Settings > API Keys** in your dashboard, or via the
    Account API.

    Session-based (cookie) authentication is also accepted for browser-based
    access.


    ## Rate Limits


    | Tier        | Requests / minute | Requests / day |

    |-------------|-------------------|----------------|

    | Default     | 300               | 10,000         |

    | Custom      | Contact us        | Contact us     |


    Rate-limit headers are included on every response so callers can
    self-throttle without

    hitting our 429s ("informed governor"):


    - `RateLimit-Policy` — every active window, e.g. `300;w=60, 10000;w=86400`

    - `RateLimit-Limit` — quota for the **most-restrictive** currently-active
    window

    - `RateLimit-Remaining` — requests left in that window

    - `RateLimit-Reset` — seconds until that window resets (relative; clock-skew
    safe)


    Legacy `X-RateLimit-*` aliases are also emitted for back-compat.
    `X-RateLimit-Reset`

    keeps the absolute Unix-timestamp shape to avoid breaking existing
    consumers.


    When rate-limited, you receive `429 Too Many Requests` with a
    `retry_after_seconds` field

    in the error envelope and a `Retry-After` header.


    ## Pagination


    List endpoints return paginated results in this envelope:


    ```json

    {
      "data": [...],
      "pagination": {
        "page": 1,
        "page_size": 25,
        "total_count": 342,
        "total_pages": 14,
        "has_next": true,
        "has_previous": false
      }
    }

    ```


    Use `?page=2&page_size=50` query parameters. Maximum page size is 100.


    ## Error Responses


    All errors conform to [RFC 9457 Problem
    Details](https://www.rfc-editor.org/rfc/rfc9457)

    with `Content-Type: application/problem+json`:


    ```json

    {
      "type": "https://closient.com/docs/errors/not_found",
      "title": "Not Found",
      "status": 404,
      "detail": "The requested resource was not found.",
      "error_code": "not_found",
      "retryable": false,
      "timestamp": "2026-03-31T12:00:00+00:00"
    }

    ```


    Common error codes: `unauthorized` (401), `forbidden` (403), `not_found`
    (404),

    `validation_error` (422), `rate_limited` (429), `internal_error` (500).
  termsOfService: https://www.closient.com/terms/
servers:
  - url: https://www.closient.com
security: []
externalDocs:
  description: Closient Documentation
  url: https://docs.closient.com
paths:
  /dashboard/api/v1/ocr/gtin:
    post:
      tags:
        - OCR
      summary: Extract GTINs from a product photo via Claude Vision
      description: >-
        Server-side fallback for in-browser Tesseract.js OCR. Uploads a single
        product photo (JPEG/PNG/GIF/WebP) to Claude Vision, asks the vision
        model for barcode digit sequences, then keeps only candidates that pass
        the GS1 mod-10 check digit. The response is always shaped — on any
        backend failure it returns an empty ``candidates`` list rather than
        surfacing the error, so the calling UI can fall through to a
        manual-entry prompt without bespoke error handling.
      operationId: apps_dashboard_api_ocr_extract_gtin_from_image
      parameters: []
      requestBody:
        content:
          multipart/form-data:
            schema:
              properties:
                image:
                  description: Product photo to scan for GTINs (JPEG, PNG, GIF, or WebP).
                  format: binary
                  title: Image
                  type: string
              required:
                - image
              title: FileParams
              type: object
        required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GtinOcrResponse'
        '400':
          description: Bad Request
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorOut'
        '401':
          description: Unauthorized
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorOut'
        '403':
          description: Forbidden
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorOut'
        '404':
          description: Not Found
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorOut'
        '405':
          description: Method Not Allowed
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorOut'
        '422':
          description: Unprocessable Content
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorOut'
        '429':
          description: Too Many Requests
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ErrorOut'
      security:
        - APIKeyHeaderAuth: []
        - OAuthTokenAuth: []
        - CookieGatedSessionAuth: []
components:
  schemas:
    GtinOcrResponse:
      description: Validated GTIN candidates extracted from a product photo.
      examples:
        - candidates:
            - '00614141000012'
            - '05901234123457'
          source: bedrock
      properties:
        candidates:
          description: >-
            Zero or more GTIN candidates that pass the GS1 mod-10 check digit.
            Strings are zero-padded to 14 digits. Empty when the model returned
            nothing usable or Bedrock errored — callers should treat empty as
            'OCR found no GTIN' rather than a transport failure.
          items:
            description: >-
              GTIN barcode digits. Accepts 8/12/13/14 digit forms; the resolver
              and storage layers normalize to GTIN-14 by left-padding with
              zeros.
            examples:
              - '00614141000012'
            pattern: ^\d{8,14}$
            type: string
          title: Candidates
          type: array
        source:
          $ref: '#/components/schemas/GtinOcrSourceEnum'
          description: >-
            Backend that produced the candidates. Currently always ``bedrock``;
            reserved as an enum for future server-side OCR fallbacks.
          examples:
            - bedrock
      required:
        - candidates
        - source
      title: GtinOcrResponse
      type: object
    ErrorOut:
      description: |-
        RFC 9457 Problem Details response.

        All API errors are returned in this format with Content-Type:
        application/problem+json.
      examples:
        - detail: The requested resource was not found.
          error_code: not_found
          retryable: false
          status: 404
          timestamp: '2026-03-31T12:00:00+00:00'
          title: Not Found
          type: https://closient.com/docs/errors/not_found
        - detail: Validation error.
          details:
            - loc:
                - body
                - name
              msg: Field required
              type: missing
          error_code: validation_error
          retryable: false
          status: 422
          timestamp: '2026-03-31T12:00:00+00:00'
          title: Validation Error
          type: https://closient.com/docs/errors/validation_error
        - detail: Rate limit exceeded. Please try again later.
          error_code: rate_limited
          retry_after: 31
          retryable: true
          status: 429
          timestamp: '2026-03-31T12:00:00+00:00'
          title: Rate Limited
          type: https://closient.com/docs/errors/rate_limited
      properties:
        type:
          description: URI reference identifying the error type.
          title: Type
          type: string
        title:
          description: Short human-readable summary of the error.
          title: Title
          type: string
        status:
          description: HTTP status code.
          title: Status
          type: integer
        detail:
          description: Human-readable explanation of this specific occurrence.
          title: Detail
          type: string
        error_code:
          description: Machine-readable error code (e.g. not_found, unauthorized).
          title: Error Code
          type: string
        retryable:
          default: false
          description: Whether retrying the same request can succeed.
          title: Retryable
          type: boolean
        timestamp:
          description: ISO 8601 timestamp of when the error occurred.
          title: Timestamp
          type: string
        retry_after:
          anyOf:
            - type: integer
            - type: 'null'
          description: Seconds to wait before retrying (when applicable).
          title: Retry After
        owner_action_required:
          anyOf:
            - type: boolean
            - type: 'null'
          description: Whether the error requires account owner intervention.
          title: Owner Action Required
        details:
          description: Additional context (validation errors, etc.).
          title: Details
      required:
        - type
        - title
        - status
        - detail
        - error_code
        - timestamp
      title: ErrorOut
      type: object
    GtinOcrSourceEnum:
      description: >-
        Backend that produced the OCR candidates.


        Currently only ``bedrock`` is emitted (Bedrock Vision via Anthropic
        Claude).

        Reserved as an enum so future server-side fallbacks (e.g. ``tesseract``,

        ``rekognition``) can be added without breaking the response shape.
      enum:
        - bedrock
      title: GtinOcrSourceEnum
      type: string
  securitySchemes:
    APIKeyHeaderAuth:
      type: apiKey
      in: header
      name: X-API-Key
    OAuthTokenAuth:
      type: http
      scheme: bearer
    CookieGatedSessionAuth:
      type: apiKey
      in: cookie
      name: sessionid

````