Create an SDK installation
An SDK installation is the workspace-level record that authorizes the SDK to run on your pages. Creating one gives you the publicKey you pass to MarkUpSDK.init() and registers the RSA public key MarkUp uses to verify the tokens your backend signs.
You create and manage installations from the MarkUp web app — there is no public REST endpoint for this. Installations are managed by workspace owners and admins.
Open the Developer Portal
- Sign in to MarkUp.io .
- Open the workspace you want to integrate.
- Go to Workspace settings → Developer Portal.
- Select the SDK tab.
The Developer Portal has three tabs — API Keys, Webhooks, and SDK. Only the SDK tab manages SDK installations. (API keys are a separate credential for server-to-server REST calls — see the distinction below.) The Developer Portal is only available to workspace owners and admins.
Create an installation
On the SDK tab, choose Create SDK Installation. The dialog has four steps.
1. Generate an RSA key pair
Generate an RSA key pair on your machine. Keep the private key secret on your server — you’ll paste only the public key into MarkUp.
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem2. Paste your public key
Paste the contents of public.pem (PEM format) into the dialog. MarkUp stores this as the installation’s signing key and uses it to verify the JWTs your backend signs with the matching private key.
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----3. Webpage URL (optional)
Optionally enter the URL of the page you want to collect feedback on, plus a name. MarkUp creates a markup for that URL and links it to the installation, so you get a markupId immediately. Leave it blank to point the SDK at an existing markup instead.
4. Allowed origins
List the origins where you embed the SDK — the origins where the SDK actually runs, which may differ from the page you’re marking up. Enter one full origin per line (scheme + host, e.g. https://myapp.com); paths, trailing slashes, and query strings are rejected.
https://myapp.com
https://staging.myapp.comAllowed origins are required for Sign in with MarkUp — that flow only mints a session for an origin you’ve listed here. If you authenticate only with your own backend (onTokenNeeded) or make server-to-server calls, you can instead tick Allow all origins (server-to-server / customer-JWT only). Ticking it disables Sign in with MarkUp, which requires specific origins.
Submit the dialog to create the installation.
What you get
After creating an installation you’ll see it in the installations table, with:
| Column | Meaning |
|---|---|
| Public Key | The browser-safe identifier you pass as publicKey to MarkUpSDK.init() and on exchange requests. Copy it from the table. |
| Markup ID | The linked markup’s ID — the markupId the SDK loads comments for. Shows — if you didn’t link one. |
| Allowed Origins | The origins this installation accepts, or All origins if you chose Allow all origins. |
| Status | active or revoked. Only active installations can authenticate. |
You can copy the publicKey and markupId from this table at any time. Deleting an installation invalidates its public key immediately — every SDK client using it stops working — so treat it as a revoke.
The public key is not a secret. It’s a workspace-scoped identifier that’s safe to ship in browser code. Security comes from JWT signature verification (your private key) and the allowed-origins check — not from keeping the public key hidden.
Security model
- Asymmetric (RS256) only. MarkUp verifies your tokens with the RSA public key you provide. Symmetric (HS256) signing is rejected, so there is no shared secret that could leak from the browser.
- Your private key never leaves your server. MarkUp only ever stores the public key. You sign tokens server-side and hand the SDK the result (see Authentication).
- Allowed origins are the origins where your SDK runs. They behave differently per flow: Sign in with MarkUp fails closed — it only issues a session for an origin you’ve listed, so it’s unavailable until you configure them (and impossible with Allow all origins). The REST API and the
onTokenNeeded(customer-JWT) flow treat an installation with no origins as “allow any origin”, so set origins explicitly in production even when you don’t use Sign in with MarkUp. - Rate limits are applied per installation — both a requests-per-minute limit for API calls and an exchange-per-minute limit for token exchanges. Contact MarkUp if your integration needs higher limits.
SDK installations vs. API keys
Don’t confuse the two credentials:
SDK installation publicKey | API key (sk_…) | |
|---|---|---|
| Created in | Developer Portal → SDK tab | Developer Portal → API Keys tab |
| Used by | The browser SDK (MarkUpSDK.init) | Server-to-server REST calls |
| Secret? | No — safe in browser code | Yes — treat like a password |
| Auth model | Verifies your end users via signed JWTs (or MarkUp sign-in) | Acts as the workspace/org itself |
If you’re building server automation rather than embedding the SDK, use an API key instead — see API authentication.
Next steps
- Authentication — sign JWTs for your installation, or use MarkUp’s built-in sign-in.
- Getting started — install the package and render the toolbar.