Customers

Import customers from CSV with structured preview

Imports multiple customers from a CSV file with full preview of all records. **Key features**: - **Structured preview**: Returns all parsed records (valid and with errors) - **Parallel validation**: NIFs validated concurrently against VeriFactu - **Granular feedback**: Customer-specific errors and warnings - **Editable data**: Structured JSON for editable table in frontend **Recommended flow**: 1. **Initial upload**: Call with `dry_run=true` to get preview 2. **Display table**: Frontend shows parsed data with errors/warnings 3. **Inline editing**: User corrects data directly in the table 4. **Final import**: Send corrected data with `dry_run=false` **Format**: Must follow CSV template format (downloadable from `/customers/template-csv`). **Security limits**: - Max size: 5MB - Max 1,000 records per file - Rate limiting: 3 imports per hour **Validation**: - Required headers per template - Full validation of each row with business rules - Parallel NIF validation against AEAT registry (VeriFactu) - Duplicate detection in CSV and database **Validation statuses**: - `VALID`: Customer valid, ready to import - `WARNING`: Customer valid but with warnings (eg: missing email) - `ERROR`: Customer invalid, cannot process - `DUPLICATE`: Duplicate customer (in CSV or DB) - `NIF_INVALID`: NIF invalid in AEAT registry


POST
/v1/customers/import-csv-preview
AuthorizationBearer <token>

API Key authentication.

Format: Authorization: Bearer beel_sk_<key>

Obtaining Keys: API Keys are managed from the BeeL dashboard

Security: API Keys are secret credentials. Do not share them or store them in source code

In: header

filestring

CSV file with customers to import

dry_run?boolean

If true (recommended initially): preview only without persistence. If false: preview + persistence of valid customers.

Defaulttrue

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://app.beel.es/api/v1/customers/import-csv-preview" \  -F file="string"
{
  "success": true,
  "data": {
    "metadata": {
      "total_customers": 10,
      "is_dry_run": true,
      "processing_time_ms": 450,
      "source_type": "CSV_IMPORT",
      "filename": "clientes_enero.csv",
      "file_size_bytes": 1048576,
      "total_rows": 250
    },
    "customers_validation": [
      {
        "index": 0,
        "customer": {
          "id": "123e4567-e89b-12d3-a456-426614174000",
          "legal_name": "Empresa Cliente SL",
          "trade_name": "EmpresaCliente",
          "nif": "12345678A",
          "address": {
            "street": "Calle Mayor, 123",
            "number": "123",
            "floor": "2º A",
            "door": "A",
            "postal_code": "28001",
            "city": "Madrid",
            "province": "Madrid",
            "country": "España",
            "country_code": "ES"
          },
          "phone": "+34 612 345 678",
          "email": "user@example.com",
          "web": "string",
          "billing_emails": [
            "user@example.com"
          ],
          "contact_person": "María García",
          "notes": "string",
          "preferred_payment_method": {
            "method": "BANK_TRANSFER",
            "iban": "ES1234567890123456789012",
            "swift": "ABCDESMMXXX",
            "payment_term_days": 30
          },
          "general_discount": 0,
          "active": true,
          "created_at": "2019-08-24T14:15:22Z",
          "updated_at": "2019-08-24T14:15:22Z",
          "alternative_id": {
            "type": "02",
            "number": "string",
            "country_code": "st"
          }
        },
        "status": "VALID",
        "errors": [
          {
            "field": "nif",
            "value": "12345678X",
            "message": "NIF not found in AEAT census"
          }
        ],
        "warnings": [
          {
            "field": "email",
            "message": "Email not provided, NIF will be used for invoicing"
          }
        ],
        "row_number": 15
      }
    ],
    "statistics": {
      "total_processed": 10,
      "valid": 6,
      "with_warnings": 2,
      "with_errors": 2,
      "duplicates": 1,
      "invalid_nifs": 1,
      "imported": 0,
      "success_rate": 0.8,
      "importable": 8,
      "not_importable": 2
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The provided data is not valid",
    "details": {
      "field": "specific error message",
      "file_size_mb": 0,
      "record_count": 0,
      "missing_headers": [
        "string"
      ]
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication required"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The provided data is not valid",
    "details": {
      "field": "specific error message"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The provided data is not valid",
    "details": {
      "field": "specific error message"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The provided data is not valid",
    "details": {
      "field": "specific error message"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}