Quickstart
Five steps to an embedded, signed-in Designa workspace inside your product.
Step 1 — Register your app
Go to app.designa.ai/partner-connect, log in with a Designa account, and submit:
- Your app/company name
- Allowed origins — the domains that will embed Designa, comma-separated
- Contact email
You'll receive:
partner_id— a stable slug, e.g.yourappembed_secret— a 64-character HMAC key, shown once.
Keep embed_secret server-side
Never ship it to the browser, commit it to a repo, or log it. If you lose it, ask Designa to rotate it — don't try to recover it.Step 2 — Generate a signed embed URL
Pick one, based on whether you have a backend:
A. You have a backend (recommended). Compute the HMAC-SHA256 signature yourself. Field order is fixed and matters:
message = partnerId|partnerUserId|partnerBusinessId|role|email|exp
sig = HMAC_SHA256(embed_secret, message) // hex digest
exp = current unix time + 300 (5 min validity)Full snippet in Authentication & signing.
B. No backend (plain frontend/SPA). Ask Designa to sign it for you — never send or store embed_secret in this path at all.
async function buildDesignaEmbedUrl({ userId, businessId, role, email }) {
const res = await fetch("https://api.designa.ai/ai/partners/sign-embed-url", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
partner_id: PARTNER_ID, // your public partner id — not sensitive
partner_user_id: userId,
partner_business_id: businessId, // optional — omit/undefined defaults to userId
role, // "owner" | "admin" | "member"
email,
}),
});
if (!res.ok) throw new Error("Designa rejected this embed request.");
const signed = await res.json(); // { partnerId, partnerUserId, partnerBusinessId, partnerRole, email, exp, sig }
const params = new URLSearchParams(signed);
return `https://app.designa.ai/embed/remix?${params}`;
}Trust here is anchored on the request's Origin header matching one of your registered allowed origins — not on you holding a secret at all. This is weaker than the backend path (an Origin header can be forged by a non-browser HTTP client, though not by a genuine in-browser fetch), but means your app never needs a backend or any secret storage.
role is "owner", "admin", or "member" — admins/owners see Buy Credits and team usage; members just consume from the shared pool. More on expiry, replay protection, and the role field in Authentication & signing.
No business/team concept in your app?
partner_business_idis optional — omit it (path B) or pass your user's own id in that slot (path A) and each user gets their own solo credit pool instead of a shared one.Want to see this working before you write any signing code? Try the sandbox — it signs a test URL for you and previews it live.
Step 3 — Embed the iframe
<iframe
src="https://app.designa.ai/embed/remix?partnerId=...&partnerUserId=...&partnerBusinessId=...&partnerRole=...&email=...&exp=...&sig=..."
style="width:100%;height:600px;border:none"
allow="clipboard-write"
title="Designa Workspace">
</iframe>Other available pages: /embed/coupon-builder, /embed/ad-builder. Full reference in Embeddable pages.
Step 4 — Listen for saved designs
window.addEventListener("message", (event) => {
if (event.origin !== "https://app.designa.ai") return;
if (event.data?.type !== "DESIGNA_ASSET_CREATED") return;
const { imageUrl, designId } = event.data.payload;
// store imageUrl; pass &designId=<id> on the next embed URL to re-edit it
});Step 5 — Know how credits work
- One shared credit pool per
partnerBusinessId, visible as a balance pill inside the embed. role=admincan top up via Stripe inside the embed and view per-member usage.- Owners can set per-user spend caps from Designa's normal team page once the business exists.
Ready to ship? Run through the go-live checklist before pointing real users at your integration.