Skip to content
Oclavex is in private preview, available to selected users. Public signup is blocked. Request access at [email protected].

Stripe

Stripe charges the customer; Oclavex licenses them. The Stripe connector keeps the two in sync: you register your Stripe account under Settings → Stripe billing, point Stripe’s webhooks at the URL the connector shows you, and from then on a subscription that names an Oclavex offer or entitlement creates, updates, pauses or ends the matching entitlement on its own. Your application can also sell from inside the licensed product: with the customer’s license session as its only credential, it starts a Stripe Checkout for that customer’s entitlement and opens the Stripe billing portal for them.

Under Settings → Stripe billing, choose Register Stripe connector and enter:

  • A display name.
  • An API key from the Stripe Dashboard — a restricted (rk_) or secret (sk_) key. Its prefix fixes the connector’s mode, test or live; the key is stored encrypted and never shown again.
  • The webhook signing secret (whsec_…) Stripe shows for the endpoint. If the endpoint does not exist yet, register with a placeholder and rotate the secret once it does.
  • The allowed price lookup keys, one per line: checkout from your application may only start one of these. They can be added later.
  • The policy: what a past-due payment and an ended subscription do to the entitlement, described under What Stripe events do; whether a plan is applied only once an invoice is paid; and whether plan changes made in Stripe are followed. The defaults are the vendor policy: pause on past due, disable on cancellation, plan applied on the first event, plan changes not followed.

Once the connector exists, its card shows the webhook URL:

https://<your tenant>.<host>/api/v1/connectors/stripe/<connector id>/webhook

Paste it into the Stripe Dashboard under Developers → Webhooks, in the same mode as the key, and subscribe the endpoint to the events in the table below. The card shows the Stripe account the key answers for once you Probe it, and its Last sync: every six hours the connector re-reads your subscriptions from Stripe, and the card says when that last ran and whether it succeeded or why not, such as failed 2 h ago: Stripe refused the API key. After three failed syncs in a row the connector reads Needs attention until a sync succeeds again. A sync that succeeds can still miss a few subscriptions, one at a time: the card’s Not synced row counts them, and Show which lists up to 20 of them, the longest-failing first, each with a link to it in the Stripe Dashboard and why, such as Stripe answered with an error on its side. The next sync tries them again. A subscription that fails three syncs in a row makes the connector read Needs attention too, until a sync gets it through. From the card you also rotate the signing secret — the previous one keeps verifying for up to 24 hours — or the API key, and disable the connector; while it is disabled, Stripe deliveries are refused. A delivery from the other mode, or with a signature the connector cannot verify, is refused as well. Registering and rotating the connector is a portal action: it stores a Stripe API key and signing secret, so it is not available to machine credentials.

Two settings on the Stripe account itself: Checkout asks the buyer to accept your terms of service, so the account needs a terms-of-service URL under its public details; and Checkout calculates tax automatically, so Stripe Tax must be set up. The billing portal your customers open is the account’s default Customer Portal configuration.

The connector reads the subscription’s metadata first, then its price’s, then its product’s — so a key set once on a Stripe Product applies to every subscription under it. A subscription that carries none of these keys is recorded as unmapped and never acted on.

Key Meaning
oclavex_plan The Oclavex plan to apply, by name. Usually on the Product: any price under it — discounted, negotiated or newly listed — applies the same plan without further mapping.
oclavex_offer, oclavex_offer_version The offer a new entitlement is created from. Required when the subscription is not for an existing entitlement: without it nothing is created, unless the connector carries a default offer set through its API. The version is optional. The offer must be Published: while it is Draft, Disabled or Archived the event is refused, not retried, and recorded as a warning on the offer’s Audit log. After you publish it, a paid subscription is picked up by the connector’s check every six hours, and any other on its next Stripe event.
oclavex_entitlement_id Attach the subscription to this existing entitlement instead of creating one. Checkout from your application sets it.
oclavex_reference Your own label for the subscription, shown beside it under Settings → Stripe billing. Checkout from your application sets it.
oclavex_deployment oclavex for the production platform. Checkout from your application sets it; put it on the Product for subscriptions you create in the Dashboard or through a Quote.
oclavex_customer_email, oclavex_customer_name The customer contact for a new entitlement. Without them the Stripe Customer’s email and name are used; a new entitlement needs one of the two emails.
oclavex_addon The code of an Oclavex add-on. Usually on the Product. A subscription that carries it sells that add-on on top of the customer’s plan: it grants the add-on to the entitlement in oclavex_entitlement_id and never applies or changes a plan.
oclavex_credits, oclavex_credit_metric On a one-time price (or its product): the number of credits it buys and the metric name of the credit balance they land on. Such a price sells a credit top-up, not a plan.

