মূল content-এ যান
Developer API · v1

Doinik Mind Map REST API

নিজের script, Zapier/n8n automation বা অন্য কোনো app থেকে Mind Map তৈরি, update, export করুন। JSON in, JSON out — Bearer API Key দিয়ে authenticate, আর সব message Banglish।

Premium feature
Base URL:https://staging.doinikmindmap.com/api/v1

01

৩ step-এ শুরু করুন

  1. Profile page-এর API Keys card থেকে “নতুন Key বানান” — Key-টা একবারই দেখানো হবে, copy করে রাখুন।
  2. প্রতি request-এ Authorization: Bearer dmm_… header দিন।
  3. GET /api/v1/me call করে দেখুন সব ঠিক আছে কি না।
Quick start
# 1) কে আমি?
curl https://staging.doinikmindmap.com/api/v1/me \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n"

# 2) নতুন Map বানান (template থেকে)
curl -X POST https://staging.doinikmindmap.com/api/v1/maps \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n" \
  -H "Content-Type: application/json" \
  -d '{"title":"Exam prep","templateId":"study-notes"}'

# 3) Markdown হিসেবে export
curl -L https://staging.doinikmindmap.com/api/v1/maps/cmv3k8p2q0001x7d1a9b2c3d4/export?format=md \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n" -o exam-prep.md
JavaScript (fetch)
const res = await fetch("https://staging.doinikmindmap.com/api/v1/maps", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.DMM_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ title: "Weekly plan", templateId: "weekly-planner" }),
});
const json = await res.json();
if (!json.ok) throw new Error(json.error); // Bangla message
console.log(json.data.map.id);

02

Authentication

