API Reference
Developer API
Programmatic access to MDSpin's conversion engine and your Knowledge Vault. Convert PDF, DOCX, Google Docs, Google Slides, and more to clean Markdown — then organize, search, and update your Vault over REST or MCP.
Authentication
All API requests require an API key sent via the Authorization header. Keys start with mdspin_ and can be generated from your API Keys dashboard.
Authorization: Bearer mdspin_your_api_key
Base URL — Conversion API
https://api.mdspin.appBase URL — Knowledge Vault & MCP
https://mdspin.appA different domain from the Conversion API above — the Vault REST endpoints and the MCP server are both served directly from the main MDSpin app.
Scopes & Permissions
Each API key carries a set of scopes that determine which endpoints it can access. All API keys include all scopes by default.
| Scope | Description | Endpoints |
|---|---|---|
| convert | Convert documents to Markdown | /v1/convert/* |
| drive | Save files to Google Drive | /v1/save/drive |
| read:account | Verify API key and read account info | /oauth/me |
| vault | Read and update your Knowledge Vault — documents, projects, search | /api/v1/vault/* |
Endpoints
/oauth/meVerify API Key
Validates an API key and returns the associated account email. Use this to confirm a key is active before making conversion requests.
Parameters
No request body — authentication is via the header.
curl -X GET https://api.mdspin.app/oauth/me \ -H "Authorization: Bearer mdspin_your_api_key"
/v1/convert/google-docConvert Google Doc (Deprecated)
Deprecated. This endpoint relied on Google Drive/Docs scopes that are no longer requested at sign-in. New users will not have a usable Google token on file. Workaround: export the Doc yourself (e.g. via Google's API or Make.com's Google Docs/Drive modules) and convert the resulting file with /v1/convert/attachment or /v1/convert/url.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| doc_id_or_url | string | Yes | Full Google Docs URL (e.g. https://docs.google.com/document/d/...) or the document ID. |
| include_metadata | boolean | No | When true, response includes character count and heading count. Defaults to false. |
curl -X POST https://api.mdspin.app/v1/convert/google-doc \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"doc_id_or_url": "https://docs.google.com/document/d/1aBcDeFgHiJkLmNoPqRsTuVwXyZ",
"include_metadata": false
}'/v1/convert/google-slidesConvert Google Slides (Deprecated)
Deprecated. This endpoint relied on Google Drive/Docs scopes that are no longer requested at sign-in. New users will not have a usable Google token on file. Workaround: export the deck as PDF or PPTX yourself (e.g. via Google's API or Make.com's Google Drive module) and convert the resulting file with /v1/convert/attachment or /v1/convert/url.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| presentation_id_or_url | string | Yes | Full Google Slides URL or just the presentation ID. |
| include_notes | boolean | No | When true, speaker notes are included under each slide. Defaults to false. |
| include_metadata | boolean | No | When true, response includes character count and heading count. Defaults to false. |
curl -X POST https://api.mdspin.app/v1/convert/google-slides \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"presentation_id_or_url": "https://docs.google.com/presentation/d/1xYzAbCdEfGhIjKlMnOpQrStUvWxYz",
"include_notes": true,
"include_metadata": false
}'/v1/convert/attachmentConvert Attachment
Converts a Base64-encoded PDF or DOCX file to Markdown. Ideal for processing email attachments or files already in memory.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| file_data | string | Yes | The file content encoded as a Base64 string. |
| filename | string | Yes | Full filename including extension, e.g. 'report.pdf' or 'notes.docx'. |
| mime_type | string | No | MIME type, e.g. 'application/pdf'. Auto-detected from filename if omitted. |
curl -X POST https://api.mdspin.app/v1/convert/attachment \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"file_data": "JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZS...",
"filename": "report.pdf",
"mime_type": "application/pdf"
}'/v1/convert/urlConvert File from URL
Fetches a file from a public URL and converts it to Markdown. Works with S3 pre-signed URLs, Dropbox links, and any direct download link.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| file_url | string | Yes | Public URL pointing to a PDF, DOCX, or other supported file. |
| filename | string | No | Override the auto-detected filename. Include extension, e.g. 'report.pdf'. |
curl -X POST https://api.mdspin.app/v1/convert/url \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"file_url": "https://example.com/files/report.pdf",
"filename": "report.pdf"
}'/v1/convert/attachments/batchBatch Convert Attachments
Converts up to 20 Base64-encoded files to Markdown in a single request. Each file is processed independently — one failure does not affect the others.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| files | array | Yes | Array of file objects (max 20). Each object must include file_data and filename, with an optional mime_type. |
curl -X POST https://api.mdspin.app/v1/convert/attachments/batch \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"files": [
{
"file_data": "JVBERi0xLjQK...",
"filename": "report.pdf"
},
{
"file_data": "UEsDBBQAAAAI...",
"filename": "notes.docx",
"mime_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}
]
}'/v1/save/driveSave Markdown to Google Drive (Deprecated)
Deprecated. This endpoint relied on Google Drive scopes that are no longer requested at sign-in. New users will not have a usable Google token on file. Workaround: take the markdown_text returned by any conversion endpoint and upload it to Drive yourself (e.g. via Google's API or Make.com's Google Drive 'Upload a File' module).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| markdown_text | string | Yes | The Markdown content to save. |
| folder_id | string | Yes | Google Drive folder ID (the last segment of the folder's URL). |
| filename | string | No | Filename without extension. Defaults to 'converted-document'. The .md extension is added automatically. |
| overwrite | boolean | No | When false (default), a timestamp is appended to avoid overwriting existing files. |
curl -X POST https://api.mdspin.app/v1/save/drive \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"markdown_text": "# Meeting Notes\n\nAttendees: Alice, Bob...",
"folder_id": "1aBcDeFgHiJkLmNoPqRsTuVwXyZ",
"filename": "meeting-notes-q1",
"overwrite": false
}'/api/v1/vault/meVault: Get Account Info
Verifies the API key (or session) and returns the authenticated user's id and how they authenticated. A lightweight check before making other Vault requests. Note: every Vault endpoint below is served from https://mdspin.app — a different domain than the conversion endpoints above (https://api.mdspin.app).
Parameters
No request body — authentication is via the header.
curl -X GET https://mdspin.app/api/v1/vault/me \ -H "Authorization: Bearer mdspin_your_api_key"
/api/v1/vault/documentsVault: List Documents
Lists documents in your Knowledge Vault, optionally filtered by project, tags, or a search term. Paginated. Never includes the document's markdown body — fetch a single document with ?include=markdown for that.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| project_id | string | No | Filter to documents in this project or its subprojects. Must be a valid UUID. |
| tags | string | No | Comma-separated list of tags to filter by. |
| search | string | No | Filter to documents whose title or filename matches this text. |
| limit | number | No | Max results per page. |
| offset | number | No | Number of results to skip, for pagination. |
curl -X GET "https://mdspin.app/api/v1/vault/documents?project_id=3fa85f64-5717-4562-b3fc-2c963f66afa6&limit=20" \ -H "Authorization: Bearer mdspin_your_api_key"
/api/v1/vault/documentsVault: Sync a Document
Upserts a document by its external identity from a connected source (e.g. a GitHub repo) — the same endpoint MDSpin's own Live Source Sync uses, exposed here for external callers. Not a general 'create any document' endpoint: it requires an existing source_connection_id from a connection you've already set up.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| source_connection_id | string | Yes | UUID of an existing source connection (created when you connect a GitHub repo to your Vault). |
| external_id | string | Yes | Stable identifier for this document at the source, e.g. a file path. |
| markdown | string | Yes | The document's Markdown content. |
| external_url | string | No | A URL back to the source, e.g. the file's GitHub URL. |
| title | string | No | Document title. Derived from the content when omitted. |
| project_id | string | No | Vault project to file the document under. Must be a project you own. |
| tags | array | No | Tags to apply to the document. |
| summary_status | string | No | 'pending' to queue an AI summary, or 'manual'. |
curl -X POST https://mdspin.app/api/v1/vault/documents \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"source_connection_id": "b6d1b5b0-3f2e-4c1a-9b8f-7f9a2f6d9e3c",
"external_id": "docs/architecture.md",
"external_url": "https://github.com/acme/wiki/blob/main/docs/architecture.md",
"markdown": "# Architecture\n\n..."
}'/api/v1/vault/documents/:idVault: Get a Document
Fetches a single document by id. Pass ?include=markdown to include its full Markdown body — omitted by default to keep the default response light.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| include | string | No | Set to 'markdown' to include the document's markdown_text in the response. |
curl -X GET "https://mdspin.app/api/v1/vault/documents/9c858901-8a57-4791-81fe-4c455b099bc9?include=markdown" \ -H "Authorization: Bearer mdspin_your_api_key"
/api/v1/vault/documents/:idVault: Update a Document
Updates a document's title, markdown body, tags, or project. Requires expected_version — the document's current version from a prior GET — so a stale, concurrent edit gets rejected (409) instead of silently overwritten. Every field you omit is left unchanged.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| expected_version | number | Yes | The document's current version. A stale value returns a 409 VERSION_CONFLICT. |
| title | string | No | New title, or null to clear it. |
| markdown_text | string | No | New Markdown body, or null to clear it. |
| tags | array | No | Replaces the document's tags entirely. |
| project_id | string | No | Moves the document to this project, or null to unfile it. Must be a project you own. |
| reason | string | No | Optional free-text note recorded on the revision. |
curl -X PATCH https://mdspin.app/api/v1/vault/documents/9c858901-8a57-4791-81fe-4c455b099bc9 \
-H "Authorization: Bearer mdspin_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"expected_version": 1,
"tags": ["finance", "q1", "reviewed"],
"reason": "Marked as reviewed"
}'/api/v1/vault/projectsVault: List Projects
Lists every project in your Vault, flat. parent_id marks a project as a subproject of another (nesting is exactly one level), so you can build a tree client-side if you need one.
Parameters
No request body — authentication is via the header.
curl -X GET https://mdspin.app/api/v1/vault/projects \ -H "Authorization: Bearer mdspin_your_api_key"
/api/v1/vault/projects/:idVault: Get a Project
Fetches a single project by id.
Parameters
No request body — authentication is via the header.
curl -X GET https://mdspin.app/api/v1/vault/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6 \ -H "Authorization: Bearer mdspin_your_api_key"
/api/v1/vault/searchVault: Search
Full-text search across every document in your Vault. project_id and tags filter the results; project_id includes a project's subprojects automatically.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| q | string | Yes | The search query. |
| project_id | string | No | Restrict results to this project and its subprojects. |
| tags | string | No | Comma-separated tags to filter by. |
| limit | number | No | Max results per page. |
| offset | number | No | Results to skip, for pagination. |
| mode | string | No | Reserved for future search modes. 'keyword' (the default) is the only accepted value today. |
curl -X GET "https://mdspin.app/api/v1/vault/search?q=quarterly+forecast&limit=10" \ -H "Authorization: Bearer mdspin_your_api_key"
/api/v1/vault/statsVault: Get Stats
Summary counts for your Vault — how many documents and top-level projects you have, and your most-used tags.
Parameters
No request body — authentication is via the header.
curl -X GET https://mdspin.app/api/v1/vault/stats \ -H "Authorization: Bearer mdspin_your_api_key"
Vault MCP Server
For AI agents rather than raw HTTP calls, your Knowledge Vault is also reachable as a Model Context Protocol server — 14 tools covering everything the REST API above exposes, plus document and project writes. Same authentication as everything else on this page.
MCP endpoint
https://mdspin.app/api/mcpConnecting a client
Using Claude Code:
claude mcp add --transport http mdspin-vault https://mdspin.app/api/mcp \ --header "Authorization: Bearer mdspin_your_api_key"
Or add it directly to any client that supports a Streamable HTTP MCP server:
{
"mcpServers": {
"mdspin-vault": {
"type": "http",
"url": "https://mdspin.app/api/mcp",
"headers": { "Authorization": "Bearer mdspin_your_api_key" }
}
}
}Read tools
| Tool | Description |
|---|---|
| vault_overview | Totals, projects, top tags, and your 10 most recently updated documents. The cheapest first call for an agent exploring your Vault. |
| search_vault | Keyword-and-meaning search across your Vault. Returns short snippets and a relevance score, never full document bodies. |
| list_documents | Filterable, keyset-paginated document listing. Prefer search_vault when looking for something specific rather than enumerating. |
| get_document | Fetch 1–5 documents by id, with a content mode: none, summary (default), outline, or full (paginated). |
| list_projects | Every project in your Vault, flat, with parent_id marking which are subprojects. |
| get_project | A single project's details and instructions, with its subprojects listed inline. |
| get_related_documents | Documents related to a given one, scoped to its top-level project. |
Write tools
| Tool | Description |
|---|---|
| create_document | Create a new document from a Markdown body. Title is derived from the first heading when omitted. |
| append_to_document | Add content to the end of an existing document without touching what's already there. |
| update_document | Full replace of title/markdown/tags/project, gated by expected_version and a required reason. Only allowed on notes and MCP-created documents — imported/converted/API-created documents return IMMUTABLE_SOURCE. |
| organize_document | Add and/or remove tags on a document. Additive/subtractive only — there's no 'set tags'. |
| remove_from_vault | Reversibly remove a document from listings and search. There is no delete tool. |
| create_project | Create a project, optionally nested one level under an existing top-level project. |
| update_project | Rename a project, change its color or instructions, or move it in or out of nesting. |
Error Codes
The REST API returns standard HTTP status codes with a JSON body of the shape { "error": "...", "message": "..." }. The Make error type column shows which class our Make.com custom app raises for that status — useful if you are branching on error type inside a Make scenario.
| Status | Meaning | Make error type | What to do |
|---|---|---|---|
| 400 | Bad Request | DataError | Check your request body — a required parameter is missing or malformed. |
| 401 | Unauthorized | InvalidConnectionError | Your API key is missing, invalid, or expired. In Make, the scenario prompts a reconnect. |
| 403 | Forbidden | InvalidAccessTokenError | Your API key does not have access to this resource, or the Drive folder is not shared with the connected account. |
| 404 | Not Found | DataError | The document, folder, or endpoint does not exist. Check the URL or ID. |
| 413 | Payload Too Large | DataError | The file exceeds the size limit. Reduce file size or use the batch endpoint for multiple smaller files. |
| 429 | Too Many Requests | RateLimitError | Rate limit exceeded. Wait and retry with exponential backoff. Make retries automatically. |
| 500 | Internal Server Error | RuntimeError | Unexpected server error. Retry the request. If it persists, contact support. |
| 502 | Bad Gateway | RuntimeError | Upstream error. Retry. |
| 503 | Service Unavailable | RuntimeError | Temporary outage or maintenance. Retry after a short delay. |
Partial failures in batch conversion
POST /v1/convert/attachments/batch always returns 200, even when some files fail. Inspect the response body to handle them:
- •
total,succeeded,failed— summary counts - •
results[].success— per-file boolean - •
results[].error,results[].message— populated whensuccessis false
Inside the Make app, this module raises a DataError whenfailed > 0, surfacing the first failure's message so the scenario halts rather than silently passing partial data downstream.
Example error response
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": "invalid_api_key",
"message": "API key invalid or expired. Reconnect your MDSpin account."
}Supported Formats
application/pdf
DOCX
application/vnd.openxmlformats-...
DOC
application/msword
PPTX
application/vnd.openxmlformats-...
Google Docs
via URL or ID
Google Slides
via URL or ID
TXT
text/plain
RTF
application/rtf
PNG
image/png
JPG
image/jpeg