SharpMD

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

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.

EventWhendata
note.createdA note is createdrev, size, updated
note.updatedA note changes. Saves in a row arrive as one eventrev, size, updated
note.movedA note is moved or renamedfrom, to
note.deletedA note goes to the trashtrash
note.restoredA note comes back from the trashrev, size
comment.createdSomeone leaves a comment for the AIcomment: id, text, quote
comment.resolvedA comment is marked as donecomment: id, reply
card.createdA card is added to a boardcard, board
card.movedA card changes column (its status)card, from, to
card.updatedThe title or an attribute of a card changescard, changes: old and new value per key
card.doneA card becomes done. Moving it into the done column sends card.moved and then this onecard
card.deletedA card is removedcard

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"}'

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.

RequestWhat it does
GET /api/v1/notesList notes. folder, limit, cursor
GET /api/v1/note?path=Read a note: text and rev
PUT /api/v1/noteCreate or replace. {path, text, rev?}
POST /api/v1/note/appendAdd at the end. {path, text}
POST /api/v1/note/moveMove 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}/resolveComments for the AI
GET /api/v1/boards?path=The boards of a note: columns and cards with their attributes
POST /api/v1/boards/cardsCreate a card. {path, column, title, attrs?}
POST /api/v1/boards/cards/{id}/moveMove it. {path, column}
POST /api/v1/boards/cards/{id}/doneTick 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

  1. In Slack, add an incoming webhook to a channel and copy its address.
  2. In SharpMD: Settings > API and automations > New automation. Pick where to watch and the events.
  3. 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

  1. Start a scenario with Webhooks > Custom webhook and copy its address.
  2. In SharpMD, create an automation with the format "Make, n8n, Zapier or other" and that address. Send a test so Make learns the fields.
  3. To write back, add an HTTP > Make a request module with the header Authorization: Bearer mdt_…, or post to an inbound address.

n8n

  1. Add a Webhook node (POST) and copy its production URL into a SharpMD automation.
  2. To act on SharpMD, add an HTTP Request node with Header Auth: name Authorization, value Bearer mdt_….
  3. The curl examples on this page can be pasted with Import cURL.

Activepieces

  1. Use the Webhook trigger and paste its live URL into a SharpMD automation.
  2. Use the HTTP piece (Send HTTP request) with the Authorization header to call the API.

Zapier

  1. Trigger: Webhooks by Zapier > Catch Hook. Paste its address into a SharpMD automation and send a test.
  2. Action: Webhooks by Zapier > POST to an inbound address, or a Custom Request to the API with the Authorization header.

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

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.

EventoCuándodata
note.createdSe crea una notarev, size, updated
note.updatedCambia una nota. Los guardados seguidos llegan como un solo eventorev, size, updated
note.movedSe mueve o se renombrafrom, to
note.deletedVa a la papeleratrash
note.restoredVuelve de la papelerarev, size
comment.createdAlguien deja un comentario para la IAcomment: id, text, quote
comment.resolvedUn comentario queda resueltocomment: id, reply
card.createdSe agrega una tarjeta a un tablerocard, board
card.movedUna tarjeta cambia de columna (su estado)card, from, to
card.updatedCambia el título o un atributocard, changes: valor anterior y nuevo por clave
card.doneUna tarjeta queda hecha. Moverla a la columna de hechas manda card.moved y después estecard
card.deletedSe quita una tarjetacard

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"}'

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

  1. En Slack, agregá un webhook entrante a un canal y copiá su dirección.
  2. En SharpMD: Ajustes > API y automatizaciones > Nueva automatización. Elegí dónde mirar y qué eventos.
  3. 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

  1. Empezá un escenario con Webhooks > Custom webhook y copiá su dirección.
  2. 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.
  3. 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

  1. Agregá un nodo Webhook (POST) y copiá su URL de producción en una automatización de SharpMD.
  2. Para actuar sobre SharpMD, un nodo HTTP Request con Header Auth: nombre Authorization, valor Bearer mdt_….
  3. Los ejemplos curl de esta página se pegan con Import cURL.

Activepieces

  1. Usá el disparador Webhook y pegá su URL en una automatización de SharpMD.
  2. Usá la pieza HTTP (Send HTTP request) con la cabecera Authorization para llamar a la API.

Zapier

  1. Disparador: Webhooks by Zapier > Catch Hook. Pegá su dirección en una automatización de SharpMD y mandá una prueba.
  2. 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.