API, webhooks and inbound addresses
Version 1 · part of the paid plan · OpenAPI 3.1
Three ways to connect your notes to other tools. All three are set up in the app, in Settings > API and automations.
- Webhooks: SharpMD calls an address when a note or a kanban card changes. Paste a Slack address and it posts a readable line.
- Inbound addresses: a secret address that adds text to a note, creates a note or creates a card. Good for forms, sales and email.
- API: read and write notes and move cards from a flow, with a token.
Webhooks
An automation watches the whole account, one folder or one note, and sends the events you pick to an https address. In a team, the admin can watch the team space, and so can the editors if the admin turns that on in the team settings.
| Event | When | data |
|---|---|---|
note.created | A note is created | rev, size, updated |
note.updated | A note changes. Saves in a row arrive as one event | rev, size, updated |
note.moved | A note is moved or renamed | from, to |
note.deleted | A note goes to the trash | trash |
note.restored | A note comes back from the trash | rev, size |
comment.created | Someone leaves a comment for the AI | comment: id, text, quote |
comment.resolved | A comment is marked as done | comment: id, reply |
card.created | A card is added to a board | card, board |
card.moved | A card changes column (its status) | card, from, to |
card.updated | The title or an attribute of a card changes | card, changes: old and new value per key |
card.done | A card becomes done. Moving it into the done column sends card.moved and then this one | card |
card.deleted | A card is removed | card |
Card events come out whether the change was made in the app, through the API or by an AI over MCP. Over MCP the AI has the same card operations as tools: list_boards, create_board, add_card, move_card, update_card and delete_card. Notes inside a protected folder never produce events.
What arrives
POST /your/address
Content-Type: application/json
X-SharpMD-Event: card.moved
X-SharpMD-Delivery: evt_Zk3v9Q0aXc81LmPq7RtY
X-SharpMD-Signature: t=1791380591,v1=5f2b…
{
"id": "evt_Zk3v9Q0aXc81LmPq7RtY",
"type": "card.moved",
"created": "2026-10-07T14:03:11Z",
"account": "acc_3f1c9a7b2d4e5f601234",
"note": { "path": "shop/board.md", "name": "board.md",
"url": "https://sharpmd.app/src/app.html?f=cloud%2Fshop%2Fboard.md", "space": "own" },
"actor": { "type": "app" },
"data": {
"card": { "id": "c8k2m9xq", "title": "Fix checkout", "column": "Done", "done": false,
"created": "2026-10-01T10:00:00Z", "updated": "2026-10-07T14:03:10Z",
"attrs": { "due": "2026-10-20", "owner": "Ana Paz" } },
"from": "To do", "to": "Done", "board": 0, "rev": 12
}
}
account is an opaque id, never an email address. actor.type is app, api, mcp, inbox, or member with an opaque id and the role when a team member did it. The text of the note is not sent unless the automation has "Include the content of the note" on (up to 64 KB, in data.text).
Check the signature
The signature is the HMAC-SHA-256, in hexadecimal, of t + "." + body with the secret shown when the automation was created. Compare it with v1 and reject a t older than five minutes.
const crypto = require('crypto');
function valid(header, rawBody, secret) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || '');
if (!m || Math.abs(Date.now() / 1000 - m[1]) > 300) return false;
const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}
Delivery
Answer with a 2xx within 8 seconds. Anything else is retried up to 5 times within an hour, with the same id. After 15 failed attempts in a row the automation turns itself off and the app says so. Redirects are not followed, and the address has to be public: private networks are refused. The last 50 deliveries are in the app, with status, response code and duration.
Inbound addresses
An address like https://sync.sharpmd.app/in/mdi_…. Whoever has it can add to that note and nothing else. It is shown once; you can replace it at any time.
curl -X POST https://sync.sharpmd.app/in/mdi_YOUR_SECRET \
-H "Content-Type: application/json" \
-d '{"text": "New order from Ana, $ 120"}'
text/plain: the body is the text.- JSON with
text(andtitle, for the name of a new note). Any other JSON becomes a table of field and value. - Forms (
application/x-www-form-urlencodedormultipart/form-data): the fields become a list. Files are skipped. - A template per address:
- {{date}} {{text}}. It also takes{{time}},{{title}}and any field by its name. - On a board: each request becomes a card in the column you chose, and the other fields become its attributes.
Up to 64 KB and 60 requests per minute. The answer is {"ok": true}.
API
Create a token in Settings > API and automations, under API tokens. The same tokens connect your AI. A token limited to a folder only reaches that folder. Send it in every request:
curl https://sync.sharpmd.app/api/v1/notes?folder=shop \
-H "Authorization: Bearer mdt_YOUR_TOKEN"
Answers are {"ok": true, "data": …} or {"ok": false, "error": {"code", "message"}}. 120 requests per minute per token. Every write returns the url that opens the note in the app.
| Request | What it does |
|---|---|
GET /api/v1/notes | List notes. folder, limit, cursor |
GET /api/v1/note?path= | Read a note: text and rev |
PUT /api/v1/note | Create or replace. {path, text, rev?} |
POST /api/v1/note/append | Add at the end. {path, text} |
POST /api/v1/note/move | Move or rename. {from, to} |
DELETE /api/v1/note?path= | Send to the trash |
GET /api/v1/folders · /search?q= · /history?path= | Folders, search, earlier versions |
GET /api/v1/comments · POST /api/v1/comments/{id}/resolve | Comments for the AI |
GET /api/v1/boards?path= | The boards of a note: columns and cards with their attributes |
POST /api/v1/boards/cards | Create a card. {path, column, title, attrs?} |
POST /api/v1/boards/cards/{id}/move | Move it. {path, column} |
POST /api/v1/boards/cards/{id}/done | Tick it. {path} |
PATCH /api/v1/boards/cards/{id} | Change title, column or attributes |
DELETE /api/v1/boards/cards/{id}?path= | Remove it |
curl -X POST https://sync.sharpmd.app/api/v1/boards/cards/c8k2m9xq/move \
-H "Authorization: Bearer mdt_YOUR_TOKEN" -H "Content-Type: application/json" \
-d '{"path": "shop/board.md", "column": "Done"}'
Send rev to write only if the note is still at that revision: otherwise the answer is 409 rev_conflict and nothing is written. Team notes are under @team/; with a token of the team, the team space is the root. A reader of a team cannot write through the API either. Protected folders are out of reach while they are locked. The full description, with every field, is in the OpenAPI file.
Cards in Markdown
A board is a kanban code block. Each heading is a column and each task a card. Attributes go in braces at the end of the card; id, created and updated are written by SharpMD.
```kanban
{show=due,owner priority=low|medium|high}
## To do
- [ ] Fix checkout {due=2026-10-20 owner="Ana Paz" id=c8k2m9xq created=2026-10-07T14:03:11Z}
## Done
```
Make, n8n, Activepieces, Zapier, Slack
Slack
- In Slack, add an incoming webhook to a channel and copy its address.
- In SharpMD: Settings > API and automations > New automation. Pick where to watch and the events.
- Choose Slack, paste the address, Create, then Send a test.
The channel gets lines like: Card "Fix checkout" moved from To do to Done in shop/board.md. Discord works the same with its webhook address.
Make
- Start a scenario with Webhooks > Custom webhook and copy its address.
- In SharpMD, create an automation with the format "Make, n8n, Zapier or other" and that address. Send a test so Make learns the fields.
- To write back, add an HTTP > Make a request module with the header
Authorization: Bearer mdt_…, or post to an inbound address.
n8n
- Add a Webhook node (POST) and copy its production URL into a SharpMD automation.
- To act on SharpMD, add an HTTP Request node with Header Auth: name
Authorization, valueBearer mdt_…. - The curl examples on this page can be pasted with Import cURL.
Activepieces
- Use the Webhook trigger and paste its live URL into a SharpMD automation.
- Use the HTTP piece (Send HTTP request) with the
Authorizationheader to call the API.
Zapier
- Trigger: Webhooks by Zapier > Catch Hook. Paste its address into a SharpMD automation and send a test.
- Action: Webhooks by Zapier > POST to an inbound address, or a Custom Request to the API with the
Authorizationheader.
Self-hosting
The server is open source. Replace https://sync.sharpmd.app with your own address. The variables are in the server README, and Privacy says what is sent and what is kept.
API, webhooks y direcciones de entrada
Versión 1 · parte del plan pago · OpenAPI 3.1
Tres formas de conectar tus notas con otras herramientas. Las tres se arman en la app, en Ajustes > API y automatizaciones.
- Webhooks: SharpMD llama a una dirección cuando cambia una nota o una tarjeta del tablero. Pegás una dirección de Slack y publica una línea legible.
- Direcciones de entrada: una dirección secreta que agrega texto a una nota, crea una nota o crea una tarjeta. Sirve para formularios, ventas y correo.
- API: leer y escribir notas y mover tarjetas desde un flujo, con un token.
Webhooks
Una automatización mira toda la cuenta, una carpeta o una nota, y manda los eventos que elijas a una dirección https. En un equipo, quien lo administra puede mirar el espacio del equipo, y también quienes editan si lo habilita en los ajustes del equipo.
| Evento | Cuándo | data |
|---|---|---|
note.created | Se crea una nota | rev, size, updated |
note.updated | Cambia una nota. Los guardados seguidos llegan como un solo evento | rev, size, updated |
note.moved | Se mueve o se renombra | from, to |
note.deleted | Va a la papelera | trash |
note.restored | Vuelve de la papelera | rev, size |
comment.created | Alguien deja un comentario para la IA | comment: id, text, quote |
comment.resolved | Un comentario queda resuelto | comment: id, reply |
card.created | Se agrega una tarjeta a un tablero | card, board |
card.moved | Una tarjeta cambia de columna (su estado) | card, from, to |
card.updated | Cambia el título o un atributo | card, changes: valor anterior y nuevo por clave |
card.done | Una tarjeta queda hecha. Moverla a la columna de hechas manda card.moved y después este | card |
card.deleted | Se quita una tarjeta | card |
Los eventos de tarjeta salen venga el cambio de la app, de la API o de una IA por MCP. Por MCP la IA tiene las mismas operaciones de tarjetas como herramientas: list_boards, create_board, add_card, move_card, update_card y delete_card. Las notas de una carpeta protegida nunca generan eventos.
Qué llega
POST /tu/direccion
Content-Type: application/json
X-SharpMD-Event: card.moved
X-SharpMD-Delivery: evt_Zk3v9Q0aXc81LmPq7RtY
X-SharpMD-Signature: t=1791380591,v1=5f2b…
{
"id": "evt_Zk3v9Q0aXc81LmPq7RtY",
"type": "card.moved",
"created": "2026-10-07T14:03:11Z",
"account": "acc_3f1c9a7b2d4e5f601234",
"note": { "path": "tienda/tablero.md", "name": "tablero.md",
"url": "https://sharpmd.app/src/app.html?f=cloud%2Ftienda%2Ftablero.md", "space": "own" },
"actor": { "type": "app" },
"data": {
"card": { "id": "c8k2m9xq", "title": "Arreglar el pago", "column": "Hecho", "done": false,
"created": "2026-10-01T10:00:00Z", "updated": "2026-10-07T14:03:10Z",
"attrs": { "vence": "2026-10-20", "responsable": "Ana Paz" } },
"from": "Por hacer", "to": "Hecho", "board": 0, "rev": 12
}
}
account es un identificador opaco, nunca un correo. actor.type es app, api, mcp, inbox, o member con un id opaco y su role cuando lo hizo alguien del equipo. El texto de la nota no viaja salvo que la automatización tenga prendido "Incluir el contenido de la nota" (hasta 64 KB, en data.text).
Comprobar la firma
La firma es el HMAC-SHA-256, en hexadecimal, de t + "." + cuerpo con el secreto que se muestra al crear la automatización. Comparala con v1 y rechazá un t de más de cinco minutos. El ejemplo en JavaScript está en la versión en inglés de esta página.
Entrega
Respondé con un 2xx en menos de 8 segundos. Cualquier otra cosa se reintenta hasta 5 veces en una hora, con el mismo id. Después de 15 intentos fallidos seguidos la automatización se desactiva sola y la app lo avisa. No se siguen redirecciones, y la dirección tiene que ser pública: las redes privadas se rechazan. Las últimas 50 entregas quedan en la app, con estado, código de respuesta y duración.
Direcciones de entrada
Una dirección como https://sync.sharpmd.app/in/mdi_…. Quien la tiene puede agregar a esa nota y nada más. Se muestra una vez, y la podés cambiar cuando quieras.
curl -X POST https://sync.sharpmd.app/in/mdi_TU_SECRETO \
-H "Content-Type: application/json" \
-d '{"text": "Pedido nuevo de Ana, $ 120"}'
text/plain: el cuerpo es el texto.- JSON con
text(ytitle, para el nombre de una nota nueva). Cualquier otro JSON queda como una tabla de campo y valor. - Formularios (
application/x-www-form-urlencodedomultipart/form-data): los campos quedan como lista. Los archivos se saltean. - Una plantilla por dirección:
- {{date}} {{text}}. También acepta{{time}},{{title}}y cualquier campo por su nombre. - En un tablero: cada pedido es una tarjeta en la columna que elegiste, y los demás campos son sus atributos.
Hasta 64 KB y 60 pedidos por minuto. La respuesta es {"ok": true}.
API
Creá un token en Ajustes > API y automatizaciones, en Tokens de la API. Los mismos tokens conectan tu IA. Uno limitado a una carpeta solo llega a esa carpeta. Va en cada pedido:
curl https://sync.sharpmd.app/api/v1/notes?folder=tienda \
-H "Authorization: Bearer mdt_TU_TOKEN"
Las respuestas son {"ok": true, "data": …} o {"ok": false, "error": {"code", "message"}}. 120 pedidos por minuto por token. Cada escritura devuelve la url que abre la nota en la app. La tabla de pedidos está en la versión en inglés, y la descripción completa en el archivo OpenAPI.
curl -X POST https://sync.sharpmd.app/api/v1/boards/cards/c8k2m9xq/move \
-H "Authorization: Bearer mdt_TU_TOKEN" -H "Content-Type: application/json" \
-d '{"path": "tienda/tablero.md", "column": "Hecho"}'
Mandá rev para escribir solo si la nota sigue en esa revisión: si cambió, la respuesta es 409 rev_conflict y no se escribe nada. Las notas del equipo están bajo @team/; con un token del equipo, el espacio del equipo es la raíz. Quien solo lee en un equipo tampoco escribe por la API. Las carpetas protegidas quedan fuera de alcance mientras están bloqueadas.
Las tarjetas en Markdown
Un tablero es un bloque de código kanban. Cada título es una columna y cada tarea una tarjeta. Los atributos van entre llaves al final de la tarjeta; id, created y updated los escribe SharpMD.
```kanban
{show=vence,responsable prioridad=baja|media|alta}
## Por hacer
- [ ] Arreglar el pago {vence=2026-10-20 responsable="Ana Paz" id=c8k2m9xq created=2026-10-07T14:03:11Z}
## Hecho
```
Make, n8n, Activepieces, Zapier, Slack
Slack
- En Slack, agregá un webhook entrante a un canal y copiá su dirección.
- En SharpMD: Ajustes > API y automatizaciones > Nueva automatización. Elegí dónde mirar y qué eventos.
- Elegí Slack, pegá la dirección, Crear, y después Enviar una prueba.
Al canal le llegan líneas como: Tarjeta "Arreglar el pago" pasó de Por hacer a Hecho en tienda/tablero.md. Discord funciona igual con la dirección de su webhook.
Make
- Empezá un escenario con Webhooks > Custom webhook y copiá su dirección.
- En SharpMD, creá una automatización con el formato "Make, n8n, Zapier u otro" y esa dirección. Mandá una prueba para que Make conozca los campos.
- Para escribir de vuelta, sumá un módulo HTTP > Make a request con la cabecera
Authorization: Bearer mdt_…, o mandá a una dirección de entrada.
n8n
- Agregá un nodo Webhook (POST) y copiá su URL de producción en una automatización de SharpMD.
- Para actuar sobre SharpMD, un nodo HTTP Request con Header Auth: nombre
Authorization, valorBearer mdt_…. - Los ejemplos curl de esta página se pegan con Import cURL.
Activepieces
- Usá el disparador Webhook y pegá su URL en una automatización de SharpMD.
- Usá la pieza HTTP (Send HTTP request) con la cabecera
Authorizationpara llamar a la API.
Zapier
- Disparador: Webhooks by Zapier > Catch Hook. Pegá su dirección en una automatización de SharpMD y mandá una prueba.
- Acción: Webhooks by Zapier > POST a una dirección de entrada, o un Custom Request a la API con la cabecera
Authorization.
Servidor propio
El servidor es de código abierto. Cambiá https://sync.sharpmd.app por tu dirección. Las variables están en el README del servidor, y en Privacidad está qué se manda y qué se guarda.
TermsTérminosPrivacyPrivacidadRefundsReembolsosAcceptable useUso aceptableCopyrightDerechos de autorSupportAyuda