Guide for agents
The rules a coding agent follows when it writes code that talks to a Diamra store. The MCP server gives the agent the same rules as its page guide. Each rule links to the page that has the details, and each group of rules ends with an example.
Three ways to work with a store
- The API: calls your server makes to the store, at
https://api.diamra.com/v1. - Webhooks: POSTs Diamra sends your server when something happens in the store.
- Embed: the design studio in an iframe on the store website, and the messages it sends the page.
Keys and tokens
- Keep the API key on the server. It starts with
dmr_live_. Every key is live, and every call is billed to the store. Never put a key in a web page, a mobile app, a URL or the source code. Read it from an environment variable. - Do not ask the developer to paste a key into the chat. Ask for the name of the environment variable that holds it.
- Send the key in the
Authorizationheader of every call:Bearerand the key. - Calls made for a customer also take the customer access token, in the
Diamra-Customer-Tokenheader. It comes from Register, Log in or Refresh in Auth. Keep both of the customer tokens on the server, out of URLs and logs. - An access token lasts an hour. A refresh token works once, so store the new one from every answer.
// The key and the customer's tokens stay on your server. Read the key from the// environment, and the access token from the session you keep for the customer.const API = "https://api.diamra.com/v1";const headers = { Authorization: `Bearer ${process.env.DIAMRA_API_KEY}`, "Diamra-Customer-Token": session.access_token, // from Register, Log in or Refresh "Content-Type": "application/json",};Calls
- Call over HTTPS only. A call over plain HTTP gets a
403and is never redirected. - A design, an estimate and a new set of views take time. The call that starts one answers at once with the status
processingand atimingobject. Ask again every few seconds. Stop when the status isfailed. See Calls that take time. - Read an error from its
errorobject. Branch oncode, showmessage, and log theRequest-Idheader of the response. - A
403 plan_requiredmeans the store is not on the Retail plan. Tell the developer. Do not retry. - Inside
/v1things are only added. Ignore a field you do not know.
// Every call: read an error from its error object, and log the Request-Id header.async function call(path, init) { const res = await fetch(`${API}${path}`, { headers, ...init }); const body = await res.json(); if (res.ok) return body; console.error(res.headers.get("Request-Id"), body.error.code, body.error.message); if (body.error.code === "plan_required") throw new Error("The store is not on the Retail plan."); // do not retry throw new Error(body.error.message);}// A design takes time. Ask again every few seconds until the status changes.let design = await call("/designs", { method: "POST", body: JSON.stringify({ prompt: "A rose gold ring with an oval sapphire" }),});while (design.status === "processing") { await new Promise((wake) => setTimeout(wake, 3000)); design = await call(`/designs/${design.id}`);}if (design.status === "failed") throw new Error("The design failed."); // stop asking// design.images holds the images, each with its id and link.Webhooks
- Check the signature of every delivery before you trust it, on the raw body, with the signing secret of that endpoint. Diamra follows Standard Webhooks, so use a Standard Webhooks library. See Signing keys.
- Answer a delivery with a 2xx within 15 seconds, then do the work. Diamra sends each event once.
- Use the
webhook-idheader to drop a repeat. Ignore an event type or a field you do not know, and still answer with a 2xx.
import express from "express";import { Webhook } from "standardwebhooks";const app = express();const wh = new Webhook(process.env.DIAMRA_WEBHOOK_SECRET); // whsec_...// express.raw keeps the body exactly as it was signed.app.post("/diamra/webhooks", express.raw({ type: "application/json" }), (req, res) => { let event; try { event = wh.verify(req.body, req.headers); // throws on a bad signature or an old timestamp } catch { return res.status(400).end(); } // event.id, event.type, event.data res.status(200).end();});Embed
- Check the origin of a
postMessagebefore you read it. See Listen for messages.
const STUDIO_ORIGIN = "https://yourstore.diamra.com";const studio = () => document.querySelector("[data-diamra-store] iframe");window.addEventListener("message", (event) => { if (event.origin !== STUDIO_ORIGIN) return; if (event.source !== studio()?.contentWindow) return; const msg = event.data; if (!msg || typeof msg.type !== "string") return; if (!msg.type.startsWith("diamra:")) return; console.log(msg.type, msg);});A usual order of work
Sign the customer in (Auth). Upload their photos if they have any (Images). Make a design (Designs). Start a project from the image they pick (Projects). Then add views, measurements and estimates.