These endpoints are called from your checkout UI before the subscriber completes their order. All three are public (no auth required) and limited to 60 requests / minute each — per API key when you send X-API-Key, otherwise per client IP. Over the limit kurnl answers 429 Too Many Requests; back off and retry (see Rate limits).

Check email availability

Check whether an email address is already registered as a kurnl account. The check is platform-wide — it is not scoped to your provider.

Request body

Response

Mind the polarity: is_taken: true means the email is already registered. Your checkout UI should then prompt the subscriber to log in instead of creating a new account.

Check subscription at location

Check whether a location already has an active subscription. Used to block booking a second product at the same connection.

Query parameters

Pass one of the two (there is no provider parameter):

Response

has_active_subscription: true means the location already has an active subscription — your checkout UI should show an error or redirect.
This endpoint fails open: malformed input, an unknown location, or a backend error all return false. Treat false as “no conflict found”, not as a guaranteed negative — the provisioning endpoints enforce the authoritative checks.

Validate discount code

Validate a discount code and return its terms so you can display them in the checkout UI.

Request body

Response — 200 OK (valid)

The request takes two optional fields that let a kurnl operator discount answer: building_id and location_identifier (either names the building). The response fields beyond discount: With applied: false (reason: "campaign_better"), label, promo_price_monthly and duration_months describe the plan’s campaign (the terms the order will get), while discount is still the operator’s. The comparison is on the monthly promo price only; a tie keeps the campaign. A bulk plan answers valid: false: operator codes never apply to bulk plans.

Response — 200 OK (invalid)

error is free text (e.g. "Plan version not found", "Invalid or expired discount code").
The code must belong to the provider of plan_version_id: another provider’s code answers exactly like an unknown one. A provider’s own code has no expiry window, so “expired” never occurs for it. An operator discount is applied to buildings with a start and an end date, so for an operator code “expired” is real. Treat a valid: true as advisory.
Discounts are billed on kurnl-billed lines: the promotional price is charged from activation for the duration’s full calendar months, then the plan’s price. At the marketplace checkout a discount code replaces the plan’s campaign; the checkout requests (location, home-drop and unit) take it as the optional discount_code. Partner provisioning accepts discount_code on the session create, complete, anonymous-complete (both only in their explicit-fields, sessionless form; with a session_id the session’s stored code is used and the body’s is ignored), provider-initiated and provisioning/bulk; without it, a partner-created line gets the plan version’s campaign. discount_type is PERCENTAGE, FIXED_MONTHLY (fixed amount off per month) or OVERWRITE_MONTHLY (fixed monthly price).

Payments not configured (409)

The checkout-creation step that follows these helper calls — and the subscriber payment-method routes (see Subscriber Self-Service) — needs the provider’s own Stripe account. If that provider has not connected one, it returns 409:
Only the Kurnl marketplace checkout needs Stripe — a provider using the external checkout is unaffected. Check service_providers.tenant_configs.stripe_connected on the plan version (see Plans) before offering the Kurnl checkout in your UI.