NewTell a voided invoice from a totally rectified one, without a second call
BeeL
Get StartedMulti-NIFVeriFactuStripeAPI ReferenceChangelog

Connect Stripe

Connect Stripe per company (NIF) so its payments auto-generate VeriFactu-compliant invoices under the right NIF — for the companies you own and, white-label, for the managed accounts you provision.


Connect Stripe to a company (NIF) and every payment on that account auto-generates an official, VeriFactu-compliant invoice under that exact NIF — no manual step. In the multi-NIF model the connection is per company, never per account: each NIF has its own Stripe account, its own invoices, its own numbering.

Two audiences, one API:

  • Your own companies — connect Stripe to any NIF your account owns.
  • Managed companies — a provisioner (agency / gestoría or fleet) connects Stripe white-label to a NIF it manages, so the holder authorizes from your portal and never leaves it.

This page covers managing the connection (connect · list · disconnect). What a payment then produces — the Fiscal Mirror, taxes, numbering, VeriFactu submission — lives in the Stripe → invoices section.

Endpoints

Three operations manage a connection, and every one of them hangs off the company, so the NIF is always explicit:

Each reference page carries the scope it requires and its full schemas.

The {company_id} in the path is the only source of context — the account that owns the NIF is derived from it, whether that is your own account or one you provisioned. A NIF you do not reach returns 403, the same answer a non-existent one gets.

{provider} is a lowercase slug — currently only stripe (Stripe Connect) is operative; woocommerce and shopify are reserved for future providers.

All three work for a NIF you own or manage; acting on a NIF you neither own nor manage returns 403. start exists for the white-label flow — connecting a NIF you manage from your own portal — see Connecting a managed NIF.

Connecting a managed NIF

Provisioners connect Stripe by API, white-label — the holder authorizes from your portal and comes back to it. Two steps:

1. Start the connection. Send the provider slug in the body, and optionally a return_url (absolute https://) to send the holder back to your portal after authorizing:

curl -X POST https://app.beel.es/api/v1/companies/550e8400-e29b-41d4-a716-446655440000/payment-connections/authorizations \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "stripe",
    "return_url": "https://your-portal.example.com/connections/stripe/return"
  }'

The connection itself only exists once the holder authorizes, which is why opening the authorization is a sibling sub-resource and not a POST on the collection.

Response — an authorization_url you redirect the holder to:

{ "success": true, "data": { "authorization_url": "https://connect.stripe.com/oauth/authorize?..." } }

2. The holder authorizes. They approve on Stripe; BeeL's callback finalizes the connection and redirects to your return_url with query params appended — on success status=success, provider, company_id, connection_id and account (the provider account id, e.g. acct_…); on error status=error, provider and message (an error code). Omit return_url (or send a non-https:// URL) and the callback lands on BeeL's default integrations screen.

The connection is sealed under the NIF's holder, so auto-invoicing runs under the correct NIF — not under your provisioner account.

start requires that you own or manage the NIF. A NIF you neither own nor manage returns 403 and no connection is initiated — its holder must connect it from the BeeL. app.

The NIF must be switched on in the mode of your key (beel_sk_test_* → Test, beel_sk_live_* → Live). Otherwise start returns 400 COMPANY_NOT_ACTIVATED_IN_ENVIRONMENT and no authorization_url: activation is what creates the invoice series and tax configuration, so without it every incoming charge would be skipped instead of invoiced. Test and Live activations are independent — see switching a NIF on.

Checking status

curl https://app.beel.es/api/v1/companies/550e8400-e29b-41d4-a716-446655440000/payment-connections \
  -H "Authorization: Bearer beel_sk_live_xxx"

Each connection comes back as a deliberately small object — its fields are in the reference. For the question you are usually asking ("did this provisioned NIF finish connecting?"), read status: a NIF whose holder opened the authorization but never approved it has no connection at all, not a connection in a pending state. An empty list is the normal answer while you wait.

Disconnecting

curl -X DELETE https://app.beel.es/api/v1/companies/550e8400-e29b-41d4-a716-446655440000/payment-connections/stripe \
  -H "Authorization: Bearer beel_sk_live_xxx"

Tokens are revoked and auto-invoicing stops. Already-issued invoices are not affected. If the NIF has no active connection for that provider, you get 404.

Payment events

A connection records every charge it receives as a payment event, whether or not it produced an invoice. This is the audit trail for a NIF's takings, and the place to recover a charge that failed to invoice.

Four operations, all hanging off the same /v1/companies/{company_id} prefix so the NIF stays explicit:

What an event tells you

The event object reports three separate things, and telling them apart is what makes the endpoint usable:

  • What the provider said — the charge, its fee, the net, who paid, and the provider's own ids. This is reconciliation material: match it against Stripe's own dashboard, never against the invoice.
  • What BeeL. did with it — whether an invoice came out, and if not, why. A failure is classified as well as described, so you can route on the category instead of parsing a message.
  • What you can do nextneeds_action, plus the two flags below.

Check retry_available and draft_available before calling. They tell you which of the two recovery paths the event supports; calling the other one returns 400.

Recovering a charge that did not invoice

  • retry re-runs the normal processing. Use it when the failure was transient — for example the NIF had no default series at the time and now does.
  • draft creates a draft invoice from the event's data (201), for you to review and issue with POST /v1/companies/{company_id}/invoices/{invoice_id}/issue. Use it when automatic processing cannot succeed but the charge is genuine.
# Find the events still waiting on you.
curl "https://app.beel.es/api/v1/companies/550e8400-e29b-41d4-a716-446655440000/payment-connections/stripe/events" \
  -H "Authorization: Bearer beel_sk_live_xxx"

# Draft an invoice from one of them.
curl -X POST "https://app.beel.es/api/v1/companies/550e8400-e29b-41d4-a716-446655440000/payment-connections/stripe/events/8ee6b023-c4e5-482e-93ca-dc66da2f9cb5/draft" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Idempotency-Key: $(uuidgen)"

The life of a charge

sequenceDiagram
autonumber
participant Payer as Payer
participant Stripe as Stripe
participant BeeL. as BeeL
participant You as Your integration
Payer->>Stripe: pays the connected NIF
Stripe->>BeeL: charge notification
BeeL->>BeeL: records a payment event
alt the NIF can issue
  BeeL->>BeeL: issues the invoice and submits it to AEAT
  BeeL-->>You: webhook invoice.issued
  BeeL-->>You: webhook verifactu.status.updated
else something blocks it
  BeeL->>BeeL: event kept with needs_action true
  You->>BeeL: GET .../events to find it
  You->>BeeL: POST .../events/{event_id}/retry or /draft
  BeeL-->>You: 201 draft invoice to review and issue
end

Where to go next