Customers

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


POST
/v1/customers/import-holded-contacts
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

Excel file (.xlsx) of contacts exported from Holded

preview?boolean

If true: parsing and mapping only without importing to DB. If false: parsing + mapping + actual import.

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