Guides

API reference

The Orvain UI website answers a small JSON API: the newsletter signup and the Stripe checkout behind the pricing page. It is the same API the site's own pages call. The component library and the MCP server are separate products and are not part of it.

Overview#

Every endpoint takes a POST with a JSON body and answers JSON, at https://orvain.dev. There is no API key. Purchases are tied to an email address and proven with the Stripe Checkout Session id that Stripe hands back after payment.

Terminal
curl -X POST https://orvain.dev/api/subscribe \
-H 'Content-Type: application/json' \
-d '{"email":"you@example.com"}'

Machine-readable files#

The API is described in OpenAPI 3.1 at /openapi.json, with an operationId, a description and typed schemas on every operation, so it can be loaded straight into a function-calling agent. /.well-known/api-catalog points at it in the RFC 9727 format. For reading the site rather than calling it, /llms.txt summarises every page, and the home page answers in Markdown to a request sent with Accept: text/markdown.

Endpoints#

Join the Orvain Dispatch newsletter

POST/api/subscribesubscribeToNewsletter

Adds an email address to the Orvain Dispatch mailing list (release notes and launch news). Idempotent: subscribing an address that is already on the list succeeds.

FieldTypeDescription
email
string
An email address.

Open a Stripe Checkout page for a plan

POST/api/stripe/checkoutcreateCheckoutSession

Returns the URL of a hosted Stripe Checkout page for one Orvain UI plan. The price, billing mode and amount are decided server-side from product, tier and billing. Without an email only the Figma file can be bought, as a guest; the code library and the bundle need the signed-in account's email. Send the buyer to the returned URL to pay.

FieldTypeDescription
product
library | figma | bundle
library = React and Vue code with the MCP server; figma = the Figma file; bundle = both.
tier
personal | team | business
Licence size: personal is Solo (1 seat), team is Studio, business is Business.
billing?
yearly | lifetime
Payment term. A term the product is not sold on falls back to the product's own.
email?
string
The signed-in account's email. Omit it to buy as a guest; Stripe then collects the email.

Confirm a paid Checkout Session

POST/api/stripe/confirmconfirmCheckout

Checks with Stripe that a Checkout Session was paid, by the given email, for an Orvain UI plan, and returns the plan it bought. For code library and bundle orders it also returns the licence key.

FieldTypeDescription
sessionId
string
A Stripe Checkout Session id (the order number on the receipt).
email
string
The email the payment was made with.

Cancel a yearly plan at the end of its term

POST/api/stripe/cancelcancelSubscription

Stops a yearly Orvain UI subscription from renewing. Access continues until the paid year ends; the response says when that is. Calling it again is safe and returns the same date.

FieldTypeDescription
subscriptionId
string
The Stripe subscription id.
email
string
The email the subscription belongs to.

Get the licence key for a paid order

POST/api/stripe/licencegetLicenceDelivery

Returns the code library licence key for a Checkout Session that Stripe reports as paid for the Library or the bundle, issuing it if needed. The session id is the proof of purchase. key is null while the key is still being issued; it is emailed either way.

FieldTypeDescription
sessionId
string
A Stripe Checkout Session id (the order number on the receipt).

Get the Figma file for a paid order

POST/api/stripe/figmagetFigmaDelivery

Returns the link to the Orvain UI Figma library for a Checkout Session that Stripe reports as paid for the Figma file or the bundle. The session id is the proof of purchase.

FieldTypeDescription
sessionId
string
A Stripe Checkout Session id (the order number on the receipt).

Email a sign-in link

POST/api/auth/requestrequestSignInLink

Emails a link that signs the address in to orvain.dev. The link works for 15 minutes. The answer is the same whether or not the address has bought anything. Limited to 5 requests per 15 minutes per email and per IP.

FieldTypeDescription
email
string
An email address.
offer?
object
Optional: the plan the visitor wants to buy next. The link carries it on to checkout; it is never granted by signing in.

Open a sign-in link

POST/api/auth/verifyverifySignInLink

Checks a sign-in link's token and answers with the account it opens: the email and the best plan it still holds (from its licences, or its Figma order), with the licence key. An account with no valid plan comes back with `offer: null`, the free tier.

FieldTypeDescription
token
string
The `token` parameter of the emailed link.

Stripe event receiver (Stripe only)

POST/api/stripe/webhookreceiveStripeWebhook

Receives checkout.session.completed, checkout.session.async_payment_succeeded and invoice.paid events from Stripe to email orders, issue licences and extend renewals. Requests must carry a valid Stripe-Signature header; anything else is rejected. Not for clients.

Errors#

Every error, at every status, is JSON in one shape. error is a sentence a person can read, code is stable and safe to branch on, and hint, when present, says how to fix the request. An unknown path under /api answers 404 not_found, and a verb an endpoint does not take answers 405 method_not_allowed with an Allow header.

Response
{
"error": "That email address doesn't look right.",
"code": "invalid_email",
"status": 400,
"hint": "Send a JSON body like {\"email\":\"you@example.com\"}.",
"docs": "https://orvain.dev/docs/api#errors"
}
CodeStatus
invalid_email
400
method_not_allowed
405
upstream_error
502
not_configured
503
unknown_plan
400
plan_unavailable
422
invalid_request
400
email_mismatch
403
not_found
404
payment_pending
409
unknown_offer
422
wrong_product
422
rate_limited
429
invalid_token
400
expired_token
400
invalid_json
400
bad_signature
401
retry
500