Customer Import

Import customers from a Holded contacts export

Parses a contacts export from Holded (.xlsx) as Holded produces it, maps each contact to a customer and returns every row with its validation outcome, as the CSV import does.

  • Deprecated: use POST /v1/companies/{company_id}/customers/imports with source: holded, which imports the same file. It answers 201 and requires the Idempotency-Key header.
  • Mapping: the contact name becomes legal_name, the Holded ID becomes the tax identifier, and mobile takes precedence over landline for the phone.
  • File: limited to 10 MB and 5,000 contacts. A file over either limit is rejected as a whole with 400 (CSV_FILE_TOO_LARGE or TOO_MANY_RECORDS) and nothing is imported.
  • preview: at its default true nothing is persisted; false also imports the mapped customers.

Retires on 9 December 2026. See the migration guide for what moved where and what changes when you switch.

post/v1/customers/import-holded-contacts

Request

  • Base URL: https://app.beel.es/api
  • URL: https://app.beel.es/api/v1/customers/import-holded-contacts
  • Auth: HTTP bearer

Headers

Idempotency-Keystring

Idempotency key to prevent duplicates in sensitive operations.

  • Any unique client-generated string (e.g. an order id). A UUID also works but is not required
  • Allowed characters: letters, digits, _ and - (max 255 chars)
  • Retrying with the same key replays the first response when it was a success (2xx) or a server error (5xx): same status and body, plus the header Idempotency-Replay: true. After a 5xx, check whether the operation took effect before retrying with a new key
  • A 4xx is not stored: the key is released, so the corrected request can reuse it
  • Stored responses expire 24 hours after processing

The key is scoped per user and environment, and bound to the request body, so retrying after a network timeout replays the stored response instead of repeating the operation.

StatusCodeWhen
400INVALID_IDEMPOTENCY_KEYThe key breaks the format rules above.
409IDEMPOTENCY_KEY_PROCESSINGThe first request is still in flight. Wait for the Retry-After seconds (2) and retry with the same key.
409IDEMPOTENCY_KEY_MISMATCHThe key was already used with a different body. Use a new key.

Response

Holded Excel processing completed with unified format. Returns parsed, validated and mapped customers using the same format as CSV import.

successboolean required

Example response

{
  "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": [
      {
        "customer": {
          "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",
          "billing_emails": [
            "user@example.com"
          ],
          "contact_person": "María García",
          "preferred_payment_method": {
            "method": "BANK_TRANSFER",
            "iban": "ES1234567890123456789012",
            "swift": "ABCDESMMXXX",
            "payment_term_days": 30
          }
        },
        "customer_id": "550e8400-e29b-41d4-a716-446655440000",
        "status": "VALID",
        "errors": [
          {
            "field": "nif",
            "value": "12345678X",
            "message": "NIF not found in AEAT census",
            "code": "CUSTOMER_IDENTIFIER_REQUIRED"
          }
        ],
        "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": 8,
      "success_rate": 0.8,
      "importable": 8,
      "not_importable": 2
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.