Edge cases and limits
Every reason BeeL can drop a Stripe event, how to replay one, and the known limits of the integration.
When BeeL drops a Stripe event without producing an invoice, it records a typed skip reason on the event log so you can audit it. This page lists every scenario, how to clear it, and the operational levers (replay, manual override) when you need to recover.
Necesita atención — inbox of skipped events
BeeL doesn't drop Stripe events silently. Every inbound webhook is ingested into a typed inbox; if it can't be turned into an invoice, BeeL parks it with a typed skip reason instead of discarding it. The dashboard's "Necesita atención" panel surfaces the parked events you can actually act on — the rest stay in the audit log for visibility, but don't ask for action.
Two layers decide whether an event goes to the panel:
- Envelope-level acceptance checks — first-line defence on the envelope itself (environment, currency, amount sanity). These run before BeeL spends any work on the event and short-circuit on the first match.
- Downstream skip reasons — emitted later in the pipeline when configuration is missing, fiscal data is incomplete, or a user-defined filter rejects the event.
Only reasons that require user action show up in the panel. Noise (duplicate sibling events, unsupported event types, dedup hits) goes to the event log but stays out of the panel.
Envelope-level acceptance checks
These checks are evaluated in this exact order — first match wins, cheapest checks first.
| 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 "Necesita atención"
Beyond envelope-level acceptance, the following downstream reasons also land in the panel because the user has a concrete action to take:
| Skip reason | Triggered when |
|---|---|
CONNECTION_DISCONNECTED | The Stripe connection has been deauthorised; events keep arriving but no processing happens |
AMOUNT_REQUIRES_FISCAL_DATA | The charge is above the simplified threshold and the customer mapping lacks NIF / address |
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) |
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 |
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 (see Scope and limitations). 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 parked event resolved.AMOUNT_REQUIRES_FISCAL_DATA— the charge is above the simplified threshold but the buyer has no NIF / address to escalate to a standard (F1) invoice. Add the missing fiscal data to the buyer's record in Stripe (or contact support if you need to backfill existing parked events), then replay.CONNECTION_DISCONNECTED— reconnect the integration from the dashboard, then replay any events that arrived while disconnected.MISSING_DEFAULT_SERIES— set a default series for the resolved document type (standard / simplified / rectificative) and replay.REFUND_ORIGINAL_NOT_FOUND— usually out-of-order delivery; BeeL retries on a backoff for ~6 hours. 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 replay, or mark resolved if the rejection was intentional.
Replaying from "Necesita atención"
Once you've fixed the underlying cause (e.g. set a NIF on the customer, reconnected the integration, configured a default series) you can replay the parked event from the dashboard. The pipeline behaves exactly as if Stripe had just delivered the event — there's no need to ask Stripe to resend.
For reasons where replay would deterministically produce the same skip (AMOUNT_ZERO_OR_NEGATIVE, UNSUPPORTED_CURRENCY, CONNECTION_DISCONNECTED while still disconnected, AMOUNT_REQUIRES_FISCAL_DATA without first editing the mapping), the dashboard offers Mark resolved instead of Generate draft / Replay — same parking semantics, manual sign-off.
Where to find it. The panel lives in Dashboard → Stripe → 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 and replay 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 replay), and data (fix the source and replay).
Permanent — no action needed
| Scenario | Notes |
|---|---|
| Event type not supported | BeeL only listens to a curated set — see Supported events |
| Sibling event has a canonical handler | Some Stripe events arrive in pairs (e.g. charge.succeeded + payment_intent.succeeded); BeeL uses the canonical one to avoid double-issue |
| Duplicate payment already invoiced | Working as intended — deduplication kicked in |
| Disputes | charge.dispute.* is reserved for future support |
Configuration — fix a setting and replay
| Scenario | What to do |
|---|---|
| Stripe connection was deauthorized | Reconnect the integration from the dashboard |
| Auto-invoicing is off on the connection | Toggle on; replay events you want to backfill |
| No default series exists for the resolved document type | Set a default series for standard / simplified / rectificative |
| VeriFactu submission is disabled | See Auto-submit policy — the invoice is issued, just not submitted to AEAT |
Data — fix the source and replay
| 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 manually outside the Stripe pipeline |
| Amount > simplified threshold and no NIF / address | Collect tax IDs in Stripe (Stripe Tax → Collect tax IDs) or lower the threshold |
| 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 exact verifactu_skip_reason or event-skip identifier exposed on the resource describes 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.
Replaying 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. The event flows through the pipeline as if it had just arrived.
Replay is only available from the dashboard today; the public API does not expose a programmatic replay endpoint. The dashboard-side button re-runs the same processing pipeline as the original event, producing an invoice (or a typed skip reason, same as the original path).
Replay always re-runs the handler. If the handler produces an invoice, you'll get a new invoice number (BeeL doesn't reuse old numbers). The original invoice — if it was created — must be cancelled separately to avoid duplicates.
Out-of-order delivery
Stripe doesn't guarantee event ordering. The most common ordering issue is a refund arriving before the original payment. BeeL handles this with a small retry budget: parked events are retried on a backoff for ~6 hours. After that they stay 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 | Multi-currency support is a roadmap item |
| 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 parked events | Older entries are archived |
| Simplified threshold | 0 € – 3 000 € | Default 400 € |
Known limitations
| Item | Status |
|---|---|
Disputes (charge.dispute.*) | Not auto-handled; surfaced in the dashboard for manual processing |
| 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?
The integration treats both the same way. The differences are on Stripe's side (KYC flow, fee handling) — BeeL only sees the resulting events. The same processing rules, the same skip reasons.
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).
Related
- Supported events — the full event catalogue
- Generated invoices — what each event produces
- Customer mappings — when fiscal data is missing