Import contacts from Holded Excel
Imports multiple customers from an Excel file exported from Holded. **Key features**: - **Specific parsing**: Reads exact structure of Holded contacts Excel (29 columns) - **Automatic mapping**: Converts Holded contacts to Customer entities automatically - **Full validation**: Validates NIFs, addresses and required data - **Preview mode**: Allows viewing parsed data before importing **Recommended flow**: 1. **Initial upload**: Call with `preview=true` to get preview 2. **Display data**: Frontend shows parsed Holded contacts 3. **Final import**: Call with `preview=false` to import definitively **Expected Excel structure** (contacts exported from Holded): - Sheet: "Holded" - Rows to skip: 2 (header + empty) - Headers in row 2: Created, Name, ID, Email, Phone, Mobile, etc. (29 columns) - Footer: "Report created automatically with Holded..." **Security limits**: - Max size: 10MB - Max 5,000 records per file - Rate limiting: 5 imports per hour **Automatic Holded → Customer mapping**: - Name → legal_name - ID → identifier (NIF/CIF) - Email → email - Phone/Mobile → phone (prioritizes mobile) - Full address → address - Tags → notes
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
Excel file (.xlsx) of contacts exported from Holded
If true: parsing and mapping only without importing to DB. If false: parsing + mapping + actual import.
trueResponse 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-holded-contacts" \ -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": "BAD_REQUEST",
"message": "Invalid request"
},
"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": "Validation error",
"details": {
"field_name": "Field is 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": "INTERNAL_ERROR",
"message": "Internal server error"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}Import customers from CSV with structured preview POST
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
List customers GET
Returns a paginated list of customers with optional filters