সব /api/v1/* endpoint শুধু Bearer API Key দিয়ে কাজ করে — login cookie/session এখানে কাজ করবে না। Key-এর format: dmm_ + ৪০টা random অক্ষর (মোট ৪৪)।

Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n
  • Key আপনার account-এর সব Map access করতে পারে (owner হিসেবে যেগুলো আপনার, আর collaborator হিসেবে যেগুলো share করা)।
  • Server-এ শুধু Key-এর SHA-256 hash থাকে; plaintext হারালে revoke করে নতুন বানান।
  • একসাথে সর্বোচ্চ ১০টা active Key। Revoke করলে সাথে সাথে সেই Key-এর request 401 পায়।
  • Key শেষ কবে ব্যবহার হয়েছে সেটা Profile-এ দেখা যায় (lastUsedAt, মিনিটে একবার update হয়)।

Key নিরাপদ রাখুন

Browser-এর public JavaScript, GitHub repo বা screenshot-এ কখনো Key বসাবেন না। Server-side code বা environment variable-এ (DMM_API_KEY) রাখুন। সন্দেহ হলে Profile থেকে Revoke করুন।

03

Rate limit

প্রতি API Key-তে মিনিটে ১২০টা request (sliding window)। Limit পার হলে 429 আসে, সাথে Retry-After header (কত second পরে আবার try করবেন)।

Headerমানে
X-RateLimit-LimitWindow-এ মোট কতটা request (120)
X-RateLimit-Remainingএই মিনিটে আর কতটা বাকি
Retry-Afterশুধু 429-এ: কত second পরে আবার try করবেন
429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0

{ "ok": false, "error": "API rate limit পার হয়ে গেছে (প্রতি Key-তে মিনিটে ১২০টা request)। একটু পরে আবার try করুন।", "code": "RATE_LIMITED", "retryAfterSec": 23 }

04

Response envelope ও error code

প্রতিটা JSON response একই খামে আসে: সফল হলে { ok: true, data }, ভুল হলে { ok: false, error, code }। error সবসময় মানুষের পড়ার মতো Banglish message — সরাসরি user-কে দেখাতে পারেন; program-এ branch করতে code ব্যবহার করুন।

Success
{ "ok": true, "data": { "id": "cmulyy1w4000o7d1kd42zznw1", "name": "Tanvir", "planTier": "PREMIUM" } }
Error
{ "ok": false, "error": "এই Map-টা পাওয়া যায়নি বা আপনার access নেই।", "code": "NOT_FOUND" }
HTTPcodeকখন
400VALIDATION / BAD_REQUESTBody বা query ঠিক নেই (Zod)। error-এ প্রথম সমস্যাটা লেখা থাকে।
401UNAUTHORIZEDKey নেই, ভুল, format ঠিক নেই বা revoke করা।
402PLAN_LIMITPlan-এ API access নেই, অথবা Map/Node limit পার হচ্ছে।
403FORBIDDEN / BANNEDMap-এ edit/delete permission নেই (viewer), বা account বন্ধ।
404NOT_FOUNDMap/Template নেই, delete করা, বা আপনার access নেই (সেটাও 404 — id guess করা আটকাতে)।
429RATE_LIMITEDমিনিটে ১২০-এর বেশি request। Retry-After দেখুন।
500INTERNALআমাদের দিকের সমস্যা — একটু পরে retry করুন।

সব response-এ Cache-Control: no-store থাকে। Date সবসময় ISO-8601 UTC string (2026-09-28T08:40:12.000Z)।

05

Endpoints

Base URL: https://staging.doinikmindmap.com/api/v1। সব path-এর জন্য OPTIONS preflight-ও আছে (দেখুন CORS)।

GET/api/v1/me

Key-এর মালিক কে

Key ঠিক আছে কি না test করার সবচেয়ে সহজ উপায়। Account-এর id, name আর planTier দেয়।
Request (curl)
curl https://staging.doinikmindmap.com/api/v1/me \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n"
Response
{
  "ok": true,
  "data": { "id": "cmulyy1w4000o7d1kd42zznw1", "name": "Tanvir", "planTier": "PREMIUM" }
}
GET/api/v1/maps

Map list (নিজের + share করা)

আপনার own Map আর যেগুলোতে আপনাকে collaborator করা হয়েছে — সবগুলোর summary, শেষ update অনুযায়ী sort করা। Document (data) এখানে থাকে না; সেটার জন্য GET /maps/{id}।
ParameterInTypeবিবরণ
pagequerynumberকত নম্বর page (default 1)।
limitquerynumberপ্রতি page-এ কতটা, 1–100 (default 20)।
qquerystringTitle-এ search (case-insensitive, max 100 অক্ষর)।
archivedquery"false" | "true" | "all"Default false = শুধু active Map। true = শুধু archived, all = সব।
Request (curl)
curl "https://staging.doinikmindmap.com/api/v1/maps?page=1&limit=20&q=exam" \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n"
Response
{
  "ok": true,
  "data": {
    "maps": [
      {
        "id": "cmv3k8p2q0001x7d1a9b2c3d4",
        "title": "Exam prep",
        "description": null,
        "nodeCount": 12,
        "isPublic": false,
        "isArchived": false,
        "tags": ["study"],
        "createdAt": "2026-09-01T10:15:00.000Z",
        "updatedAt": "2026-09-28T08:40:12.000Z",
        "lastOpenedAt": "2026-09-28T08:40:12.000Z",
        "ownerId": "cmulyy1w4000o7d1kd42zznw1",
        "role": "OWNER"
      }
    ],
    "page": 1,
    "limit": 20,
    "total": 1,
    "hasMore": false
  }
}

role = OWNER | EDITOR | VIEWER। Viewer হলে PATCH/DELETE-এ 403 পাবেন।

POST/api/v1/maps

নতুন Map তৈরি

তিনভাবে বানানো যায়: শুধু title (একটা root Node নিয়ে খালি Map), templateId (built-in slug যেমন study-notes, অথবা community template-এর id/slug), কিংবা পুরো data document (দেখুন Map document format)। Dashboard-এর মতোই plan-এর Map limit আর Node limit এখানেও খাটে।
ParameterInTypeবিবরণ
titlerequiredbodystringMap-এর নাম, 1–120 অক্ষর।
descriptionbodystringসর্বোচ্চ 500 অক্ষর।
templateIdbodystringBuilt-in template slug (GET /templates দেখুন) বা community template id/slug। data থাকলে এটা ignore হয়।
databodyMapDocumentপুরো document। Node label/note plain text করা হয়, rich html sanitize হয়।
Request (curl)
curl -X POST https://staging.doinikmindmap.com/api/v1/maps \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Exam prep",
    "description": "HSC physics chapter 3",
    "templateId": "study-notes"
  }'
Response · 201 Created
{
  "ok": true,
  "data": {
    "map": {
      "id": "cmv3k8p2q0001x7d1a9b2c3d4",
      "title": "Exam prep",
      "description": "HSC physics chapter 3",
      "nodeCount": 15,
      "isPublic": false,
      "isArchived": false,
      "tags": [],
      "createdAt": "2026-09-29T04:12:09.000Z",
      "updatedAt": "2026-09-29T04:12:09.000Z",
      "lastOpenedAt": "2026-09-29T04:12:09.000Z",
      "ownerId": "cmulyy1w4000o7d1kd42zznw1",
      "role": "OWNER"
    }
  }
}

Template-এ plan-এর Node limit-এর বেশি Node থাকলে refuse না করে limit পর্যন্ত trim করা হয় (Premium-এ limit নেই)।

GET/api/v1/maps/{id}

একটা Map, পুরো document সহ

Map-এর metadata + পুরো data (nodes, edges, settings, viewport)। Owner, editor, viewer — সবাই পড়তে পারে। Public Map-ও এই Key দিয়ে পড়া যায়।
ParameterInTypeবিবরণ
idrequiredpathstringMap id (list বা create response থেকে)।
Request (curl)
curl https://staging.doinikmindmap.com/api/v1/maps/cmv3k8p2q0001x7d1a9b2c3d4 \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n"
Response
{
  "ok": true,
  "data": {
    "map": {
      "id": "cmv3k8p2q0001x7d1a9b2c3d4",
      "title": "Exam prep",
      "description": null,
      "nodeCount": 3,
      "isPublic": false,
      "isArchived": false,
      "tags": [],
      "createdAt": "2026-09-01T10:15:00.000Z",
      "updatedAt": "2026-09-28T08:40:12.000Z",
      "lastOpenedAt": null,
      "ownerId": "cmulyy1w4000o7d1kd42zznw1",
      "templateId": "study-notes",
      "data": {
        "version": 1,
        "nodes": [
          { "id": "root", "type": "mindNode", "position": { "x": 0, "y": 0 },
            "data": { "label": "Chapter 3", "isRoot": true, "shape": "rounded", "color": "#4F46E5", "textColor": "#ffffff", "borderColor": "#4F46E5", "borderStyle": "solid", "borderWidth": 2, "fontSize": 14, "fontWeight": "normal" } },
          { "id": "n1", "type": "mindNode", "position": { "x": 260, "y": -80 }, "data": { "label": "Formulas", "shape": "rounded", "color": "#ffffff", "textColor": "#0f172a", "borderColor": "#4F46E5", "borderStyle": "solid", "borderWidth": 2, "fontSize": 14, "fontWeight": "normal" } },
          { "id": "n2", "type": "mindNode", "position": { "x": 260, "y": 80 }, "data": { "label": "Examples", "note": "পরীক্ষায় আসে", "shape": "rounded", "color": "#ffffff", "textColor": "#0f172a", "borderColor": "#4F46E5", "borderStyle": "solid", "borderWidth": 2, "fontSize": 14, "fontWeight": "normal" } }
        ],
        "edges": [
          { "id": "e_root_n1", "source": "root", "target": "n1", "type": "mindEdge", "data": { "style": "curved", "arrow": "none" } },
          { "id": "e_root_n2", "source": "root", "target": "n2", "type": "mindEdge", "data": { "style": "curved", "arrow": "none" } }
        ],
        "settings": { "theme": "default", "background": "dots", "snapToGrid": false, "gridSize": 20, "layout": "free", "defaultEdgeStyle": "curved" }
      }
    },
    "role": "OWNER",
    "owner": { "id": "cmulyy1w4000o7d1kd42zznw1", "name": "Tanvir" }
  }
}
PATCH/api/v1/maps/{id}

Map update (title, tags, document…)

যেটা পাঠাবেন শুধু সেটাই বদলায়। data দিলে পুরো document replace হয় — তাই আগে GET করে, বদলে, তারপর PATCH করুন। Owner আর editor করতে পারে; isArchived শুধু owner।
ParameterInTypeবিবরণ
titlebodystring1–120 অক্ষর।
descriptionbodystring | nullসর্বোচ্চ 500 অক্ষর; null দিলে মুছে যায়।
databodyMapDocumentপুরো document। Node limit owner-এর plan অনুযায়ী — শুধু সেই save refuse হয় যেটা Map-কে limit-এর বাইরে বড় করে।
tagsbodystring[]সর্বোচ্চ 10টা, প্রতিটা 30 অক্ষর।
isArchivedbodybooleanArchive / unarchive (owner only)।
createVersionbodybooleantrue দিলে save-এর আগে একটা version snapshot নেয় (Standard+ owner)।
versionLabelbodystringSnapshot-এর নাম, max 80।
Request (curl)
curl -X PATCH https://staging.doinikmindmap.com/api/v1/maps/cmv3k8p2q0001x7d1a9b2c3d4 \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Exam prep (final)",
    "tags": ["study", "physics"],
    "data": {
      "version": 1,
      "nodes": [
        { "id": "root", "position": { "x": 0, "y": 0 }, "data": { "label": "Chapter 3", "isRoot": true } },
        { "id": "n1", "position": { "x": 260, "y": -80 }, "data": { "label": "Formulas" } },
        { "id": "n2", "position": { "x": 260, "y": 80 }, "data": { "label": "Examples", "note": "পরীক্ষায় আসে" } }
      ],
      "edges": [
        { "id": "e1", "source": "root", "target": "n1" },
        { "id": "e2", "source": "root", "target": "n2" }
      ],
      "settings": { "theme": "default" }
    }
  }'
Response
{
  "ok": true,
  "data": {
    "map": {
      "id": "cmv3k8p2q0001x7d1a9b2c3d4",
      "title": "Exam prep (final)",
      "description": null,
      "nodeCount": 3,
      "updatedAt": "2026-09-29T04:20:41.000Z",
      "isArchived": false,
      "tags": ["study", "physics"]
    }
  }
}

Node-এর label/note plain text হিসেবে রাখা হয় (HTML tag থাকলেও text হিসেবেই দেখাবে); rich text চাইলে data.html দিন — সেটা DOMPurify দিয়ে sanitize হয়।

Free plan-এর owner-এর Map-এ 20-এর বেশি Node করতে চাইলে 402 PLAN_LIMIT; কিন্তু আগে থেকেই বড় Map ছোট করা যায়।

DELETE/api/v1/maps/{id}

Map delete (trash)

শুধু owner। Soft delete — Map trash-এ যায়, public link বন্ধ হয়, list/GET-এ আর দেখায় না।
ParameterInTypeবিবরণ
idrequiredpathstringMap id।
Request (curl)
curl -X DELETE https://staging.doinikmindmap.com/api/v1/maps/cmv3k8p2q0001x7d1a9b2c3d4 \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n"
Response
{ "ok": true, "data": { "deleted": true, "id": "cmv3k8p2q0001x7d1a9b2c3d4" } }
GET/api/v1/maps/{id}/export?format=json|md

Export (JSON বা Markdown file)

JSON envelope না — সরাসরি file body আসে, Content-Disposition: attachment সহ। json = আমাদের নিজস্ব re-importable format, md = nested Markdown outline। বিস্তারিত: Export format।
ParameterInTypeবিবরণ
idrequiredpathstringMap id।
formatquery"json" | "md"Default json।
Request (curl)
curl -L "https://staging.doinikmindmap.com/api/v1/maps/cmv3k8p2q0001x7d1a9b2c3d4/export?format=md" \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n" -o exam-prep.md
Response · text/markdown
HTTP/1.1 200 OK
Content-Type: text/markdown; charset=utf-8
Content-Disposition: attachment; filename="exam-prep.md"; filename*=UTF-8''Exam%20prep.md

# Chapter 3

- Formulas
- Examples
  > পরীক্ষায় আসে
GET/api/v1/templates

Template list

২৪টা built-in Banglish template + community-র public template + আপনার নিজেরগুলো। slug-টা POST /maps-এর templateId হিসেবে দিন।
ParameterInTypeবিবরণ
categoryquerystringplanning | business | study | personal | creative | general | custom
qquerystringTitle/description-এ search।
withDataquery"1"1 দিলে প্রতিটা template-এর পুরো document (data)-ও আসে।
Request (curl)
curl "https://staging.doinikmindmap.com/api/v1/templates?category=study" \
  -H "Authorization: Bearer dmm_x9K2pQ7vL4mN8bR3tY6wA1cE5hJ0uZ2sD4fG7kM9n"
Response
{
  "ok": true,
  "data": {
    "templates": [
      {
        "id": "builtin_study-notes",
        "slug": "study-notes",
        "title": "Study Notes",
        "titleBn": "Study Notes",
        "description": "একটা chapter-এর সব topic, formula আর example এক জায়গায়।",
        "category": "study",
        "thumbnail": null,
        "isBuiltIn": true,
        "isPublic": true,
        "isMine": false,
        "downloads": 0,
        "nodeCount": 15,
        "author": null,
        "createdAt": "1970-01-01T00:00:00.000Z",
        "updatedAt": "1970-01-01T00:00:00.000Z"
      }
    ],
    "total": 1
  }
}

06

Map document format

একটা Map-এর পুরো content একটা JSON document — { version: 1, nodes, edges, settings, viewport? }। Canvas-এ React Flow ব্যবহার হয়, তাই node/edge-এর shape-ও সেটার মতো। নিচের field-গুলো ছাড়া বাকি সব optional; না দিলে default বসে।

Minimal document
{
  "version": 1,
  "nodes": [
    { "id": "root", "position": { "x": 0, "y": 0 }, "data": { "label": "আমার Idea", "isRoot": true } },
    { "id": "n1",   "position": { "x": 260, "y": 0 }, "data": { "label": "প্রথম branch" } }
  ],
  "edges": [
    { "id": "e1", "source": "root", "target": "n1" }
  ],
  "settings": { "theme": "default", "layout": "free" }
}

nodes[]

  • id (unique, ≤64), position.x/y
  • type: "mindNode" (default)
  • data.label (text, ≤2000), data.isRoot — ঠিক একটা root রাখুন
  • data.html rich text (sanitized), note ≤5000, link, icon (emoji), image
  • Style: shape (rectangle | rounded | oval | diamond | cloud | hexagon), color, textColor, borderColor, borderStyle, borderWidth, fontSize, fontWeight
  • Extra: tags[], progress 0–100, priority 0–5, collapsed

edges[]

  • id, source, target (node id)
  • type: "mindEdge" (default)
  • data.style: curved | straight | elbow
  • data.arrow: none | one | two
  • data.kind: "link" দিলে cross-link (hierarchy না)
  • data.label, color, width, dashed, animated

settings

  • theme: default | ocean | forest | sunset …
  • background: dots | lines | cross | none
  • layout: free | radial | tree | horizontal | vertical | organic
  • snapToGrid, gridSize (5–100)
  • defaultEdgeStyle
  • branding { text, logo, hideWatermark } (Premium export)
  • Limit: সর্বোচ্চ 5000 node, 10000 edge per document। Plan-এর Node limit আলাদা (Free 20, Standard/Premium unlimited)।
  • Root থেকে edge ধরে যে Node-এ পৌঁছানো যায় সেগুলোই outline/Markdown-এ আসে; বাকিগুলো “অন্যান্য Node” হিসেবে।
  • Server nodeCount নিজে হিসাব করে (nodes.length) — আপনাকে পাঠাতে হবে না।

07

Export format

API দিয়ে দুটো text format export করা যায়; PNG/SVG/PDF app-এর Export button থেকে (browser-এ render লাগে)।

format=json
{
  "app": "doinik-mind-map",
  "version": 1,
  "title": "Exam prep",
  "exportedAt": "2026-09-29T04:25:00.000Z",
  "data": { "version": 1, "nodes": [...], "edges": [...], "settings": {...} }
}
format=md
# Chapter 3

- 📌 Formulas
  - Newton's 2nd law
- Examples ([link](https://example.com))
  > পরীক্ষায় আসে

## অন্যান্য Node

- Loose note
  • json — একই file পরে app-এ Import করা যায় (Dashboard → Import) বা POST /maps-এর data হিসেবে পাঠানো যায় (.data অংশটা)।
  • md — Notion/Obsidian-এ paste করার মতো nested outline। Node-এর emoji icon, link আর note-ও আসে।

08

CORS ও browser থেকে call

v1 cookie ব্যবহার করে না, তাই CORS পুরো খোলা: Access-Control-Allow-Origin: *। যেকোনো origin থেকে fetch করতে পারবেন — কিন্তু মনে রাখবেন, browser-এর JavaScript-এ Key বসালে সেটা যে কেউ দেখতে পাবে। Browser app-এর জন্য নিজের backend-এ proxy করুন।

Preflight
OPTIONS /api/v1/maps  →  204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Allow-Methods: GET, POST, PATCH, DELETE, OPTIONS
Access-Control-Expose-Headers: Retry-After, Content-Disposition, X-RateLimit-Limit, X-RateLimit-Remaining
Access-Control-Max-Age: 86400

09

Plan, Key আর limit

API access শুধু Premium plan-এ

Free বা Standard account থেকে Key বানানো যায় না; আগে বানানো Key-ও plan downgrade হলে 402 PLAN_LIMIT পায়। Pricing দেখুন।
  • Key বানান/revoke করুন: Profile → API Keys। প্রতি account-এ ১০টা active Key।
  • Key দিয়ে বানানো Map-ও আপনার Dashboard-এ সাথে সাথে দেখা যায় (এবং উল্টোটাও)।
  • Key-এর তৈরি আর revoke — দুটোই audit log-এ থাকে।
  • কোনো সমস্যা? Support-এ লিখুন, subject-এ “API” লিখলে দ্রুত পাবেন।

তৈরি? প্রথম Key-টা বানিয়ে ফেলুন।

Profile page-এর API Keys card থেকে — ৩০ second-এর কাজ।