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>

Scopes: API Keys use the same scopes as OAuth2 tokens. Each key is created with specific scopes that limit which endpoints it can access. The required scope for each endpoint is documented in the operation's security section under OAuth2.

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": "NIF_IVA",
            "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"
  }
}