Create customer
Creates a new customer. **Idempotency:** Supports `Idempotency-Key` header to prevent duplicates when a request is retried (network timeout, double-click, etc.).
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
Header Parameters
Idempotency key to prevent duplicates in sensitive operations.
- Must be a unique UUID generated by the client
- If the same key is sent twice, the result of the first operation is returned
- Keys expire after processing
uuidCustomer legal name (required)
^\S.*$1 <= length <= 120Customer trade name (optional)
length <= 120Alternative identifier for customers without Spanish Tax ID.
VeriFactu rules (enforced server-side, returns 422 ALTERNATIVE_ID_INVALID on violation)
- If
country_code = ES, thentypemust bePASSPORT(03) orNOT_REGISTERED(07). - If
type = NOT_REGISTERED(07), thencountry_codemust beES.
Matrix of allowed combinations
type | country_code = ES | country_code ≠ ES |
|---|---|---|
NIF_IVA (02) | ✗ | ✓ |
PASSPORT (03) | ✓ | ✓ |
COUNTRY_ID (04) | ✗ | ✓ |
RESIDENCE_CERTIFICATE (05) | ✗ | ✓ |
OTHER_DOCUMENT (06) | ✗ | ✓ |
NOT_REGISTERED (07) | ✓ | ✗ |
Phone number. Allows digits, spaces, dashes, parentheses, and optional leading +
^[+]?[0-9\s\-\(\)]+$9 <= length <= 20Email address (minimum valid email is 5 chars, e.g. a@b.co)
email5 <= length <= 255Website URL
^(https?://.+|)$length <= 255Additional emails for invoice delivery (optional)
Contact person name (optional)
length <= 200Additional notes about the customer (optional)
General discount percentage (optional)
0 <= value <= 100Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://app.beel.es/api/v1/customers" \ -H "Content-Type: application/json" \ -d '{ "legal_name": "Tech Solutions SL", "nif": "B12345678", "email": "admin@techsolutions.com", "phone": "+34912345678", "address": { "street": "Calle Mayor", "number": "123", "floor": "2º B", "postal_code": "28013", "city": "Madrid", "province": "Madrid", "country": "España" }, "notes": "Cliente prioritario - Pago puntual" }'Customer created successfully with generated ID and initial statistics
{
"success": true,
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"legal_name": "Tech Solutions SL",
"nif": "B12345678",
"email": "admin@techsolutions.com",
"phone": "+34912345678",
"address": {
"street": "Calle Mayor",
"number": "123",
"floor": "2º B",
"postal_code": "28013",
"city": "Madrid",
"province": "Madrid",
"country": "España"
},
"notes": "Cliente prioritario - Pago puntual",
"active": true,
"created_at": "2025-01-20T10:00:00Z",
"updated_at": "2025-01-20T10:00:00Z"
},
"meta": {
"timestamp": "2025-01-20T10:00:00Z",
"request_id": "c1c1c1c1-0001-4000-a000-000000000001"
}
}{
"success": false,
"error": {
"code": "INVALID_JSON_FORMAT",
"message": "The field 'due_date' has an invalid date format: '2026-03-04fds'. Expected format: YYYY-MM-DD.",
"details": {
"field": "due_date",
"invalid_value": "2026-03-04fds",
"expected_format": "YYYY-MM-DD"
}
},
"meta": {
"timestamp": "2026-03-05T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}Duplicate resource exists (NIF, email, invoice number, series code)
{
"success": false,
"error": {
"code": "CONFLICT",
"message": "Resource already exists",
"details": {
"conflict_type": "DUPLICATE_NIF",
"field": "nif",
"value": "B12345678",
"existing_resource_id": "123e4567-e89b-12d3-a456-426614174000",
"message": "A customer with NIF B12345678 already exists"
}
},
"meta": {
"timestamp": "2025-01-20T10:00:00Z",
"request_id": "d4d4d4d4-0004-4000-a000-000000000004"
}
}Request data fails validation (missing fields, invalid format, business rules)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"errors": [
{
"field": "nif",
"message": "Invalid NIF format. Expected 9 characters (8 digits + letter or letter + 8 digits)",
"value": "B123INVALID"
},
{
"field": "lineas",
"message": "At least one line item is required",
"value": []
},
{
"field": "receptor.direccion.codigo_postal",
"message": "Invalid postal code format. Expected 5 digits",
"value": "280"
},
{
"field": "lineas[0].precio_unitario",
"message": "Unit price must be greater than or equal to 0",
"value": -10.5
}
]
}
},
"meta": {
"timestamp": "2025-01-20T10:00:00Z",
"request_id": "c3c3c3c3-0003-4000-a000-000000000003"
}
}{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal server error"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}Update company details PATCH
Updates editable fields of a company. NIF, legal name, and entity type are immutable after creation.
Create or validate multiple customers POST
Creates multiple customers in a single operation or validates data without persisting. **Validation flow:** 1. `dry_run=true`: Full validation only (NIFs, duplicates, format) without persistence 2. `dry_run=false`: Validation + actual creation **Validations performed:** - Individual validation of each customer (same rules as single customer creation) - Detection of duplicate NIFs within the batch - Detection of duplicate NIFs against existing database - Parallel NIF validation against AEAT registry (VeriFactu) - Field format verification (email, phone, etc.) **Result statuses:** - `VALID`: Customer valid, ready to create - `WARNING`: Customer valid but with warnings (e.g., missing email) - `ERROR`: Customer invalid, cannot process - `DUPLICATE`: Duplicate NIF (in batch or existing DB) - `NIF_INVALID`: NIF not valid in AEAT registry **Atomicity:** - `dry_run=true`: Validation only, no persistence - `dry_run=false`: If any customer fails, ALL customers are rejected (full atomicity)