Edge cases and limits
Every reason BeeL. can skip a Stripe event, how to retry one, and the known limits of the integration.
When a Stripe event produces no invoice, BeeL. records the reason on the event so you can audit it. This page lists every scenario, how to clear it, and what you can do to recover (retry the event, generate a draft, mark it resolved).
Needs attention — inbox of skipped events
BeeL. doesn't discard Stripe events silently. Every event it receives is recorded; if it can't be turned into an invoice, it keeps the event with the reason instead of discarding it. The dashboard's Needs attention panel (Necesita atención in the dashboard) lists the events you can actually act on — the rest stay in the event log for visibility, but don't ask for action.
Two kinds of reason decide whether an event goes to the panel:
- Checks on the event itself — environment, currency and amount. They are checked first, in a fixed order, and the first one that fails decides the reason.
- Reasons found while building the invoice — missing configuration, incomplete fiscal data, or a filter you configured.
Only reasons that require your action show up in the panel. Events that need none (the second event of a pair Stripe always sends, unsupported event types, events already invoiced) are in the event log but stay out of the panel.
Checks on the event itself
These checks are evaluated in this exact order — the first match wins.
| Check | What it checks | Skip reason |
|---|---|---|
| Livemode mismatch | The Stripe event's livemode flag doesn't match the connection's environment (sandbox vs live) | LIVEMODE_MISMATCH |
| Unsupported currency | The event currency isn't EUR (current single supported currency) | UNSUPPORTED_CURRENCY |
| Amount zero or negative | The payment_intent / charge / invoice / refund has amount ≤ 0 | AMOUNT_ZERO_OR_NEGATIVE |
Other reasons that surface in Needs attention
These reasons also land in the panel, because you have a concrete action to take:
| Skip reason | Triggered when |
|---|---|
CONNECTION_DISCONNECTED | The Stripe connection has been deauthorised; events keep arriving but produce no invoice |
AMOUNT_REQUIRES_FISCAL_DATA | Legacy: events recorded before charges above 3,000 € without NIF / address were saved as drafts automatically. Generate draft is offered |
RECTIFICATIVA_OUT_OF_PERIOD | A refund/credit note targets an original outside the rectificative window |
REFUND_ORIGINAL_NOT_FOUND | A refund arrived but BeeL. can't find the original payment (often out-of-order delivery) |
SIMPLIFIED_INVOICE_NOT_ALLOWED | The sale cannot go on a simplified invoice (for example a service to a buyer outside Spain) and the buyer's address is incomplete. Generate draft is offered |
| 0 % rate requires an exemption reason | Stripe charged a line at 0 % and neither Stripe nor your default exemption reason says why. Declare the reason and retry; no draft is offered |
UNSUPPORTED_STRIPE_TAX_TREATMENT | Stripe reports a treatment BeeL. does not reflect (reverse charge, customer exempt, zero-rated, or a manual 0 % rate for a buyer outside the IVA territory). Not retryable, no draft |
MISSING_DEFAULT_SERIES | No default series is configured for the resolved document type |
FILTER_AMOUNT_REJECTED, FILTER_CUSTOMER_REJECTED, FILTER_DESCRIPTION_REJECTED, FILTER_CATEGORY_REJECTED | A filter rule you configured rejected the event — visible in the panel for review, but won't trigger an email |
Charges saved as a draft
Some charges are not skipped: BeeL. saves them as a draft invoice, emails the issuer (Live connections only), and lists the draft in Needs attention. Open the draft, complete it and issue it. Retrying the original event is not needed.
| Cause | What to do |
|---|---|
| The charge is above 3,000 € and the customer has no NIF / address | Complete the recipient (name, NIF or foreign identifier, address) and issue |
| The AEAT definitively rejected the buyer's NIF | Correct the NIF or the name and issue; the invoice is never downgraded to a simplified one |
See Charges that cannot be invoiced automatically.
What to do, by reason
LIVEMODE_MISMATCH— someone hit your test webhook with a live event (or vice versa). Reconfigure the Stripe webhook endpoint so the right connection receives the right environment.UNSUPPORTED_CURRENCY— BeeL. is EUR-only today. Switch the Stripe price to EUR, or route non-EUR charges through a separate Stripe account that doesn't feed BeeL.AMOUNT_ZERO_OR_NEGATIVE— typically $0 authorisations confused with charges, internal vouchers, or full-refund chains. Review the original charge in Stripe; if it's legitimately zero, mark the event resolved.AMOUNT_REQUIRES_FISCAL_DATA— only on events recorded before charges above 3,000 € without a NIF / address were saved as drafts automatically (see Charges that cannot be invoiced automatically). Generate a draft from the event: it comes out as a standard invoice with the recipient left for you to complete, and cannot be issued until the recipient has a NIF (or a foreign identifier) and an address. Retrying doesn't help — it reads the recipient from the same Stripe payment again.SIMPLIFIED_INVOICE_NOT_ALLOWED— generate a draft and complete the buyer's street, city, postal code and country; to avoid it next time, make Checkout collect the full billing address. See Buyers outside Spain.- 0 % rate requires an exemption reason — declare your default exemption reason in Settings > Taxes, then retry the event. See Charges at 0 %.
UNSUPPORTED_STRIPE_TAX_TREATMENT— issue the invoice through the Invoicing API, or correct the tax in Stripe. A manual 0 % rate is only invoiced automatically for buyers in the peninsula or the Balearic Islands.CONNECTION_DISCONNECTED— reconnect the integration from the dashboard, then retry any events that arrived while disconnected.MISSING_DEFAULT_SERIES— set a default series for the resolved document type (standard / simplified / rectificative) and retry the event.REFUND_ORIGINAL_NOT_FOUND— usually out-of-order delivery; BeeL. retries the event automatically up to 8 times, 10 minutes after the first failure and doubling each time, never more than 6 hours apart — about a day in all. If it persists, the original was issued by a different connection or before BeeL. was connected — handle the refund manually.FILTER_*— the event matched a filter you configured. Either widen the filter and retry the event, or mark it resolved if the rejection was intentional.
Retrying from Needs attention
Once you've fixed the underlying cause (e.g. set a NIF on the customer, reconnected the integration, configured a default series), retry the event from the dashboard: BeeL. processes it as if Stripe had just delivered it — there's no need to ask Stripe to resend.
For reasons where a retry would always give the same result (AMOUNT_ZERO_OR_NEGATIVE, UNSUPPORTED_CURRENCY, CONNECTION_DISCONNECTED while still disconnected), the dashboard offers Mark resolved instead of Generate draft / Retry: the event stays recorded, and you sign it off by hand. AMOUNT_REQUIRES_FISCAL_DATA can't be retried either, but it does offer Generate draft.
Where to find it. The panel lives in Dashboard → Stripe → Needs attention (Necesita atención). Each row links to the originating event in the event log and to the related customer mapping (when there is one) so you can fix it and retry without leaving the page.
When BeeL. skips an event
The reasons fall in three buckets — permanent (no invoice will ever come from this event), configuration (fix a setting and retry), and data (fix the source and retry).
Permanent — no action needed
| Scenario | Notes |
|---|---|
| Event type not supported | BeeL. only listens to a curated set — see Supported events |
| The other event of a pair | Some Stripe events arrive in pairs (e.g. charge.succeeded + payment_intent.succeeded); BeeL. invoices only one of them, so the charge is not invoiced twice |
| Duplicate payment already invoiced | Working as intended — the charge already has its invoice |
| Dispute won | charge.dispute.closed in your favour — the charge and its invoice stand, and the review item opened by the dispute closes on its own |
| Credit note voided before it produced a corrective | Nothing was declared, so there is nothing to undo |
Configuration — fix a setting and retry
| Scenario | What to do |
|---|---|
| Stripe connection was deauthorized | Reconnect the integration from the dashboard |
| Auto-invoicing is off on the connection (the default of a Live connection) | Toggle on; retry the events you want to backfill |
| No default series exists for the resolved document type | Set a default series for standard / simplified / rectificative |
Data — fix the source and retry
| Scenario | What to do |
|---|---|
| Payment amount ≤ 0 € | No invoice for free or negative charges — investigate the Stripe charge |
| Currency ≠ EUR | Either bill in EUR or invoice those charges manually |
| Amount > 3,000 € and no NIF / address | BeeL. saves a draft and, on Live connections, emails you: complete the recipient in BeeL. and issue it; collect tax IDs in Stripe (Stripe Tax → Collect tax IDs) to avoid it next time |
| Refund / credit note with no matching original BeeL. invoice | Wait for the original payment webhook (often out-of-order), or invoice manually |
| Refund amount > original payment amount | Inspect Stripe — usually a data anomaly |
| Refund on an already-voided invoice | Chain is terminated — no further correctives |
| Webhook arrived for the wrong environment (live on test or vice versa) | Verify the webhook endpoint configuration in Stripe |
The event's failure_reason — in the dashboard event log and in the events list of the API — names which scenario triggered. Use the dashboard event log to inspect the raw payload.
Inspecting skipped events
Every Stripe event lands in the log visible at Dashboard > Developers > Stripe events. Each row shows:
- The Stripe
event.idandtype - The processing outcome (processed / skipped / failed)
- The skip reason (when applicable)
- The full raw payload (one click)
Most operational debugging starts here.
Retrying a Stripe event
When you need to reprocess an event (e.g. you fixed a configuration bug and want to backfill the invoices), you have two options.
Option 1 — From the dashboard
Open the event row, click Reprocess. BeeL. processes the event as if it had just arrived, producing an invoice (or a skip reason, as the first time).
Option 2 — From the API
The public API exposes the payment events of a connection, and both recovery levers, under the company that owns the connection:
| Endpoint | What it does |
|---|---|
GET /v1/companies/{company_id}/payment-connections/{connection_id}/events | Lists the events of the connection, most recent first — audit which charges produced an invoice and which didn't |
POST .../events/{event_id}/retry | Reprocesses an event whose automatic invoicing didn't complete, applying the NIF's current configuration. Only retryable states qualify, and the retry budget is finite: otherwise 400 EVENT_INVALID_STATUS_FOR_RETRY or 400 EVENT_MAX_RETRIES_EXCEEDED |
POST .../events/{event_id}/draft | Builds a draft invoice from an event that couldn't be invoiced automatically, with the same recipient resolution and tax treatment the automatic flow would have used, so you can review it before issuing. 400 EVENT_INVALID_STATUS_FOR_DRAFT if the event was already invoiced; 422 if invoicing rules reject the resulting document |
Both POSTs accept an Idempotency-Key header. Your key's account must own or manage the NIF, otherwise 403.
A retry never invoices a charge twice. Only an event that did not produce its invoice can be retried, and a charge that already has an invoice resolves to that same invoice — see Data conversion > Idempotency on both sides.
Out-of-order delivery
Stripe doesn't guarantee event ordering. The most common ordering issue is a refund arriving before the original payment. BeeL. retries such an event automatically up to 8 times, starting 10 minutes apart and doubling, never more than 6 hours apart — about a day in all; after that it stays failed for manual handling.
If you see persistent "refund original not found", check whether the original was issued by a different connection or before BeeL. was connected — in either case the refund needs manual handling.
Hard limits
| Limit | Value | Notes |
|---|---|---|
| Currency | EUR only | Payments in other currencies are skipped |
| Connections per account | 10 | Soft cap; raise via support |
| Webhook timeout | 10 seconds per event | Standard Stripe timeout |
| Retry budget for transient failures | Follows Stripe's default schedule | Up to 3 days |
| Event log retention | 90 days for processed events; indefinite for events that still need attention | Older entries are archived |
Known limitations
| Item | Status |
|---|---|
Disputes (charge.dispute.*) | Never corrected automatically. An open dispute, and a lost one, surface as a review item; you decide whether the invoice needs a corrective and issue it yourself — see Supported events |
| Multi-currency invoices | EUR only; payments in other currencies are skipped |
| Partial captures | Treated as the captured amount (BeeL. doesn't see the authorisation total) |
| Subscription proration credits | Translated to a credit note → corrective, same as any other credit note |
| Stripe Tax disabled | BeeL. falls back to your configured default IVA — invoice may not match what the customer expects |
What about Stripe Connect Express vs Standard?
BeeL. connects a Stripe account through Stripe Connect's authorisation flow (OAuth): the account's owner authorises BeeL., and every charge on that account is invoiced under the one NIF it was connected to. A Stripe account can be connected to a single NIF across BeeL.
What that means for a platform that runs its own Connect integration:
- Your platform account can be connected like any other Stripe account, but then every charge on it is invoiced under that one NIF — yours.
- Your Express connected accounts are not something BeeL. reads: BeeL. does not receive their events, and cannot route each one's charges to a different NIF.
So a marketplace on Connect Express whose partners each invoice under their own NIF uses the API instead: one managed account per partner, and an invoice on that partner's company_id when your own Stripe webhook confirms the charge.
When to write to support
Open a ticket at it@beel.es for:
- Persistent processing errors on a specific event ID
- Genuine total mismatches between Stripe and BeeL. that aren't explained by refunds or inclusivity toggles
- VeriFactu rejection codes you can't decipher (we'll cross-check with AEAT)
Include the Stripe event ID and the BeeL. invoice number (if one was created).