DSR Marketplace

Developer guide

For sellers whose apps, SaaS or APIs are sold on DSR. Everything is JSON over HTTPS at https://digitalsilkroute.com/api/v1. DSR takes the payment; your software asks DSR who paid and until when.

1. Your seller key

Create a key under Seller dashboard → Delivery. It looks like dsr_sk_… and is shown once. Send it as Authorization: Bearer dsr_sk_…. Keep it on your server only: never in an app, a web page or a public repository. If it leaks, revoke it and make a new one.

2. Licence keys (installable apps)

Each buyer gets a key like DSR-7F3A1-0C9B2-55E10-AB4D7 in their DSR library. On start-up your app checks it and activates the device, up to the device limit on your listing. These two endpoints can be called straight from the app (no seller key needed).

POST https://digitalsilkroute.com/api/v1/licenses/verify
Content-Type: application/json

{ "key": "DSR-…", "device_id": "a-stable-id-for-this-device",
  "device_name": "Office PC", "product": "your-listing-slug", "activate": true }

200 { "valid": true, "product": { "slug": "…", "title": "…" },
      "plan": { "billing": "once", "active_until": null },
      "activations": { "used": 1, "max": 3 } }
403 { "valid": false, "reason": "This licence was revoked (for example after a refund)." }

Freeing a device (for example on uninstall). From the app, send the key with the same device_id that is activated; someone who only knows the key can't remove other people's devices. From your server you can free any device of your product's keys by adding your seller key.

POST https://digitalsilkroute.com/api/v1/licenses/deactivate
{ "key": "DSR-…", "device_id": "a-stable-id-for-this-device" }
(optional) Authorization: Bearer dsr_sk_…

200 { "ok": true }
404 { "ok": false, "reason": "This device isn't activated on this key." }

3. Plan checks (SaaS and API)

Ask DSR whether a customer's plan is active, by the email of their DSR account. DSR matches the email to the account, so it keeps working if the customer later changes their email on DSR. Server to server only.

curl "https://digitalsilkroute.com/api/v1/entitlements?email=buyer@example.com&product=your-listing-slug" \
  -H "Authorization: Bearer dsr_sk_…"

200 { "found": true, "product": "your-listing-slug",
      "active": true, "billing": "month", "active_until": "2026-12-06T10:00:00Z" }

Plans on DSR never renew by themselves. DSR emails the customer 7 days and 1 day before the end, and once it has ended, with a link to pay for the same plan. Paying early adds the time after the current end date.

4. Sign in with DSR (SaaS)

Let customers sign in to your app with their DSR account and get their plan in the same step (OAuth 2.0 authorization code). First add your exact return addresses under Seller dashboard → Delivery → Sign in with DSR. Your client_id is your listing's slug.

Step 1: send the customer to DSR

Make a random state, keep it in the user's session, and link to:

https://digitalsilkroute.com/oauth/authorize
  ?response_type=code
  &client_id=your-listing-slug
  &redirect_uri=https%3A%2F%2Fyourapp.com%2Fauth%2Fdsr%2Fcallback
  &state=RANDOM_VALUE

The "Sign in with DSR" button

<a href="https://digitalsilkroute.com/oauth/authorize?response_type=code&client_id=your-listing-slug&redirect_uri=https%3A%2F%2Fyourapp.com%2Fauth%2Fdsr%2Fcallback&state=RANDOM_VALUE"
   style="display:inline-flex;align-items:center;gap:8px;padding:10px 18px;border-radius:999px;
          background:#0d75ed;color:#fff;font:600 14px/20px Inter,system-ui,sans-serif;text-decoration:none">
  <img src="https://digitalsilkroute.com/favicon.ico" alt="" width="18" height="18" style="border-radius:4px;background:#fff">
  Sign in with DSR
</a>

Step 2: DSR sends them back

After they press Continue, DSR redirects to redirect_uri?code=…&state=… (or ?error=access_denied if they cancel). Check state matches. The code works once, for 10 minutes.

Step 3: swap the code on your server

curl -X POST https://digitalsilkroute.com/api/v1/oauth/token \
  -H "Authorization: Bearer dsr_sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "grant_type": "authorization_code", "code": "CODE_FROM_URL",
        "redirect_uri": "https://yourapp.com/auth/dsr/callback" }'

200 { "user": { "id": "4b0c…", "name": "Ayesha Khan", "email": "ayesha@example.com" },
      "entitlement": { "active": true,
                       "plan": { "id": "…", "name": "Pro", "billing": "month" },
                       "active_until": "2026-12-06T10:00:00Z" },
      "product": "your-listing-slug" }
400 { "error": "invalid_grant", "error_description": "This code has expired. Sign in again." }

Node example (Express). user.id never changes, so store it as the DSR id of your user; re-check the plan later with plan checks.

app.get("/auth/dsr/callback", async (req, res) => {
  if (req.query.state !== req.session.dsrState) return res.status(400).send("Bad state");
  const r = await fetch("https://digitalsilkroute.com/api/v1/oauth/token", {
    method: "POST",
    headers: { "Authorization": `Bearer ${process.env.DSR_SECRET_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ grant_type: "authorization_code", code: req.query.code,
                           redirect_uri: "https://yourapp.com/auth/dsr/callback" }),
  });
  if (!r.ok) return res.status(401).send("Sign in failed");
  const { user, entitlement } = await r.json();
  req.session.user = { dsrId: user.id, email: user.email, name: user.name, active: entitlement.active };
  res.redirect(entitlement.active ? "/app" : "/pricing");
});

5. Customer API keys (API products)

Customers with an active plan create their own key in their DSR library (dsr_bk_…, shown once, one per customer). They send it to your API; your server asks DSR whether it's valid and reports how many calls it used. Set a monthly call limit per plan under Seller dashboard → Delivery → API limits (empty = unlimited).

curl -X POST https://digitalsilkroute.com/api/v1/keys/verify \
  -H "Authorization: Bearer dsr_sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "key": "dsr_bk_…", "units": 1 }'

200 { "valid": true, "product": "your-listing-slug",
      "plan": { "id": "…", "name": "Starter", "billing": "month" },
      "active_until": "2026-12-06T10:00:00Z",
      "usage": { "used": 1532, "limit": 10000, "period": "2026-11-01" } }
403 { "valid": false, "reason": "This month's call limit for the customer's plan is used up.", … }

units is optional: leave it out (or 0) to only check, or send how many calls to count. Usage resets on the 1st of each month (UTC). Tip: cache a valid answer for a minute and send the units in batches.

6. Limits and security

  • Licence verify and deactivate: 60 requests a minute per IP address.
  • Plan checks, Sign in with DSR and customer key checks: 600 requests a minute per seller key.
  • Over the limit you get 429 with a Retry-After header (seconds). Wait that long, then try again.
  • Only the licence endpoints accept calls from browsers (CORS). Everything that takes your seller key works from servers only.
  • Redirect addresses for Sign in with DSR must match exactly and use https (http only for localhost).

Rules for selling are in the seller rules. Questions: contact DSR.