Replace a customer (deprecated)
Scopecustomers:writeReplaces an existing customer with the body you send.
- Not a partial update:
trade_name,email,website,billing_emails,contact_person,notesandgeneral_discountare cleared when they are absent from the body, so send the customer complete. To change only some fields, usePATCH /v1/companies/{company_id}/customers/{customer_id}. - AEAT census: the customer's Spanish tax identifier is only checked against the AEAT
census when the body changes the
nifor thelegal_nameof the stored customer. Resending the same pair never asks the census, so a customer stored long ago stays editable even if its NIF is no longer listed. For a legal entity the census checks the CIF only and itslegal_nameis not verified, so the name never causes the rejection; only a natural person's NIF is crossed with the name. Duplicate and format checks run on every update. - Deprecated: this route will be retired on the date announced in its
Sunsetresponse header. The canonical form has a single update verb,PATCH /v1/companies/{company_id}/customers/{customer_id}, which is not a drop-in replacement for this one: it changes only the fields present in the body. To reproduce a total replacement, send every field and passnullin the ones you want cleared.
Retires on 9 December 2026. See the migration guide for what moved where and what changes when you switch.
Keys are prefixed beel_sk_, and each one carries the scopes it was created with: a key
short of the scope an operation needs is answered 403. The scope an operation requires
is shown next to its title, and the full catalogue lives in the Scopes reference.
Keys are created from the BeeL dashboard. They are secret credentials: do not share them or commit them to source control.
In: header
Path Parameters
Customer ID
uuidCustomer legal name. Matched against the AEAT census only for individuals; for a company the name is not verified.
1 <= length <= 120Customer trade name. Omitting it clears the field: this is a full replacement, and
the creation default (falling back to legal_name) does not apply here.
length <= 120Address you send when you create or update a company, a customer or an onboarding.
A required field made only of whitespace passes the length checks below but leaves the
address without that part, so it is rejected with 422: STREET_EMPTY,
POSTAL_CODE_EMPTY, CITY_EMPTY or PROVINCE_EMPTY.
Addresses you read back are described by their own schema.
A phone number as this API accepts it: 9 to 20 characters, and only digits, spaces,
dashes, parentheses and an optional leading +. Every request that takes a phone number
uses this schema.
It is Phone plus the rules enforced on input. A value this schema accepts always
satisfies Phone, so anything you send here is something a response can return.
^[+]?[0-9\s\-\(\)]+$9 <= length <= 20Main contact address (minimum valid email is 5 chars, e.g. a@b.co). Invoice emails go
here only when the customer has no billing_emails.
email5 <= length <= 255Website URL
^(https?://.+|)$length <= 255Addresses that receive the customer's invoice emails. When the send request names no
recipients and the invoice has no email_config recipients, invoices go to these
addresses, and not to email; email is used only when billing_emails is empty.
Contact person name (optional)
length <= 200Additional notes about the customer (optional)
General discount percentage (optional)
0 <= value <= 100Whether the customer is active or inactive
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://app.beel.es/api/v1/customers/550e8400-e29b-41d4-a716-446655440000" \ -H "Content-Type: application/json" \ -d '{}'{
"success": true,
"data": {
"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",
"website": "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"
}
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"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 is required to access this resource"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "You do not have permission to access this resource"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "INVOICE_NOT_FOUND",
"message": "Invoice not found"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "The provided data is not valid.",
"details": {
"legal_name": "The field 'legal_name' cannot be empty",
"recipient.address.postal_code": "Contains invalid characters."
}
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please try again in 60 seconds."
},
"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"
}
}{
"success": false,
"error": {
"code": "UNSUPPORTED_MEDIA_TYPE",
"message": "Unsupported media type: text/plain. Supported: application/json"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}List the customers (deprecated) GET
Returns a paginated list of customers, with optional filters. - **Deprecated:** use `GET /v1/companies/{company_id}/customers`, which behaves identically. **Retires on 9 December 2026.** See the [migration guide](https://docs.beel.es/changelog/resources-under-the-nif) for what moved where and what changes when you switch.
Update a customer partially (deprecated) PATCH
Updates only the fields present in the body, leaving every other field of the customer as it is. - **Null vs omitted:** a field sent as `null` is cleared, which is different from omitting it (see `PatchCustomerRequest`). The result goes through the same validation as `PUT`. - **AEAT census:** the customer's Spanish tax identifier is only checked against the AEAT census when the request changes the `nif` or the `legal_name`. Editing anything else never asks the census. For a **legal entity** the census checks the CIF only and its `legal_name` is not verified, so the name never causes the rejection; only a **natural person**'s NIF is crossed with the name. Duplicate and format checks run on every update. - **Deprecated:** use `PATCH /v1/companies/{company_id}/customers/{customer_id}`, which behaves identically. **Retires on 9 December 2026.** See the [migration guide](https://docs.beel.es/changelog/resources-under-the-nif) for what moved where and what changes when you switch.