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

# Bulk import products/services from a CSV file

> Uploads a CSV file (multipart/form-data, field name "file") and creates one product per data row. Required columns: description, productKey, price. Optional columns: unitKey (default H87), unitName, sku, taxIncluded, taxability, livemode — same field names as the JSON create endpoint. Each row is validated individually against the SAT product/unit key catalogs before creating it — rows with invalid SAT keys are never created silently. Processing is partial: valid rows are created even if other rows fail, and every failure is reported with its row number and reason.



## OpenAPI

````yaml https://api.timbrix.mx/api/openapi.json post /products/import
openapi: 3.0.0
info:
  title: Timbrix API
  description: >-
    API de facturación electrónica CFDI 4.0 para México, con servidor OAuth2
    para gestionar organizaciones, miembros y webhooks. Compatible con agentes
    de IA — ver la extensión `x-ai-agent-friendly` en la raíz de esta spec.


    REST API with OAuth2 server for managing organizations, members, and
    webhooks.
  version: '1.0'
  contact: {}
servers: []
security: []
tags:
  - name: organizations
    description: Organization management endpoints
  - name: oauth
    description: OAuth2 authentication and authorization
  - name: webhooks
    description: Webhook configuration and delivery
  - name: users
    description: User information endpoints
  - name: api-keys
    description: API Keys management and validation
paths:
  /products/import:
    post:
      tags:
        - products
      summary: Bulk import products/services from a CSV file
      description: >-
        Uploads a CSV file (multipart/form-data, field name "file") and creates
        one product per data row. Required columns: description, productKey,
        price. Optional columns: unitKey (default H87), unitName, sku,
        taxIncluded, taxability, livemode — same field names as the JSON create
        endpoint. Each row is validated individually against the SAT
        product/unit key catalogs before creating it — rows with invalid SAT
        keys are never created silently. Processing is partial: valid rows are
        created even if other rows fail, and every failure is reported with its
        row number and reason.
      operationId: ProductsController_importCsv
      parameters:
        - name: X-Organization-Id
          in: header
          description: >-
            Required for Supabase session auth. Ignored when authenticating with
            an API key (the organization resolves from the key).
          required: false
          schema:
            type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
      responses:
        '201':
          description: Import summary with per-row success/error detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportProductsCsvResponseDto'
        '400':
          description: Missing X-Organization-Id header for a session request
      security:
        - apiKey: []
        - bearer: []
components:
  schemas:
    ImportProductsCsvResponseDto:
      type: object
      properties:
        totalRows:
          type: number
          example: 50
          description: Total de filas de datos procesadas (sin contar el encabezado)
        successCount:
          type: number
          example: 47
          description: Número de productos creados exitosamente
        errorCount:
          type: number
          example: 3
          description: Número de filas que fallaron y no generaron un producto
        errors:
          description: Detalle de errores por fila
          type: array
          items:
            $ref: '#/components/schemas/ImportProductsCsvRowErrorDto'
      required:
        - totalRows
        - successCount
        - errorCount
        - errors
    ImportProductsCsvRowErrorDto:
      type: object
      properties:
        row:
          type: number
          example: 3
          description: >-
            Número de fila en el archivo CSV (la fila 1 es el encabezado, la
            primera fila de datos es la 2)
        message:
          type: string
          example: >-
            La clave de producto o servicio "99999999" no existe en el catálogo
            SAT (c_ClaveProdServ)
          description: Motivo por el que la fila no se pudo importar
      required:
        - row
        - message
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: 'API Key for authentication (format: sk_...)'
    bearer:
      scheme: bearer
      bearerFormat: JWT
      type: http

````