REST API · OpenAPI 3.1 · typed SDK

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.

create-ring.ts@rmj/sdk
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).

embed.html
<!-- 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 addToCart event and create a cart line with the chosen specs + price.
  • Custom storefront: embed via the JS SDK, read selection events to drive your own price/spec panel.
  • Headless: read /ring-builder/catalog (now incl. per-part/value SKU + price) and POST /ring-builder/quote from 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.

Open GraphQL Playground ↗
POST /api/graphqlAuthorization: Bearer rmj_live_…
# 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/projectsList projectsmodels:read
POST/api/public/projectsCreate a project (idempotent)models:write
GET/api/public/projects/:idFetch a project incl. studio configmodels:read
PATCH/api/public/projects/:idUpdate name / config / thumbnailmodels:write
DELETE/api/public/projects/:idDelete a projectmodels:write
GET/api/public/projects/:id/versionsList a project's version historymodels:read
POST/api/public/projects/:id/versionsSnapshot a version (named or autosave)models:write
POST/api/public/projects/:id/versions/:vid/restoreRestore a project to a versionmodels:write
DELETE/api/public/projects/:id/versions/:vidDelete a version from the historymodels:write
GET/api/public/sharesList design-share links (/d/:slug)shares:read
POST/api/public/sharesCreate the share link for a projectshares:write
GET/api/public/shares/:idFetch a design shareshares:read
PATCH/api/public/shares/:idAccess / password / expiry / downloads / rotate slugshares:write
DELETE/api/public/shares/:idDelete a design shareshares:write
GET/api/public/creditsPlan + live credit balanceusage:read
GET/api/public/ring-builder/catalogPublished ring catalog (groups, parts, default)ringbuilder:read
GET/api/public/ring-builder/embedsList ring-builder embedsringbuilder:read
POST/api/public/ring-builder/embedsCreate a ring-builder embedringbuilder:write
PATCH/api/public/ring-builder/embeds/:idUpdate config / domains / activeringbuilder:write
GET/api/public/ring-builder/pricingAn embed's price books + per-part overridesringbuilder:read
POST/api/public/ring-builder/pricingCreate/update an embed's price book (currency, markup, rounding)ringbuilder:write
GET/api/public/ring-builder/stone-setsAn embed's centre-stone tiersringbuilder:read
POST/api/public/ring-builder/stone-setsCreate a centre-stone tierringbuilder:write
GET/api/public/ring-builder/pagesAn embed's designed page — the draft and what is liveringbuilder:read
POST/api/public/ring-builder/pagesSave the page draft, and optionally publish or unpublish itringbuilder:write
POST/api/public/ring-builder/priceAuthoritative price for a selectionringbuilder:read
POST/api/public/ring-builder/quoteComposed SKU + total (sum-of-parts catalog pricing)ringbuilder:read
POST/api/public/ring-builder/conciergeAI concierge — chat turn → validated selection + authoritative priceringbuilder:read
POST/api/public/ring-builder/cartAdd a configured ring to the storefront cart (match → mint → draft → hosted → event)commerce:write
POST/api/public/ring-builder/verifyTurn a signed quote token back into the price it proves (no key — the token is the credential)public
GET/api/public/diamonds/searchSearch the live loose-diamond feed (retail-marked-up)diamonds:read
GET/api/public/integrations/shopifyShopify connection status + attributed order revenueintegrations:read
POST/api/public/lifestyleStage a ring render into a branded lifestyle scenelifestyle:write
POST/api/public/checkout/sessionCreate a Stripe Checkout session for a ring selection (authoritatively priced)checkout:write
GET/api/public/ring-builder/quotesList saved quotesringbuilder:read
POST/api/public/ring-builder/quotesSave a quote/enquiryringbuilder:write
GET/api/public/ring-builder/quotes/:idRetrieve a saved quoteringbuilder:read
GET/api/public/embeds/:id/analyticsEmbed analytics — funnel, daily trend & top selectionsanalytics:read

API access is included on Pro and Studio plans. The @rmj/sdk package gives you typed access from Node or the browser.