Register an invoice reply
Scopeinvoice-replies:writeRegisters a message that a customer sent you on a channel of your own about an invoice
of the company. It is stored with authenticated_by API_KEY and without a connection_id.
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
Unique identifier (UUID) of the company the operation acts on: its identifier, not its NIF. It is the only source of context: the account that owns it is derived from it, and the BeeL-Active-Company header plays no part. A company you do not reach answers 403, and so does a company that does not exist, so the existence of a company in another account is never disclosed.
uuidHeader Parameters
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 other than 503, check whether the operation took effect before retrying with a new key - After a
503, retry first with the same key. If the response carriesIdempotency-Replay: true, the operation may have taken effect: check the resource before using a new key. Without that header, the retry runs the operation once - 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.
| Status | Code | When |
|---|---|---|
400 | INVALID_IDEMPOTENCY_KEY | The key breaks the format rules above. |
409 | IDEMPOTENCY_KEY_PROCESSING | The first request is still in flight. Wait for the Retry-After seconds (2) and retry with the same key. |
409 | IDEMPOTENCY_KEY_MISMATCH | The key was already used with a different body. Use a new key. |
^[a-zA-Z0-9_-]+$length <= 255An invoice or proforma of the company that is not a draft or scheduled, in the environment of the credential.
uuidWhere the customer wrote: the medium, not the provider of the connection that brought
it (an email is EMAIL whatever received it). More values may be added: treat an
unknown one like OTHER.
EMAIL: an email;sender.addressis an email address.WHATSAPP:sender.addressis a phone number in E.164 format.TELEGRAM:sender.addressis the user identifier on Telegram.SLACK:sender.addressis the user identifier on Slack.SMS:sender.addressis a phone number in E.164 format.OTHER: any other channel, such as the chat of your product.
Identifier of the message on its channel: the Message-ID for EMAIL, the message identifier of the provider for messaging channels, your own for OTHER. A second message with the same channel and external_id answers 409 INVOICE_REPLY_DUPLICATE.
1 <= length <= 998When you received the message. Omit it to use the moment of the call. A moment more than 5 minutes ahead answers 422 VALUE_OUT_OF_RANGE.
date-timeSubject of the message. Omit the field when the channel has none.
1 <= length <= 998Text of the message, without the quoted messages it answers. Omit it when the message has no text; then attachments is required.
1 <= length <= 20000Attachments to describe. Only their description is stored, never a file.
items <= 10Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://app.beel.es/api/v1/companies/497f6eca-6276-4993-bfeb-53cbbbba6f08/invoice-replies" \ -H "Content-Type: application/json" \ -d '{ "invoice_id": "b71d5e2a-9c3f-4a7b-8e10-2f6d4c8a9b13", "channel": "WHATSAPP", "external_id": "wamid.EXAMPLE0001", "sender": { "address": "+34600123456", "name": "Laura Gómez" }, "received_at": "2026-11-03T09:12:44Z", "text": "Hola, ¿podéis mandarme la factura a nombre de Distribuciones Ejemplo S.L.?" }'{
"success": true,
"data": {
"id": "3f0c9a1e-6b2d-4c8f-a1e5-7d9b0c2e4f61",
"channel": "EMAIL",
"authenticated_by": "REPLY_TOKEN",
"connection_id": "8c3e1f7a-2b4d-4e6f-9a1c-5d7b3e9f2a41",
"invoice_id": "b71d5e2a-9c3f-4a7b-8e10-2f6d4c8a9b13",
"invoice_number": "F2026-0142",
"customer_id": "7a2c9e14-3b5d-4f6a-8c0e-1d2b3a4c5e6f",
"status": "RECEIVED",
"received_at": "2026-11-03T09:12:44Z",
"subject": "RE: Factura F2026-0142",
"excerpt": "Hola, el CIF que aparece no es el nuestro, es [NIF]. ¿Podéis corregirla?",
"sender": {
"address": "[EMAIL]",
"name": "Laura Gómez"
},
"external_id": "CAH7xQ2b9pLk3mZ0@mail.distribuciones-ejemplo.es",
"attachments": [
{
"id": "5b0e2c7a-91d4-4f3e-8a6b-2c1d9e0f7a34",
"url": "/v1/companies/9f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f/invoice-replies/3f0c9a1e-6b2d-4c8f-a1e5-7d9b0c2e4f61/attachments/5b0e2c7a-91d4-4f3e-8a6b-2c1d9e0f7a34",
"file_expires_at": "2026-11-18T10:15:00Z",
"content_type": "application/pdf",
"size_bytes": 48213,
"filename": "justificante-transferencia.pdf"
}
],
"text": "Hola, el CIF que aparece no es el nuestro, es B87654315. ¿Podéis corregirla?\nGracias,\nLaura",
"is_text_truncated": false
},
"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 is required to access this resource"
},
"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"
},
"type": "https://docs.beel.es/errors/INVOICE_NO_LINES",
"title": "INVOICE_NO_LINES",
"detail": "The invoice must have at least one line",
"instance": "/v1/invoices/abc-123"
}{
"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"
},
"type": "https://docs.beel.es/errors/INVOICE_NO_LINES",
"title": "INVOICE_NO_LINES",
"detail": "The invoice must have at least one line",
"instance": "/v1/invoices/abc-123"
}{
"success": false,
"error": {
"code": "INVOICE_REPLY_DUPLICATE",
"message": "A reply with this channel and external identifier already exists.",
"details": {
"reply_id": "3f0c9a1e-6b2d-4c8f-a1e5-7d9b0c2e4f61"
}
},
"meta": {
"timestamp": "2026-11-03T09:12:44Z",
"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"
},
"type": "https://docs.beel.es/errors/INVOICE_NO_LINES",
"title": "INVOICE_NO_LINES",
"detail": "The invoice must have at least one line",
"instance": "/v1/invoices/abc-123"
}{
"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"
}
}Void an invoice (deprecated) POST
Voids an issued invoice, moving it to `VOIDED`. - **Deprecated:** use `POST /v1/companies/{company_id}/invoices/{invoice_id}/void`, which behaves identically. - **VeriFactu:** when it is enabled for the invoice, the cancellation is submitted to the AEAT. - **`reason`:** required in the body. `void_date` is optional. - **Sent, paid or corrected invoices:** the successor operation documents when they can be voided (`issued_in_error`, `422 VOID_REQUIRES_ISSUED_IN_ERROR`, `422 INVOICE_HAS_LIVE_CORRECTIVES`, `422 TOTAL_CORRECTIVE_NOT_VOIDABLE`). - **PDF:** unchanged; the void is reported by the invoice's `status`. **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.
Delete an invoice reply DELETE
Erases the text, subject, sender, attachments, `external_id` and `connection_id` of the reply, to answer an erasure request, and delivers `invoice.reply.deleted`. Repeating it answers `204` and delivers nothing. The same `channel` and `external_id` can no longer be registered: a new attempt answers `409` without `reply_id`. Retrying the original registration with its same `Idempotency-Key` within 24 hours still replays the original response.