markdown.bz

Markdown sharing guides / API, curl and GitHub Actions

How to publish Markdown with the API, curl and GitHub Actions

A single POST of Markdown text to the publishing API returns a share URL that can be viewed in a browser. No account or API key is required. If you use it repeatedly, stay within the input limits and the limit on how many shares can be created, and save the URL returned on success as the result of your job.

1. Publish a Markdown file with curl

curl --fail-with-body --request POST \
  'https://markdown.bz/api/v1/documents' \
  --header 'Content-Type: text/markdown; charset=utf-8' \
  --data-binary '@README.md'

This is the shortest example, sending the file as Content-Type: text/markdown. The title is the title in the frontmatter (or the first Markdown heading if there is none), with no expiry and no password. On success, 201 Created and JSON are returned.

2. Set the expiry and title with JSON

curl --fail-with-body --request POST \
  'https://markdown.bz/api/v1/documents' \
  --header 'Content-Type: application/json' \
  --data '{
    "markdown": "# CI report\n\nAll tests passed.",
    "title": "CI report",
    "expiryDays": 7
  }'

expiryDays is null (no expiry) or 3, 7, 30, 60 or 100. If omitted, there is no expiry. You can also set a viewing password, but do not leave it in plain text in your shell history or CI logs; use environment variables or Actions secrets.

3. Use the official CLI

The public repository 743starlight/markdownbz-examples contains a Node.js CLI with no external dependencies, curl and Node samples, and tests, under the MIT license.

git clone https://github.com/743starlight/markdownbz-examples.git
cd markdownbz-examples
node bin/markdownbz.mjs README.md

# Publish for 7 days
node bin/markdownbz.mjs report.md --expiry-days 7

On success, the CLI prints only the share URL to standard output, so you can capture it in a shell variable.

public_url="$(node bin/markdownbz.mjs report.md --expiry-days 7)"
printf '%s\n' "$public_url"

4. Publish from GitHub Actions

permissions:
  contents: read

steps:
  - uses: actions/checkout@v7
  - id: publish
    uses: 743starlight/markdownbz-examples@v1
    with:
      markdown-path: report.md
      expiry-days: '7'
  - run: echo "${{ steps.publish.outputs.public-url }}"

The action's public-url output is the share URL. Publishing automatically on every push piles up unneeded documents, so limit it to when it is actually needed, such as jobs whose output is final, releases or manual runs.

5. Use the share URL from the response

{
  "slug": "AbCdEf1234567890",
  "publicUrl": "https://markdown.bz/d/AbCdEf1234567890",
  "expiresAt": null,
  "deleteToken": "32-character delete token"
}
  • publicUrl: the share URL to give to people
  • slug: the identifier of the shared document
  • expiresAt: null with no expiry, or an ISO 8601 date-time when an expiry is set
  • deleteToken: a token for deleting the share later. It is only returned in this response

To pass the raw Markdown to AI, add /raw to the end of the share URL. For details, see How to pass a Markdown share URL to AI.

6. Delete shares you no longer need

curl --fail-with-body --request DELETE \
  'https://markdown.bz/api/v1/documents/AbCdEf1234567890' \
  --header "Authorization: Bearer $MARKDOWNBZ_DELETE_TOKEN"

The deleteToken returned at creation proves the request comes from you, and 204 No Content is returned on success. Use it when you have published the wrong content, or to remove the old URL after recreating a document. Anyone who knows the token can delete the share, so do not hand it over with the share URL; keep it somewhere safe, such as your CI secrets.

7. What to check when a request fails

HTTPWhat to check
400The JSON, and the expiry, title and password values
401 / 403The Authorization: Bearer header on the delete request, and the deleteToken returned at creation
413Whether the Markdown is within 1MB and the JSON request is not too large
415Whether the content type is application/json or text/markdown
429Wait for Retry-After, and send fewer concurrent or back-to-back requests
500 / 503Wait a while, then retry a limited number of times

Resending does not overwrite the same document; it creates a new share URL. If your process retries after a timeout, keep in mind that duplicate URLs may be created. The full specification is in the API docs and OpenAPI 3.1.

Last reviewed: / Reviewed by the markdown.bz team