Action

Send Draft To Readwise

Posted by FlohGro, Last update 3 days ago

created by @FlohGro / more on my Blog

Send to Readwise Reader

Send the current draft’s Markdown content to your Readwise Reader inbox.

Configuration

The action uses Drafts’ built-in Credential system to store your Readwise access token. You’ll be prompted on first run. Get your token at readwise.io/access_token.

Usage

  1. Open or create a draft with Markdown content.
  2. Run the action.
  3. A prompt lets you review and edit the title and tags before sending.
  4. Tap Send to push it to Readwise Reader.

The first line of the draft is used as the document title (stripping any leading #). The rest of the content is converted to HTML and sent as the document body.

If you find this useful and want to support me you can donate or buy me a coffee

Steps

  • script

    // SendToReadwise.js
    // Sends the current draft's Markdown content to Readwise Reader
    // as a document in the inbox. Uses the Readwise Reader API v3.
    //
    // Configuration (override):
    //   READWISE_CATEGORY — document category (default: "article")
    //   READWISE_TAGS     — array of tags to apply (default: ["drafts"])
    //   READWISE_LOCATION — "new" (inbox), "later", "archive" (default: "new")
    //
    // Token stored via Drafts' Credential system.
    // Get yours at: https://readwise.io/access_token
    
    if (typeof READWISE_CATEGORY === "undefined") var READWISE_CATEGORY = "article";
    if (typeof READWISE_TAGS === "undefined") var READWISE_TAGS = [];
    if (typeof READWISE_LOCATION === "undefined") var READWISE_LOCATION = "new";
    
    function sendToReadwise() {
      var content = draft.content;
      if (!content || content.trim().length === 0) {
        app.displayWarningMessage("Draft is empty.");
        return;
      }
    
      // --- Get API token via Credential system ---
      var cred = Credential.create("Readwise Reader", "Enter your Readwise access token.\nGet it at readwise.io/access_token");
      cred.addPasswordField("token", "Access Token");
      if (!cred.authorize()) {
        app.displayErrorMessage("Readwise token not provided.");
        context.fail();
        return;
      }
      var token = cred.getValue("token");
      if (!token || token.trim().length === 0) {
        app.displayErrorMessage("Readwise token is empty.");
        context.fail();
        return;
      }
    
      // --- Extract title from first line and body without it ---
      var lines = content.split("\n");
      var title = lines[0].replace(/^#+\s*/, "").trim();
      if (title.length === 0) {
        title = "Draft from " + new Date().toISOString().substring(0, 10);
      }
      // Remove the title line from the body to avoid duplication in Readwise
      var bodyLines = lines.slice(1);
      // Also strip leading blank lines after the title
      while (bodyLines.length > 0 && bodyLines[0].trim() === "") {
        bodyLines.shift();
      }
      var bodyMd = bodyLines.join("\n");
    
      // --- Unique URL (Readwise deduplicates by URL) ---
      var fakeUrl = "https://drafts.app/d/" + draft.uuid + "#" + Date.now();
    
      // --- Prompt user to review before sending ---
      var p = Prompt.create();
      p.title = "Send to Readwise Reader";
      p.message = "Review before sending:";
      p.addTextField("title", "Title", title);
      p.addTextField("tags", "Tags (comma-separated)", READWISE_TAGS.join(", "));
      //p.addTextField("summary", "Summary (optional)", "");
      //p.addTextField("notes", "Notes (optional)", "");
      p.addButton("Send");
      p.addButton("Cancel");
    
      if (!p.show() || p.buttonPressed === "Cancel") {
        context.cancel();
        return;
      }
    
      var finalTitle = p.fieldValues["title"] || title;
      var tagsStr = p.fieldValues["tags"] || "";
      var finalTags = tagsStr.split(",").map(function (t) { return t.trim(); }).filter(function (t) { return t.length > 0; });
      //var summary = p.fieldValues["summary"] || null;
      //var notes = p.fieldValues["notes"] || null;
    
      // --- Convert body Markdown to HTML via Drafts built-in ---
      var md = new GitHubMarkdown();
      var htmlContent = "<div>" + md.render(bodyMd) + "</div>";
    
      // --- Build request payload ---
      var payload = {
        "url": fakeUrl,
        "title": finalTitle,
        "html": htmlContent,
        //"category": READWISE_CATEGORY,
        "location": READWISE_LOCATION,
        "saved_using": "Drafts App"
      };
    
      if (finalTags.length > 0) {
        payload["tags"] = finalTags;
      }
      //if (summary && summary.trim().length > 0) {
      //  payload["summary"] = summary.trim();
      //}
      //if (notes && notes.trim().length > 0) {
      //  payload["notes"] = notes.trim();
      //}
    
      // --- Send to Readwise Reader API ---
      var http = HTTP.create();
      var response = http.request({
        "url": "https://readwise.io/api/v3/save/",
        "method": "POST",
        "encoding": "json",
        "data": payload,
        "headers": {
          "Authorization": "Token " + token,
          "Content-Type": "application/json"
        }
      });
    
      if (response.success) {
        console.log("Readwise: HTTP " + response.statusCode + " — " + (response.responseText || ""));
        app.displaySuccessMessage("Sent to Readwise Reader!");
      } else {
        console.log("Readwise error: HTTP " + response.statusCode);
        console.log("Response: " + (response.responseText || "(empty)"));
        console.log("Payload URL: " + payload["url"]);
        console.log("Title: " + payload["title"]);
        console.log("HTML length: " + htmlContent.length);
        var errorMsg = "Readwise failed (HTTP " + response.statusCode + ")";
        try {
          var errData = JSON.parse(response.responseText);
          if (errData.detail) errorMsg += ": " + errData.detail;
        } catch (e) { }
        app.displayErrorMessage(errorMsg);
        context.fail();
      }
    }
    
    sendToReadwise();
    

Options

  • After Success Default
    Notification None
    Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.