Customer mappings

How BeeL matches Stripe customers to BeeL customers, auto-creates ad-hoc records, and handles missing fiscal data.


Every Stripe payment carries some hint about who paid (customer ID, email, billing details). BeeL turns that into a customer mapping — a stored link between the Stripe-side customer and the BeeL-side customer (or to an ad-hoc record when no BeeL customer exists yet). The mapping is what lets BeeL issue a properly-identified invoice on every subsequent payment from the same buyer.

Mappings are built and maintained automatically. They are not user-editable today and there is no public API to create, link, or unlink them. Their content is derived from what Stripe sends on each payment, plus your auto-create customer connection setting. The integration points that are yours to control live in Connection settings.

Recent improvements (May 2026) — if you previously hit any of these, they're fixed:

  • Mappings now persist on the first webhook delivery, including the auto-create path. Previously some flows skipped the mapping write, so the second payment from the same buyer was treated as new.
  • The mapping is updated atomically. Two concurrent webhook deliveries for the same Stripe customer can no longer race to create duplicate mappings.
  • Country no longer defaults to ES. If Stripe sends a foreign address (or no country at all), the mapping stores what Stripe actually sent.
  • The Stripe charge total is now mirrored on both forwards and rectificativas. Refunds that previously wouldn't reconcile because the credit note total drifted from the original charge now match exactly.
  • Simplified (F2) invoices issued from Stripe preserve the customer's name and email from the Stripe payload instead of defaulting everyone to Consumidor final.

Two kinds of mapping

A mapping is either:

  • Linked — tied to a managed customer in your BeeL account. Future invoices use the managed customer's current data (address, legal name).
  • Ad-hoc — a stand-alone snapshot of the buyer's data extracted from Stripe. Future invoices reuse the snapshot without creating a BeeL customer.

Both are valid sources for an invoice's recipient. Whether a mapping ends up linked or ad-hoc depends on what Stripe sent and on auto-linking (below) — you don't choose at mapping time.

What happens on every Stripe payment

event arrives


1. Read the connection's "auto-create customer" setting

     ├─ off  →  No mapping work. Invoice issued with the
     │          buyer's data inline (nothing stored).

     └─ on   ▼
                 2. Look up a mapping for this Stripe customer
                    (by Stripe customer ID and/or email).

                 ├─ found
                 │    ├─ linked  → recipient = the linked managed customer
                 │    └─ ad-hoc  → recipient = the stored snapshot

                 └─ not found

                 3. Build a snapshot from the Stripe payload:
                    – customer.name, email, address
                    – customer.tax_ids[0].value as NIF (if Spanish format)
                 4. Persist a new ad-hoc mapping with that snapshot
                 5. recipient = the new snapshot

After step 5, the next payment from the same Stripe customer will hit step 2 and reuse the mapping — no re-extraction.

How persistence works

A mapping is uniquely identified by the pair (your Stripe connection, the Stripe customer ID). When a webhook arrives and auto-create customer is on, BeeL updates the mapping atomically:

  • If no mapping exists for that Stripe customer, it's created — either linked to a managed customer (if one matches the NIF the payload carries) or as ad-hoc with the snapshot extracted from the payload.
  • If a mapping already exists, the mapping row itself isn't rewritten: the link target and the ad-hoc snapshot stay as they were captured the first time.

So the mapping is stable across webhooks. But the data behind it is not always stable — and that distinction matters:

  • For a linked mapping, every subsequent webhook re-runs the upsert against the managed customer's own record. If Stripe sent updated fiscal data, the managed customer is updated to match — Stripe wins over what you have in BeeL. If you need to preserve a manual edit on a managed customer, turn off auto-create customer for that connection.
  • For an ad-hoc mapping, the snapshot is captured once at creation and never refreshed by a later webhook. If Stripe later collects a NIF or corrects the address, the existing ad-hoc mapping keeps the old data — see When the recipient ends up incomplete.

When auto-create customer is on and the Stripe payload carries a valid Spanish NIF, BeeL looks up your managed customers by that NIF:

  • A match exists → the mapping is created linked to the existing managed customer (no duplicate created), and the managed customer's fiscal data is refreshed with what Stripe sent under the Stripe wins policy.
  • No match and Stripe sent a complete address → BeeL creates a brand-new managed customer from the Stripe payload and links the mapping to it.
  • No match and the address is incomplete → no managed customer is created or updated; the mapping is created as ad-hoc with the snapshot.

If the payload has no valid NIF (foreign buyer with only alternative_id, or no tax data at all), the mapping is always ad-hoc — no auto-link, no managed customer.

Ad-hoc fields

When a mapping is created as ad-hoc, BeeL stores a snapshot of the buyer's data from the Stripe payload. The fields and their sources:

Snapshot fieldSource
Legal namecustomer.name or charge.billing_details.name
NIFcustomer.tax_ids[0].value (if Spanish format)
Emailcustomer.email
Phonecustomer.phone
Street, number, postal code, city, province, country, country codeextracted from customer.address (or charge.billing_details.address)

This snapshot is the source for the auto-emitted invoice's recipient block whenever the mapping is ad-hoc (no managed customer linked). It is populated only when the mapping is first created — once it exists, future webhooks never overwrite it (see How persistence works).

When the recipient ends up incomplete

Two common reasons:

1. Stripe didn't send a customer

Some payment flows (Stripe Terminal, payment links without customer collection) don't attach a customer.* block. BeeL falls back to charge.billing_details (name, email, address). When there is no Stripe customer ID at all, no mapping is created — the payment is just one-off — and the invoice falls to F2 (simplified), populating the recipient with whatever name/email Stripe sent and otherwise defaulting to Consumidor final. See Generated invoices.

2. No NIF on the Stripe customer

Stripe lets you collect tax IDs (customer.tax_ids) but it's opt-in. Without a NIF, BeeL cannot issue F1 above the simplified threshold — the event lands in the Necesita atención inbox so you can review it (see Edge cases and limits).

Fix: enable Stripe Tax's "collect tax IDs" or use Checkout's tax-collection options. As soon as the next payment from the same buyer carries tax_ids, the lookup at step 2 above still finds the existing mapping — but because mappings are frozen at creation time, that new NIF won't propagate into the old mapping. For payments that originated under the old (NIF-less) mapping, the operational path is to fix the buyer's setup in Stripe so any future customer ID gets a fresh, properly-built mapping on first use.

Country is no longer assumed to be Spain. If Stripe sends no country, BeeL stores whatever Stripe actually sent (including empty) — and the invoice path adapts based on the real data.

Connection settings that affect mappings

SettingDefaultEffect
Auto-create customerOnPersist a mapping on every new buyer. Turning off keeps invoices flowing but stores no mapping.

You change it in Connection settings.

Pitfall: turning auto-create off mid-stream

The flag only gates new mappings. If you turn auto-create customer off after the integration has been running:

  • Existing mappings keep resolving normally. Every payment from a Stripe customer that BeeL has already seen will reuse its mapping and issue the invoice as usual.
  • Payments from a new Stripe customer ID won't create a mapping. The recipient is built inline from the Stripe payload and the Stripe event lands in the Necesita atención inbox so you can review it.

Turning the flag back on does not retroactively persist mappings for events processed while it was off.