Jewelry rendering, programmable.
Everything in the dashboard is on the API: create projects, read studio configs, manage embeds and meter credits — from your store backend, PIM or order pipeline.
import { createClient } from "@rmj/sdk";
const rmj = createClient({ apiKey: process.env.RMJ_API_KEY });
// 1. Fetch catalog
const catalog = await rmj.ringBuilder.catalog();
// 2. Authoritative Quote (SKU & Price)
const selection = { bandSlug: "classic-round", metalPresetId: "yellow_gold_18k" };
const quote = await rmj.ringBuilder.quote(selection);
// 3. Save Quote for checkout
const saved = await rmj.ringBuilder.saveQuote(
selection,
{ name: "Jane Doe", email: "jane@example.com" },
"cart",
{ idempotencyKey: "cart-1234" }
);Scoped, hashed keys
Keys are SHA-256 hashed at rest, shown once, scoped per capability (models, embeds, usage) and revocable instantly.
Rate-limited & idempotent
120 req/min per key with Retry-After headers; all mutations accept an Idempotency-Key so retries never double-create.
Tenant-isolated by design
Every request is bound to your organization — row-level security in the database backs every API check.
Embeddable ring builder
Publish a live, interactive 3D ring builder on any store. Customers configure band / shape / setting / carat / metal in real time; you receive the selection, price and an add-to-cart event. Configure it in Dashboard → Embeds → Ring builder (default ring, allowed metals, AR, price, CTA, branding, domain lock).
<!-- 1. iframe — drop anywhere -->
<iframe src="https://app.example.com/embed/SLUG"
width="100%" height="640" style="border:0;border-radius:16px"
allow="xr-spatial-tracking; camera; fullscreen" loading="lazy"></iframe>
<!-- 2. JS SDK — auto-resize + cart events -->
<div id="ring"></div>
<script src="https://app.example.com/ring-builder.js"></script>
<script>
RMJRingBuilder.mount('#ring', {
slug: 'SLUG',
onSelection: (s) => updatePrice(s.price),
onAddToCart: (s) => cart.add(s), // s = { shape, setting, carat, metal, price, currency }
});
</script>Use cases
- Shopify / WooCommerce: listen for the
addToCartevent and create a cart line with the chosen specs + price. - Custom storefront: embed via the JS SDK, read
selectionevents to drive your own price/spec panel. - Headless: read
/ring-builder/catalog(now incl. per-part/value SKU + price) and POST/ring-builder/quotefrom your backend for the authoritative composed SKU + total. - Automation: create/update embeds over the REST API to roll the builder out across many storefronts.
Events are sent via postMessage with source: "rmj-ring-builder". Domain locking is enforced with a per-embed frame-ancestors CSP; set embedOnly to also refuse opening the embed URL outside an iframe.
GraphQL API
One endpoint, every (non-admin) feature — ask for exactly the fields you need. Same bearer keys, scopes and per-key domain lock as REST. Explore and test it in the built-in playground.
# Query exactly what you need — projects, embeds, catalog, price, org…
query {
organization { plan creditsBalance }
embeds(type: "ring_builder") { id embedUrl isActive }
ringCatalog { groups { code label values { code label } } }
}
# Create a ring-builder embed
mutation {
createEmbed(input: {
type: "ring_builder",
allowedDomains: ["myshop.com"],
config: { pricing: { enabled: true, currency: "USD", base: 1200, perCaratDelta: 800 } }
}) { id embedUrl }
}
# curl:
# curl https://app.example.com/api/graphql \
# -H "Authorization: Bearer rmj_live_…" -H "Content-Type: application/json" \
# -d '{"query":"{ organization { plan creditsBalance } }"}'Endpoints
Authenticate with Authorization: Bearer rmj_live_…
| GET | /api/public/projects | List projects | models:read |
| POST | /api/public/projects | Create a project (idempotent) | models:write |
| GET | /api/public/projects/:id | Fetch a project incl. studio config | models:read |
| PATCH | /api/public/projects/:id | Update name / config / thumbnail | models:write |
| DELETE | /api/public/projects/:id | Delete a project | models:write |
| GET | /api/public/projects/:id/versions | List a project's version history | models:read |
| POST | /api/public/projects/:id/versions | Snapshot a version (named or autosave) | models:write |
| POST | /api/public/projects/:id/versions/:vid/restore | Restore a project to a version | models:write |
| DELETE | /api/public/projects/:id/versions/:vid | Delete a version from the history | models:write |
| GET | /api/public/shares | List design-share links (/d/:slug) | shares:read |
| POST | /api/public/shares | Create the share link for a project | shares:write |
| GET | /api/public/shares/:id | Fetch a design share | shares:read |
| PATCH | /api/public/shares/:id | Access / password / expiry / downloads / rotate slug | shares:write |
| DELETE | /api/public/shares/:id | Delete a design share | shares:write |
| GET | /api/public/credits | Plan + live credit balance | usage:read |
| GET | /api/public/ring-builder/catalog | Published ring catalog (groups, parts, default) | ringbuilder:read |
| GET | /api/public/ring-builder/embeds | List ring-builder embeds | ringbuilder:read |
| POST | /api/public/ring-builder/embeds | Create a ring-builder embed | ringbuilder:write |
| PATCH | /api/public/ring-builder/embeds/:id | Update config / domains / active | ringbuilder:write |
| GET | /api/public/ring-builder/pricing | An embed's price books + per-part overrides | ringbuilder:read |
| POST | /api/public/ring-builder/pricing | Create/update an embed's price book (currency, markup, rounding) | ringbuilder:write |
| GET | /api/public/ring-builder/stone-sets | An embed's centre-stone tiers | ringbuilder:read |
| POST | /api/public/ring-builder/stone-sets | Create a centre-stone tier | ringbuilder:write |
| GET | /api/public/ring-builder/pages | An embed's designed page — the draft and what is live | ringbuilder:read |
| POST | /api/public/ring-builder/pages | Save the page draft, and optionally publish or unpublish it | ringbuilder:write |
| POST | /api/public/ring-builder/price | Authoritative price for a selection | ringbuilder:read |
| POST | /api/public/ring-builder/quote | Composed SKU + total (sum-of-parts catalog pricing) | ringbuilder:read |
| POST | /api/public/ring-builder/concierge | AI concierge — chat turn → validated selection + authoritative price | ringbuilder:read |
| POST | /api/public/ring-builder/cart | Add a configured ring to the storefront cart (match → mint → draft → hosted → event) | commerce:write |
| POST | /api/public/ring-builder/verify | Turn a signed quote token back into the price it proves (no key — the token is the credential) | public |
| GET | /api/public/diamonds/search | Search the live loose-diamond feed (retail-marked-up) | diamonds:read |
| GET | /api/public/integrations/shopify | Shopify connection status + attributed order revenue | integrations:read |
| POST | /api/public/lifestyle | Stage a ring render into a branded lifestyle scene | lifestyle:write |
| POST | /api/public/checkout/session | Create a Stripe Checkout session for a ring selection (authoritatively priced) | checkout:write |
| GET | /api/public/ring-builder/quotes | List saved quotes | ringbuilder:read |
| POST | /api/public/ring-builder/quotes | Save a quote/enquiry | ringbuilder:write |
| GET | /api/public/ring-builder/quotes/:id | Retrieve a saved quote | ringbuilder:read |
| GET | /api/public/embeds/:id/analytics | Embed analytics — funnel, daily trend & top selections | analytics:read |
API access is included on Pro and Studio plans. The @rmj/sdk package gives you typed access from Node or the browser.