An entitlement the connector creates or attaches gets a billing record with the Stripe ids: provider stripe, the subscription id (sub_…) and the customer id (cus_…), together with what the subscription last reported — its state, the period end, an open past-due episode. The record is the billing object of the entitlement in the API (GET /api/v1/provision/admin/entitlements/{id}/billing), and GET /api/v1/provision/admin/entitlements/by-billing-anchor/stripe:subscription:sub_… finds the entitlement by it. The entitlement’s own externalReference stays free for your CRM or order id.

The connector trusts a delivery only for its ids. It re-reads the subscription and the invoice from Stripe before acting, so deliveries can arrive out of order or twice without harm, and every six hours it re-reads your subscriptions from Stripe and repairs whatever a missed delivery left behind. What each event does to the entitlement, under the vendor default policy:

Stripe event Oclavex
customer.subscription.created (active or trialing) Creates an entitlement from the offer the subscription names, stamps the references, applies the plan and enables activations. A Stripe trial is honoured as a trialing entitlement.
checkout.session.completed Attaches the new subscription to the entitlement the checkout was started for and applies the plan. For a credit top-up, adds the credits once the payment has gone through.
checkout.session.async_payment_succeeded A top-up paid by a method that settles later, such as a bank debit: adds the credits when it settles.
invoice.paid First invoice: as above, if the subscription’s own event has not done it yet. A renewal changes nothing. With Apply a plan only on a paid invoice on, this is the event that applies the plan.
customer.subscription.updated Status and price are re-read. A plan change made in Stripe is applied only with Follow plan changes made in Stripe on.
invoice.payment_failed, invoice.payment_action_required Pause the entitlement (vendor default): it stays configured but refuses new activations until Stripe reports the payment recovered. Keep the plan leaves it untouched through Stripe’s retry window.
invoice.voided, customer.subscription.pending_update_expired Stripe drops a plan change whose charge failed after 23 hours and voids its invoice. The subscription is re-read: it stays on the plan it had, a voided invoice is not owed, and the payment problem is over.
customer.subscription.paused / resumed Pause; resume.
customer.subscription.deleted Disable the entitlement (vendor default): activations stop and the entitlement is kept. Apply a plan moves it to the plan you name instead. Lapse holds it on the <plan>-lapsed plan of the same plan set — a plan you define with the values a lapsed customer keeps — when the subscription ended for non-payment; a cancellation the customer chose leaves the entitlement unchanged.
customer.created, customer.updated Keeps the billing details of the customer’s organization — legal name, address, tax id, billing email — up to date with Stripe. A Customer created by checkout is already linked. A Customer you create in Stripe is linked to the organization its oclavex_organization_id metadata names. A Customer linked to no organization creates none. The organization’s name, contacts and licenses stay yours.
customer.deleted Recorded. The organization stays; its subscriptions end through their own events.
charge.refunded, charge.dispute.* Recorded on the subscription. A refund never revokes access — end the subscription to do that.

An add-on subscription (oclavex_addon) follows its own rules: once paid it grants the add-on, a cancellation scheduled for the period end sets the grant to end then, and customer.subscription.deleted ends the grant when Stripe ended the subscription. It never pauses, disables or re-plans the entitlement — the plan subscription does that.

A subscription whose first payment has not gone through (incomplete) is not activatable until it does. Any other event type is acknowledged and ignored.

The connector’s consumer endpoints let a licensed application upgrade its own user. The credential is the end user’s license session token, the one the application holds after activation. The entitlement is the session’s and is never named in the request; nor is an amount — the price is one of the connector’s allowed lookup keys, and the plan comes from the Stripe Product behind it.

POST /api/v1/connectors/stripe/{connectorId}/consumer/checkout-sessions
{ "priceLookupKey": "…", "successUrl": "…", "cancelUrl": "…" }

successUrl and cancelUrl are where Stripe sends the user after paying or going back. Leave them out to return to your tenant’s portal. A URL you pass must be on your tenant’s own host or on one of the Return hosts on the connector’s settings card, such as the host of your application’s own site. Any other host is refused with 400 checkout.invalid_return_url, so a Checkout page under your name never sends your customer somewhere else.

Redirect the user to the url in the answer. The Stripe Customer is created from the billing details of the entitlement’s customer organization on the first purchase and reused afterwards; promotion codes, automatic tax and tax-id collection are on. The request is refused when the price is not allowed (400), when the entitlement’s plan is managed by you rather than billed (403), when the entitlement has no customer organization (409), and when a live subscription already exists (409) — plan changes then happen in the billing portal. When the subscription is paid, checkout.session.completed attaches it to the entitlement, as above.

A price whose Product carries oclavex_addon sells an add-on as a subscription of its own: a live plan subscription does not block it, a live subscription to the same add-on does (409), and the add-on is granted when it is paid. Cancelling it at the period end keeps the add-on until then.

A one-time price sells a credit top-up instead: the same request opens a one-off payment for the credits the price’s oclavex_credits and oclavex_credit_metric metadata name, and the answer’s mode is payment. A live subscription does not block it, and an entitlement without a customer organization can buy one — Stripe then collects the payer’s details. The credits are added when Stripe confirms the payment, once per purchase; see selling top-ups.

