Set the status of an invoice
Scopeinvoices:writeSets the commercial status of an invoice. Any transition other than the ones below is rejected.
PAID: fromISSUED,SENTorOVERDUE.SENT: fromISSUED.ISSUED: fromSENTonly, to undo aSENTset by mistake.- Not set here: issuing and voiding are fiscal acts with their own operations
(
POST …/{invoice_id}/issue,POST …/{invoice_id}/void), and issuing is never undone.
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.
uuidInvoice ID
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, 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.
| 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 <= 255Target status.
- PAID: from
ISSUED,SENTorOVERDUE. - SENT: from
ISSUED. Recordssent_at. - ISSUED: from
SENTonly. Clearssent_at. Use it to undo aSENTset by mistake; it never un-issues an invoice, which is irreversible.
"ISSUED" | "SENT" | "PAID"Payment date. Only read when status is PAID; defaults to today.
dateTimestamp for when the invoice was sent. Only read when status is SENT;
defaults to now.
date-timeResponse 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/companies/497f6eca-6276-4993-bfeb-53cbbbba6f08/invoices/550e8400-e29b-41d4-a716-446655440000/status" \ -H "Content-Type: application/json" \ -d '{ "status": "PAID", "payment_date": "2025-02-05", "payment_method": { "method": "BANK_TRANSFER", "iban": "ES9121000418450200051332" } }'State changed to PAID. Payment date, method, and reference recorded
{
"success": true,
"data": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"invoice_number": "A/2025/0042",
"series": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"code": "A"
},
"number": 42,
"type": "STANDARD",
"status": "PAID",
"issue_date": "2025-01-20",
"due_date": "2025-02-20",
"payment_date": "2025-02-05",
"sent_at": "2025-01-25T09:00:00Z",
"paid_at": "2025-02-05T14:30:00Z",
"issuer": {
"legal_name": "Tu Empresa SL",
"nif": "B12345674",
"address": {
"street": "Calle Ejemplo",
"number": "123",
"postal_code": "28001",
"city": "Madrid",
"province": "Madrid",
"country": "España"
}
},
"recipient": {
"customer_id": "123e4567-e89b-12d3-a456-426614174000",
"legal_name": "Cliente Ejemplo SL",
"nif": "B87654321"
},
"lines": [
{
"description": "Corporate website development",
"quantity": 40,
"unit": "hours",
"unit_price": 37.5,
"discount_percentage": 0,
"taxable_base": 1500,
"main_tax": {
"type": "IVA",
"percentage": 21,
"regime_key": "01"
},
"line_total": 1815
}
],
"totals": {
"taxable_base": 1500,
"total_vat": 315,
"total_irpf": 0,
"total_equivalence_surcharge": 0,
"vat_breakdown": [
{
"type": 21,
"base": 1500,
"amount": 315
}
],
"invoice_total": 1815
},
"payment_info": {
"method": "BANK_TRANSFER",
"iban": "ES9121000418450200051332",
"payment_term_days": 30
},
"pdf_download_url": "/v1/companies/7c9e6679-7425-40de-944b-e07fc1f90ae7/invoices/f47ac10b-58cc-4372-a567-0e02b2c3d479/pdf",
"created_at": "2025-01-20T10:30:00Z",
"updated_at": "2025-02-05T14:30:00Z"
},
"meta": {
"timestamp": "2025-02-05T14:30:00Z",
"request_id": "d2e3f4a5-b6c7-4d8e-9f0a-1b2c3d4e5f6a"
}
}{
"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": "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": "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"
}
}Send several invoices in one email POST
Sends one email carrying the PDFs of several invoices of this company as attachments. - **`recipients`:** required, and must carry at least one address; no address is inferred from any profile. - **Limit:** up to 200 invoices per message (`invoice_ids`). - **Failures:** invoices whose PDF cannot be attached are reported in `failures`, and the message is still sent with the rest.
Schedule an invoice PUT
Replaces the scheduling of a draft invoice, whether it had one or not, moving it to `SCHEDULED`. Both fields of the body are required. - **`scheduled_for`:** the date the invoice is processed on. Today or later; an earlier date is rejected with `422 SCHEDULED_DATE_IN_PAST`. - **`generation_mode`:** `DRAFT` leaves the invoice as a draft for manual review, `ISSUE_AND_SEND` issues and sends it automatically. There is no default. - **Availability:** requires the `scheduled_invoices` feature.