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 7On 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 peopleslug: the identifier of the shared documentexpiresAt:nullwith no expiry, or an ISO 8601 date-time when an expiry is setdeleteToken: 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
| HTTP | What to check |
|---|---|
| 400 | The JSON, and the expiry, title and password values |
| 401 / 403 | The Authorization: Bearer header on the delete request, and the deleteToken returned at creation |
| 413 | Whether the Markdown is within 1MB and the JSON request is not too large |
| 415 | Whether the content type is application/json or text/markdown |
| 429 | Wait for Retry-After, and send fewer concurrent or back-to-back requests |
| 500 / 503 | Wait 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