POST /api/v1/connectors/stripe/{connectorId}/consumer/portal-sessions
{ "returnUrl": "…", "flow": "payment_method_update" }
GET /api/v1/connectors/stripe/{connectorId}/consumer/me

The portal session opens the Stripe billing portal for the same payer — the home page, or straight into payment_method_update, subscription_cancel or subscription_update. Its returnUrl follows the same rule as a checkout’s, refused with 400 portal.invalid_return_url. me reports what Stripe last said about the subscription: its state, paid plan, interval, period end, cancellation and past-due dates, which provider bills the entitlement, and whether it is billed through Stripe at all.

Every failure answers with a problem+json body, including one that starts at Stripe. The connector never answers 502 or 504 on these endpoints: a CDN or proxy in front of it replaces those with its own HTML page, and your application would never see the problem. It answers one of two statuses instead, and the problem’s codeName says which:

Status codeName What happened What to do
424 stripe.refused Stripe refused the request because of how your Stripe account and the connector are set up: the API key, its permissions, a price or an account setting. The detail names what Stripe said. Fix the account or the connector. Sending the same request again does not help.
503 stripe.unavailable Stripe could not be reached, timed out, answered with a server error, or asked the connector to slow down. When one Stripe account keeps failing under steady use, the connector also pauses its calls for that account for a few seconds and answers straight away; other accounts are not affected. Try again later. When Stripe or that pause names a wait, the answer carries it in Retry-After, at most one hour.

Both have type connectors/stripe/stripe.error. Other 503 answers carry no codeName and name their cause in type: connectors/stripe/connector.disabled and connectors/stripe/connector.no_api_key for a connector that is switched off or has no API key, and connectors/stripe/organization.link_failed when the Stripe customer was created but could not be recorded on the customer organization: try the request again. The Probe on the connector’s settings card answers the same two statuses, with type connectors/stripe/connector.probe_failed.

  • Licensing → Stripe subscriptions lists every subscription the connector has observed, with its state, paid plan and the entitlement it bills; a subscription the connector could not attribute to an entitlement reads as unmapped. Connector registration and credentials stay under Settings → Stripe billing.
  • The entitlement page → Billing is the same record every provider uses — see Billing for the four cards and what Managed by vendor does. With Stripe as the provider, the Subscription card carries Stripe’s own state against the plan in force, with links into the Stripe Dashboard while a connector is registered.
  • The customer’s organization page → Billing details shows the legal name, address, tax id and billing email as Stripe holds them, read-only once Stripe is their source.
  • The entitlements list Billing column and filter read the same record; see Billing.

Quotes, coupons, refunds and mark-as-paid stay in the Stripe Dashboard, behind those links.

Without the connector, keep Stripe and Oclavex in sync by relaying Stripe’s events to the REST API yourself and keying everything on an external reference:

Stripe subscription event
→ your relay (a Zapier Zap, or a small function)
→ Oclavex REST API, keyed on the Stripe id

The relay is where the mapping lives. Zapier is the quickest relay to set up; a serverless function that verifies Stripe’s signature and calls the API works identically.

When you create the entitlement, stamp the Stripe ids onto it — externalReference → stripe:subscription:sub_… and customerExternalReference → stripe:customer:cus_…. Oclavex stores them verbatim and indexes them per tenant, so the relay finds the right entitlement without keeping its own id map:

GET /api/v1/provision/admin/entitlements/by-external-reference/stripe:subscription:sub_1234

The lookup also matches archived and canceled entitlements, so re-delivering the same event is safe — you update the existing entitlement instead of creating a duplicate.

Stripe event What it means Do in Oclavex
customer.subscription.created (active) New paid subscription Create an entitlement from an offer, set the external references, enable activations
customer.subscription.created (trialing) Trial started Same, on your trial offer
customer.subscription.updated → active Recovered or un-paused Resume; enable activations
customer.subscription.updated → plan change Upgrade / downgrade Apply the matching plan
invoice.payment_failed → past due Payment problem Pause — activations are refused until it resolves
customer.subscription.paused Paused by the customer Pause
customer.subscription.deleted (canceled) Churn Cancel — disable activations

Each action is one REST call — create, apply-plan, pause, resume, enable/disable activations. The exact endpoints and payloads are in the REST API reference; the entitlement operations themselves are covered in Entitlement operations. A failed payment should stop new activations without destroying the entitlement: pause does that, and resume lifts the hold when Stripe reports the payment recovered. Cancellation is the terminal step — reserve it for a truly ended subscription.

The flow runs the other way too. Subscribe a webhook (see Zapier) to MeteredUsage.OverageStatusChanged and the entitlement events, and your relay can push consumption and license state onto the Stripe customer’s metadata — so support and finance see, next to the invoice, how much of the plan the customer is actually using.

See it live: sign up and try Mirage — the metered-SaaS product this integration serves, with hourly quotas, prepaid credits and an in-app plan upgrade, on a license issued to you.