Auto-submit policy
The exact conditions under which BeeL. sends an issued invoice to AEAT for you — and what happens when one of them isn't met.
BeeL. never silently submits an invoice to AEAT. Auto-submit only happens when a small list of preconditions all hold — and when one of them fails, BeeL. records why on the invoice so you can audit it later. This page documents the policy.
The four gates
All four must be open for BeeL. to submit the invoice to AEAT. If any of them is closed, the invoice is issued locally with verifactu.enabled: false on the response, and the reason is recorded in verifactu.skip_reason.
The per-invoice / per-integration toggle
On POST /v1/companies/{company_id}/invoices the gate is options.verifactu_enabled. Omit it and the company's declared preference applies — the "apply VeriFactu by default" setting (apply_by_default); if the company has no VeriFactu configuration it resolves to false. Send it explicitly (true or false) to override the preference for that one invoice. A PROFORMA always forces false, whatever the preference or the value you send.
The Stripe integration carries its own VeriFactu submission toggle instead — see Stripe / VeriFactu submission.
A VeriFactu configuration exists
You must have set up VeriFactu on your account at least once. The configuration record carries:
- The representation (PDF signed by you, delegating BeeL. to submit on your behalf)
- The environment target (Production or Sandbox)
- The NIFs you have authorised for submission
Read it with GET /v1/companies/{company_id}/verifactu-configuration. The only writable fields are enabled and apply_by_default, through PUT /v1/companies/{company_id}/verifactu-configuration — everything else (status, signed, activated, nif_status…) is resolved server-side. That PUT replaces the whole state and is not a partial merge: both fields are required, and omitting one is a client error, not a silent false.
The configuration enabled flag is on
Your VeriFactu configuration has an enabled flag you can turn off without deleting the record. This is the kill switch for the entire account — useful for maintenance windows or before a wave of test issuance. When off, every issued invoice lands with verifactu.enabled: false until you flip it back on.
The issuing NIF is registered with VeriFactu
The NIF that issues the invoice must be censado — registered and active in the VeriFactu system. A configuration can exist and be enabled while a specific issuing NIF is still not yet registered (for example, mid-onboarding). When the issuing NIF is not registered, the invoice is issued locally with verifactu.skip_reason: NIF_NOT_REGISTERED until the registration completes.
How a skipped submission looks on the invoice
When BeeL. doesn't submit, the invoice resource exposes the state through the nested verifactu object. The skip_reason field names which gate was closed:
{
"id": "...",
"status": "ISSUED",
"verifactu": {
"enabled": false,
"skip_reason": "NIF_NOT_REGISTERED"
}
}skip_reason values
skip_reason is nullable. When submission goes ahead it is null (the field does not apply); when the invoice is skipped it carries exactly one of the following reasons, matching which gate was closed:
| Value | Meaning |
|---|---|
CONNECTION_DISABLED | The per-invoice / per-integration toggle resolved to false (gate 1). |
CONFIG_MISSING | No VeriFactu configuration exists for the account (gate 2). |
CONFIG_DISABLED | A configuration exists but its enabled flag is off (gate 3). |
NIF_NOT_REGISTERED | The issuing NIF is not yet censado in VeriFactu (gate 4). |
A null skip_reason means "submission was not skipped"; a non-null value means the invoice was skipped on purpose for that reason.
When BeeL. DOES submit (all four gates open), the invoice carries the full record and skip_reason is null:
{
"id": "...",
"status": "ISSUED",
"verifactu": {
"enabled": true,
"skip_reason": null,
"submission_status": "PENDING",
"registration_number": null,
"registered_at": null,
"invoice_hash": "F8B2A3...",
"chaining_hash": "A1C4E7...",
"qr_url": null,
"qr_base64": null,
"error_code": null,
"error_message": null
}
}See Submission states for the full lifecycle of submission_status.
Defaults you should know
- Stripe integrations ship with VeriFactu auto-submit on by default. Stripe Connect payments auto-submit unless you explicitly turn the toggle off.
- Manual API issuance follows the account's
apply_by_defaultunless the request setsoptions.verifactu_enabledexplicitly.apply_by_default: truerequiresenabled: true; and ifenabledisfalse,apply_by_defaultmust befalsetoo. - Sandbox keys still submit to AEAT's sandbox environment — submissions are real but flagged as test in AEAT.
Production submissions are not undoable as a batch. Disable auto-submit before issuing a wave of invoices you don't want to send to AEAT.
There's no public "submit now" endpoint
The public API does not expose an endpoint to manually trigger a submission for an invoice that landed with verifactu.enabled: false. Your options:
This is by design — auto-submit is meant to be set once and trusted, not driven per-invoice from the API.
Related
- Submission states — what happens after the submission is queued
- Stripe / VeriFactu submission — same policy applied to Stripe-generated invoices
- getVeriFactuConfiguration — read your account's config
- updateVeriFactuConfiguration — flip
enabledandapply_by_default(the only two writable fields)